Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 3.27.0

* Adds support for loading resources with custom URL schemes via
`WebKitWebViewControllerCreationParams.urlSchemeHandlers`, backed by the
native `WKURLSchemeHandler` API.

## 3.26.0

* Adds new method for accessing a native `WKWebView` from a `FlutterPluginRegistrar`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ import XCTest
@testable import webview_flutter_wkwebview

class ErrorProxyAPITests: XCTestCase {
func testPigeonDefaultConstructor() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiNSError(registrar)

let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(
pigeonApi: api, code: 42, domain: "domain",
userInfo: [NSLocalizedDescriptionKey: "description"])

XCTAssertEqual(instance?.code, 42)
XCTAssertEqual(instance?.domain, "domain")
XCTAssertEqual(instance?.localizedDescription, "description")
}

func testCode() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiNSError(registrar)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ import XCTest
@testable import webview_flutter_wkwebview

class HTTPURLResponseProxyAPITests: XCTestCase {
func testPigeonDefaultConstructor() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiHTTPURLResponse(registrar)

let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(
pigeonApi: api, statusCode: 404, url: "http://google.com", httpVersion: nil,
headerFields: ["Content-Type": "image/png"])

XCTAssertEqual(instance?.url, URL(string: "http://google.com"))
XCTAssertEqual(instance?.statusCode, 404)
XCTAssertEqual(instance?.value(forHTTPHeaderField: "Content-Type"), "image/png")
}

func testPigeonDefaultConstructorWithInvalidUrl() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiHTTPURLResponse(registrar)

XCTAssertThrowsError(
try api.pigeonDelegate.pigeonDefaultConstructor(
pigeonApi: api, statusCode: 200, url: "", httpVersion: nil, headerFields: nil))
}

func testStatusCode() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiHTTPURLResponse(registrar)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import XCTest

@testable import webview_flutter_wkwebview

class URLResponseProxyAPITests: XCTestCase {
func testPigeonDefaultConstructor() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiURLResponse(registrar)

let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(
pigeonApi: api, url: "test-scheme://host/resource", mimeType: "image/png",
expectedContentLength: 3, textEncodingName: nil)

XCTAssertEqual(instance?.url, URL(string: "test-scheme://host/resource"))
XCTAssertEqual(instance?.mimeType, "image/png")
XCTAssertEqual(instance?.expectedContentLength, 3)
XCTAssertNil(instance?.textEncodingName)
}

func testPigeonDefaultConstructorWithInvalidUrl() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiURLResponse(registrar)

XCTAssertThrowsError(
try api.pigeonDelegate.pigeonDefaultConstructor(
pigeonApi: api, url: "", mimeType: nil, expectedContentLength: 0,
textEncodingName: nil))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import WebKit
import XCTest

@testable import webview_flutter_wkwebview

class URLSchemeHandlerProxyAPITests: XCTestCase {
func testPigeonDefaultConstructor() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeHandler(registrar)

let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api)
XCTAssertNotNil(instance)
}

@MainActor func testStartUrlSchemeTask() {
let api = TestURLSchemeHandlerApi()
let registrar = TestProxyApiRegistrar()
let instance = URLSchemeHandlerImpl(api: api, registrar: registrar)
let webView = WKWebView()
let task = TestURLSchemeTask()

instance.webView(webView, start: task)

XCTAssertEqual(api.startUrlSchemeTaskArgs, [webView, task])
XCTAssertFalse(URLSchemeTaskState.isStopped(task))
}

@MainActor func testStopUrlSchemeTask() {
let api = TestURLSchemeHandlerApi()
let registrar = TestProxyApiRegistrar()
let instance = URLSchemeHandlerImpl(api: api, registrar: registrar)
let webView = WKWebView()
let task = TestURLSchemeTask()

instance.webView(webView, stop: task)

XCTAssertEqual(api.stopUrlSchemeTaskArgs, [webView, task])
XCTAssertTrue(URLSchemeTaskState.isStopped(task))
}
}

class TestURLSchemeHandlerApi: PigeonApiProtocolWKURLSchemeHandler {
var startUrlSchemeTaskArgs: [AnyHashable?]? = nil
var stopUrlSchemeTaskArgs: [AnyHashable?]? = nil

func startUrlSchemeTask(
pigeonInstance pigeonInstanceArg: WKURLSchemeHandler, webView webViewArg: WKWebView,
urlSchemeTask urlSchemeTaskArg: WKURLSchemeTask,
completion: @escaping (Result<Void, PigeonError>) -> Void
) {
startUrlSchemeTaskArgs = [webViewArg, urlSchemeTaskArg as? NSObject]
}

func stopUrlSchemeTask(
pigeonInstance pigeonInstanceArg: WKURLSchemeHandler, webView webViewArg: WKWebView,
urlSchemeTask urlSchemeTaskArg: WKURLSchemeTask,
completion: @escaping (Result<Void, PigeonError>) -> Void
) {
stopUrlSchemeTaskArgs = [webViewArg, urlSchemeTaskArg as? NSObject]
}
}

class TestURLSchemeTask: NSObject, WKURLSchemeTask {
var request: URLRequest = URLRequest(url: URL(string: "test-scheme://host/resource")!)

var didReceiveResponseArg: URLResponse? = nil
var didReceiveDataArg: Data? = nil
var didFinishCalled = false
var didFailWithErrorArg: (any Error)? = nil

func didReceive(_ response: URLResponse) {
didReceiveResponseArg = response
}

func didReceive(_ data: Data) {
didReceiveDataArg = data
}

func didFinish() {
didFinishCalled = true
}

func didFailWithError(_ error: any Error) {
didFailWithErrorArg = error
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import WebKit
import XCTest

@testable import webview_flutter_wkwebview

#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#endif

class URLSchemeTaskProxyAPITests: XCTestCase {
func testRequest() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeTask(registrar)

let instance = TestURLSchemeTask()
let value = try? api.pigeonDelegate.request(pigeonApi: api, pigeonInstance: instance)

XCTAssertEqual(value?.value, instance.request)
}

func testDidReceiveResponse() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeTask(registrar)

let instance = TestURLSchemeTask()
let response = URLResponse(
url: URL(string: "test-scheme://host/resource")!, mimeType: "image/png",
expectedContentLength: 3, textEncodingName: nil)
try? api.pigeonDelegate.didReceiveResponse(
pigeonApi: api, pigeonInstance: instance, response: response)

XCTAssertEqual(instance.didReceiveResponseArg, response)
}

func testDidReceiveData() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeTask(registrar)

let instance = TestURLSchemeTask()
let data = Data([1, 2, 3])
try? api.pigeonDelegate.didReceiveData(
pigeonApi: api, pigeonInstance: instance, data: FlutterStandardTypedData(bytes: data))

XCTAssertEqual(instance.didReceiveDataArg, data)
}

func testDidFinish() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeTask(registrar)

let instance = TestURLSchemeTask()
try? api.pigeonDelegate.didFinish(pigeonApi: api, pigeonInstance: instance)

XCTAssertTrue(instance.didFinishCalled)
}

func testDidFailWithError() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeTask(registrar)

let instance = TestURLSchemeTask()
let error = NSError(domain: "domain", code: 42)
try? api.pigeonDelegate.didFailWithError(
pigeonApi: api, pigeonInstance: instance, error: error)

XCTAssertEqual(instance.didFailWithErrorArg as? NSError, error)
}

func testCallsAreNoOpsAfterTaskWasStopped() {
let registrar = TestProxyApiRegistrar()
let api = registrar.apiDelegate.pigeonApiWKURLSchemeTask(registrar)

let instance = TestURLSchemeTask()
URLSchemeTaskState.markStopped(instance)

let response = URLResponse(
url: URL(string: "test-scheme://host/resource")!, mimeType: nil,
expectedContentLength: 0, textEncodingName: nil)
try? api.pigeonDelegate.didReceiveResponse(
pigeonApi: api, pigeonInstance: instance, response: response)
try? api.pigeonDelegate.didReceiveData(
pigeonApi: api, pigeonInstance: instance,
data: FlutterStandardTypedData(bytes: Data([1])))
try? api.pigeonDelegate.didFinish(pigeonApi: api, pigeonInstance: instance)
try? api.pigeonDelegate.didFailWithError(
pigeonApi: api, pigeonInstance: instance, error: NSError(domain: "", code: 0))

XCTAssertNil(instance.didReceiveResponseArg)
XCTAssertNil(instance.didReceiveDataArg)
XCTAssertFalse(instance.didFinishCalled)
XCTAssertNil(instance.didFailWithErrorArg)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ import Foundation
/// This class may handle instantiating native object instances that are attached to a Dart instance
/// or handle method calls on the associated native class or an instance of that class.
class ErrorProxyAPIDelegate: PigeonApiDelegateNSError {
func pigeonDefaultConstructor(
pigeonApi: PigeonApiNSError, code: Int64, domain: String, userInfo: [String: Any?]
) throws -> NSError {
return NSError(
domain: domain, code: Int(code), userInfo: userInfo.compactMapValues { $0 })
}

func code(pigeonApi: PigeonApiNSError, pigeonInstance: NSError) throws -> Int64 {
return Int64(pigeonInstance.code)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,29 @@ import Foundation
/// This class may handle instantiating native object instances that are attached to a Dart instance
/// or handle method calls on the associated native class or an instance of that class.
class HTTPURLResponseProxyAPIDelegate: PigeonApiDelegateHTTPURLResponse {
func pigeonDefaultConstructor(
pigeonApi: PigeonApiHTTPURLResponse, statusCode: Int64, url: String, httpVersion: String?,
headerFields: [String: String]?
) throws -> HTTPURLResponse {
let registrar = pigeonApi.pigeonRegistrar as! ProxyAPIRegistrar
guard let parsedUrl = URL(string: url) else {
throw registrar.createConstructorNullError(type: URL.self, parameters: ["string": url])
}
guard
let response = HTTPURLResponse(
url: parsedUrl, statusCode: Int(statusCode), httpVersion: httpVersion,
headerFields: headerFields)
else {
throw registrar.createConstructorNullError(
type: HTTPURLResponse.self,
parameters: [
"url": url, "statusCode": statusCode, "httpVersion": httpVersion,
"headerFields": headerFields,
])
}
return response
}

func statusCode(pigeonApi: PigeonApiHTTPURLResponse, pigeonInstance: HTTPURLResponse) throws
-> Int64
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ class ProxyAPIDelegate: WebKitLibraryPigeonProxyApiDelegate {
pigeonRegistrar: registrar, delegate: HTTPURLResponseProxyAPIDelegate())
}

func pigeonApiURLResponse(_ registrar: WebKitLibraryPigeonProxyApiRegistrar)
-> PigeonApiURLResponse
{
return PigeonApiURLResponse(
pigeonRegistrar: registrar, delegate: URLResponseProxyAPIDelegate())
}

func pigeonApiWKURLSchemeHandler(_ registrar: WebKitLibraryPigeonProxyApiRegistrar)
-> PigeonApiWKURLSchemeHandler
{
return PigeonApiWKURLSchemeHandler(
pigeonRegistrar: registrar, delegate: URLSchemeHandlerProxyAPIDelegate())
}

func pigeonApiWKURLSchemeTask(_ registrar: WebKitLibraryPigeonProxyApiRegistrar)
-> PigeonApiWKURLSchemeTask
{
return PigeonApiWKURLSchemeTask(
pigeonRegistrar: registrar, delegate: URLSchemeTaskProxyAPIDelegate())
}

func pigeonApiWKUserScript(_ registrar: WebKitLibraryPigeonProxyApiRegistrar)
-> PigeonApiWKUserScript
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import Foundation

/// ProxyApi implementation for `URLResponse`.
///
/// This class may handle instantiating native object instances that are attached to a Dart instance
/// or handle method calls on the associated native class or an instance of that class.
class URLResponseProxyAPIDelegate: PigeonApiDelegateURLResponse {
func pigeonDefaultConstructor(
pigeonApi: PigeonApiURLResponse, url: String, mimeType: String?, expectedContentLength: Int64,
textEncodingName: String?
) throws -> URLResponse {
guard let parsedUrl = URL(string: url) else {
throw (pigeonApi.pigeonRegistrar as! ProxyAPIRegistrar).createConstructorNullError(
type: URL.self, parameters: ["string": url])
}
return URLResponse(
url: parsedUrl, mimeType: mimeType, expectedContentLength: Int(expectedContentLength),
textEncodingName: textEncodingName)
}
}
Loading