Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
gwdp committed Apr 5, 2022
2 parents 2acd05f + 3bb288e commit 63a6e1b
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 14 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -80,6 +80,7 @@ Made possible by the Capacitor community. 💖
<!-- CONTRIBUTORS:START -->

<p align="center">
<a href="https://github.com/Steven0351"><img src="https://github.com/Steven0351.png?size=100" width="50" height="50" /></a>
<a href="https://github.com/samydoesit"><img src="https://github.com/samydoesit.png?size=100" width="50" height="50" /></a>
<a href="https://github.com/hermitdemschoenenleben"><img src="https://github.com/hermitdemschoenenleben.png?size=100" width="50" height="50" /></a>
<a href="https://github.com/carldea"><img src="https://github.com/carldea.png?size=100" width="50" height="50" /></a>
Expand Down
18 changes: 18 additions & 0 deletions android/capacitor/src/main/java/com/getcapacitor/Bridge.java
Expand Up @@ -131,6 +131,9 @@ public class Bridge {
// A list of listeners that trigger when webView events occur
private List<WebViewListener> webViewListeners = new ArrayList<>();

// An interface to manipulate route resolving
private RouteProcessor routeProcessor;

/**
* Create the Bridge with a reference to the main {@link Activity} for the
* app, and a reference to the {@link WebView} our app will use.
Expand Down Expand Up @@ -1201,6 +1204,14 @@ void setWebViewListeners(List<WebViewListener> webViewListeners) {
this.webViewListeners = webViewListeners;
}

RouteProcessor getRouteProcessor() {
return routeProcessor;
}

void setRouteProcessor(RouteProcessor routeProcessor) {
this.routeProcessor = routeProcessor;
}

/**
* Add a listener that the WebViewClient can trigger on certain events.
* @param webViewListener A {@link WebViewListener} to add.
Expand All @@ -1224,6 +1235,7 @@ public static class Builder {
private List<Class<? extends Plugin>> plugins = new ArrayList<>();
private AppCompatActivity activity;
private Fragment fragment;
private RouteProcessor routeProcessor;
private final List<WebViewListener> webViewListeners = new ArrayList<>();

public Builder(AppCompatActivity activity) {
Expand Down Expand Up @@ -1276,6 +1288,11 @@ public Builder addWebViewListeners(List<WebViewListener> webViewListeners) {
return this;
}

public Builder setRouteProcessor(RouteProcessor routeProcessor) {
this.routeProcessor = routeProcessor;
return this;
}

public Bridge create() {
// Cordova initialization
ConfigXmlParser parser = new ConfigXmlParser();
Expand All @@ -1299,6 +1316,7 @@ public Bridge create() {
Bridge bridge = new Bridge(activity, fragment, webView, plugins, cordovaInterface, pluginManager, preferences, config);
bridge.setCordovaWebView(mockWebView);
bridge.setWebViewListeners(webViewListeners);
bridge.setRouteProcessor(routeProcessor);

if (instanceState != null) {
bridge.restoreInstanceState(instanceState);
Expand Down
Expand Up @@ -12,11 +12,11 @@ public class BridgeActivity extends AppCompatActivity {

protected Bridge bridge;
protected boolean keepRunning = true;
private CapConfig config;
protected CapConfig config;

private int activityDepth = 0;
private List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
private final Bridge.Builder bridgeBuilder = new Bridge.Builder(this);
protected int activityDepth = 0;
protected List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
protected final Bridge.Builder bridgeBuilder = new Bridge.Builder(this);

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -66,7 +66,7 @@ protected void load(Bundle savedInstanceState) {
this.load();
}

private void load() {
protected void load() {
Logger.debug("Starting BridgeActivity");

bridge = bridgeBuilder.addPlugins(initialPlugins).setConfig(config).create();
Expand Down
@@ -0,0 +1,8 @@
package com.getcapacitor;

/**
* An interface used in the processing of routes
*/
public interface RouteProcessor {
String process(String path);
}
Expand Up @@ -24,7 +24,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -256,6 +255,10 @@ private WebResourceResponse handleLocalRequest(WebResourceRequest request, PathH
InputStream responseStream;
try {
String startPath = this.basePath + "/index.html";
if (bridge.getRouteProcessor() != null) {
startPath = this.basePath + bridge.getRouteProcessor().process("/index.html");
}

if (isAsset) {
responseStream = protocolHandler.openAsset(startPath);
} else {
Expand Down Expand Up @@ -467,6 +470,13 @@ private void createHostingDetails() {
public InputStream handle(Uri url) {
InputStream stream = null;
String path = url.getPath();

// Pass path to routeProcessor if present
RouteProcessor routeProcessor = bridge.getRouteProcessor();
if (routeProcessor != null) {
path = bridge.getRouteProcessor().process(path);
}

try {
if (path.startsWith(capacitorContentStart)) {
stream = protocolHandler.openContentUrl(url);
Expand Down
8 changes: 8 additions & 0 deletions ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
Expand Up @@ -80,6 +80,8 @@
62FABD1A25AE5C01007B3814 /* Array+Capacitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FABD1925AE5C01007B3814 /* Array+Capacitor.swift */; };
62FABD2325AE60BA007B3814 /* BridgedTypesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FABD2225AE60BA007B3814 /* BridgedTypesTests.m */; };
62FABD2B25AE6182007B3814 /* BridgedTypesHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */; };
A71289E627F380A500DADDF3 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71289E527F380A500DADDF3 /* Router.swift */; };
A71289EB27F380FD00DADDF3 /* RouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71289EA27F380FD00DADDF3 /* RouterTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -217,6 +219,8 @@
62FABD1925AE5C01007B3814 /* Array+Capacitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Capacitor.swift"; sourceTree = "<group>"; };
62FABD2225AE60BA007B3814 /* BridgedTypesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BridgedTypesTests.m; sourceTree = "<group>"; };
62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BridgedTypesHelper.swift; sourceTree = "<group>"; };
A71289E527F380A500DADDF3 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; };
A71289EA27F380FD00DADDF3 /* RouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -292,6 +296,7 @@
621ECCCD254204C400D3D615 /* CapacitorTests-Bridging-Header.h */,
62E79C712638B23300414164 /* JSExportTests.swift */,
62959BBD2526510200A3D7F1 /* Info.plist */,
A71289EA27F380FD00DADDF3 /* RouterTests.swift */,
);
path = CapacitorTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -349,6 +354,7 @@
373A69C0255C9360000A6F44 /* NotificationHandlerProtocol.swift */,
373A69F1255C95D0000A6F44 /* NotificationRouter.swift */,
62E79C562638AF7500414164 /* assets */,
A71289E527F380A500DADDF3 /* Router.swift */,
);
path = Capacitor;
sourceTree = "<group>";
Expand Down Expand Up @@ -580,6 +586,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A71289E627F380A500DADDF3 /* Router.swift in Sources */,
62959B362524DA7800A3D7F1 /* CAPBridgeViewController.swift in Sources */,
621ECCB72542045900D3D615 /* CAPBridgedJSTypes.m in Sources */,
62959B402524DA7800A3D7F1 /* TmpViewController.swift in Sources */,
Expand Down Expand Up @@ -634,6 +641,7 @@
62A91C3425535F5700861508 /* ConfigurationTests.swift in Sources */,
62FABD2325AE60BA007B3814 /* BridgedTypesTests.m in Sources */,
621ECCC3254204B700D3D615 /* BridgedTypesTests.swift in Sources */,
A71289EB27F380FD00DADDF3 /* RouterTests.swift in Sources */,
6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
8 changes: 6 additions & 2 deletions ios/Capacitor/Capacitor/CAPBridgeViewController.swift
Expand Up @@ -42,7 +42,7 @@ import Cordova
setScreenOrientationDefaults()

// get the web view
let assetHandler = WebViewAssetHandler()
let assetHandler = WebViewAssetHandler(router: router())
assetHandler.setAssetPath(configuration.appLocation.path)
let delegationHandler = WebViewDelegationHandler()
prepareWebView(with: configuration, assetHandler: assetHandler, delegationHandler: delegationHandler)
Expand Down Expand Up @@ -89,7 +89,11 @@ import Cordova
}
return descriptor
}


open func router() -> Router {
return _Router()
}

/**
The WKWebViewConfiguration to use for the webview.
Expand Down
27 changes: 27 additions & 0 deletions ios/Capacitor/Capacitor/Router.swift
@@ -0,0 +1,27 @@
//
// Router.swift
// Capacitor
//
// Created by Steven Sherry on 3/29/22.
// Copyright © 2022 Drifty Co. All rights reserved.
//

import Foundation

public protocol Router {
func route(for path: String) -> String
}

// swiftlint:disable:next type_name
internal struct _Router: Router {
func route(for path: String) -> String {
let pathUrl = URL(string: path)

// if the pathUrl is null, then it is an invalid url (meaning it is empty or just plain invalid) then we want to route to /index.html
if pathUrl?.pathExtension.isEmpty ?? true {
return "/index.html"
}

return path
}
}
15 changes: 10 additions & 5 deletions ios/Capacitor/Capacitor/WebViewAssetHandler.swift
Expand Up @@ -3,8 +3,13 @@ import MobileCoreServices

@objc(CAPWebViewAssetHandler)
internal class WebViewAssetHandler: NSObject, WKURLSchemeHandler {

private let router: Router
private var basePath: String = ""

init(router: Router) {
self.router = router
super.init()
}

func setAssetPath(_ assetPath: String) {
self.basePath = assetPath
Expand All @@ -14,14 +19,14 @@ internal class WebViewAssetHandler: NSObject, WKURLSchemeHandler {
var startPath = self.basePath
let url = urlSchemeTask.request.url!
let stringToLoad = url.path


let resolvedRoute = router.route(for: stringToLoad)
if stringToLoad.starts(with: CapacitorBridge.fileStartIdentifier) {
startPath = stringToLoad.replacingOccurrences(of: CapacitorBridge.fileStartIdentifier, with: "")
} else if stringToLoad.isEmpty || url.pathExtension.isEmpty {
startPath.append("/index.html")
} else {
startPath.append(stringToLoad)
startPath.append(resolvedRoute)
}

let localUrl = URL.init(string: url.absoluteString)!
let fileUrl = URL.init(fileURLWithPath: startPath)

Expand Down
2 changes: 1 addition & 1 deletion ios/Capacitor/CapacitorTests/CapacitorTests.swift
Expand Up @@ -23,7 +23,7 @@ class CapacitorTests: XCTestCase {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
let descriptor = InstanceDescriptor.init()
bridge = MockBridge(with: InstanceConfiguration(with: descriptor, isDebug: true), delegate: MockBridgeViewController(), cordovaConfiguration: descriptor.cordovaConfiguration, assetHandler: MockAssetHandler(), delegationHandler: MockDelegationHandler())
bridge = MockBridge(with: InstanceConfiguration(with: descriptor, isDebug: true), delegate: MockBridgeViewController(), cordovaConfiguration: descriptor.cordovaConfiguration, assetHandler: MockAssetHandler(router: _Router()), delegationHandler: MockDelegationHandler())
}

override func tearDown() {
Expand Down
30 changes: 30 additions & 0 deletions ios/Capacitor/CapacitorTests/RouterTests.swift
@@ -0,0 +1,30 @@
//
// RouterTests.swift
// CapacitorTests
//
// Created by Steven Sherry on 3/29/22.
// Copyright © 2022 Drifty Co. All rights reserved.
//

import XCTest
@testable import Capacitor

class RouterTests: XCTestCase {
let router = _Router()

func testRouterReturnsIndexWhenProvidedInvalidPath() {
XCTAssertEqual(router.route(for: "/skull.💀"), "/index.html")
}

func testRouterReturnsIndexWhenProvidedEmptyPath() {
XCTAssertEqual(router.route(for: ""), "/index.html")
}

func testRouterReturnsIndexWhenProviedPathWithoutExtension() {
XCTAssertEqual(router.route(for: "/a/valid/path/no/ext"), "/index.html")
}

func testRouterReturnsPathWhenProvidedValidPath() {
XCTAssertEqual(router.route(for: "/a/valid/path.ext"), "/a/valid/path.ext")
}
}

0 comments on commit 63a6e1b

Please sign in to comment.