Repository: cordova-ios Updated Branches: refs/heads/master 7682bfeec -> dcbdb9437
CB-9883 - Remove unused iOS bridges This closes #178 Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/dcbdb943 Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/dcbdb943 Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/dcbdb943 Branch: refs/heads/master Commit: dcbdb94371fe20bc2582730a3537ab982cdeacc5 Parents: 7682bfe Author: Shazron Abdullah <shaz...@apache.org> Authored: Tue Nov 3 14:20:11 2015 -0800 Committer: Shazron Abdullah <shaz...@apache.org> Committed: Thu Nov 5 17:14:08 2015 -0800 ---------------------------------------------------------------------- .../CDVUIWebViewNavigationDelegate.m | 24 ---- CordovaLib/Classes/Public/CDVCommandQueue.h | 1 - CordovaLib/Classes/Public/CDVCommandQueue.m | 24 ---- CordovaLib/Classes/Public/CDVURLProtocol.m | 27 +--- cordova-js-src/exec.js | 122 ++++--------------- ...ging the JavaScript to Native Bridge Mode.md | 36 ------ 6 files changed, 23 insertions(+), 211 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dcbdb943/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m b/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m index b660638..e4a84ea 100644 --- a/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m +++ b/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m @@ -101,30 +101,6 @@ return NO; } - if ([[url fragment] hasPrefix:@"%01"] || [[url fragment] hasPrefix:@"%02"]) { - // Delegate is called *immediately* for hash changes. This means that any - // calls to stringByEvaluatingJavascriptFromString will occur in the middle - // of an existing (paused) call stack. This doesn't cause errors, but may - // be unexpected to callers (exec callbacks will be called before exec() even - // returns). To avoid this, we do not do any synchronous JS evals by using - // flushCommandQueueWithDelayedJs. - NSString* inlineCommands = [[url fragment] substringFromIndex:3]; - if ([inlineCommands length] == 0) { - // Reach in right away since the WebCore / Main thread are already synchronized. - [vc.commandQueue fetchCommandsFromJs]; - } else { - inlineCommands = [inlineCommands stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - [vc.commandQueue enqueueCommandBatch:inlineCommands]; - } - // Switch these for minor performance improvements, and to really live on the wild side. - // Callbacks will occur in the middle of the location.hash = ... statement! - [(CDVCommandDelegateImpl*)self.enginePlugin.commandDelegate flushCommandQueueWithDelayedJs]; - // [_commandQueue executePending]; - - // Although we return NO, the hash change does end up taking effect. - return NO; - } - /* * Give plugins the chance to handle the url */ http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dcbdb943/CordovaLib/Classes/Public/CDVCommandQueue.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/Public/CDVCommandQueue.h b/CordovaLib/Classes/Public/CDVCommandQueue.h index 3329078..cb7bd6e 100644 --- a/CordovaLib/Classes/Public/CDVCommandQueue.h +++ b/CordovaLib/Classes/Public/CDVCommandQueue.h @@ -32,7 +32,6 @@ - (void)resetRequestId; - (void)enqueueCommandBatch:(NSString*)batchJSON; -- (void)processXhrExecBridgePoke:(NSNumber*)requestId; - (void)fetchCommandsFromJs; - (void)executePending; - (BOOL)execute:(CDVInvokedUrlCommand*)command; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dcbdb943/CordovaLib/Classes/Public/CDVCommandQueue.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/Public/CDVCommandQueue.m b/CordovaLib/Classes/Public/CDVCommandQueue.m index d2f71cb..b78ed83 100644 --- a/CordovaLib/Classes/Public/CDVCommandQueue.m +++ b/CordovaLib/Classes/Public/CDVCommandQueue.m @@ -84,30 +84,6 @@ static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame. } } -- (void)processXhrExecBridgePoke:(NSNumber*)requestId -{ - NSInteger rid = [requestId integerValue]; - - // An ID of 1 is a special case because that signifies the first request of - // the page. Since resetRequestId is called from webViewDidStartLoad, and the - // JS context at the time of webViewDidStartLoad is still that of the previous - // page, it's possible for requests from the previous page to come in after this - // point. We ignore these by enforcing that ID=1 be the first ID. - if ((_lastCommandQueueFlushRequestId == 0) && (rid != 1)) { - CDV_EXEC_LOG(@"Exec: Ignoring exec request from previous page."); - return; - } - - // Use the request ID to determine if we've already flushed for this request. - // This is required only because the NSURLProtocol enqueues the same request - // multiple times. - if (rid > _lastCommandQueueFlushRequestId) { - _lastCommandQueueFlushRequestId = [requestId integerValue]; - [self fetchCommandsFromJs]; - [self executePending]; - } -} - - (void)fetchCommandsFromJs { __weak CDVCommandQueue* weakSelf = self; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dcbdb943/CordovaLib/Classes/Public/CDVURLProtocol.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/Public/CDVURLProtocol.m b/CordovaLib/Classes/Public/CDVURLProtocol.m index c345060..e758086 100644 --- a/CordovaLib/Classes/Public/CDVURLProtocol.m +++ b/CordovaLib/Classes/Public/CDVURLProtocol.m @@ -97,28 +97,6 @@ static CDVViewController *viewControllerForRequest(NSURLRequest* request) if ([[theUrl absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { return YES; } else if (viewController != nil) { - if ([[theUrl path] isEqualToString:@"/!gap_exec"]) { - NSString* queuedCommandsJSON = [theRequest valueForHTTPHeaderField:@"cmds"]; - NSString* requestId = [theRequest valueForHTTPHeaderField:@"rc"]; - if (requestId == nil) { - NSLog(@"!cordova request missing rc header"); - return NO; - } - BOOL hasCmds = [queuedCommandsJSON length] > 0; - if (hasCmds) { - SEL sel = @selector(enqueueCommandBatch:); - [viewController.commandQueue performSelectorOnMainThread:sel withObject:queuedCommandsJSON waitUntilDone:NO]; - [viewController.commandQueue performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO]; - } else { - SEL sel = @selector(processXhrExecBridgePoke:); - [viewController.commandQueue performSelectorOnMainThread:sel withObject:[NSNumber numberWithInteger:[requestId integerValue]] waitUntilDone:NO]; - } - // Returning NO here would be 20% faster, but it spams WebInspector's console with failure messages. - // If JS->Native bridge speed is really important for an app, they should use the iframe bridge. - // Returning YES here causes the request to come through canInitWithRequest two more times. - // For this reason, we return NO when cmds exist. - return !hasCmds; - } // Returning YES here means that the request will be handled below, by startLoading, which will // override the network layer and return a 401 instead. Returning NO means that the network layer // will perform as ususal, and the request will be proceed. @@ -139,10 +117,7 @@ static CDVViewController *viewControllerForRequest(NSURLRequest* request) // NSLog(@"%@ received %@ - start", self, NSStringFromSelector(_cmd)); NSURL* url = [[self request] URL]; - if ([[url path] isEqualToString:@"/!gap_exec"]) { - [self sendResponseWithResponseCode:200 data:nil mimeType:nil]; - return; - } else if ([[url absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { + if ([[url absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) { if (asset) { // We have the asset! Get the data and send it along. http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dcbdb943/cordova-js-src/exec.js ---------------------------------------------------------------------- diff --git a/cordova-js-src/exec.js b/cordova-js-src/exec.js index 11cc92b..a0ef65d 100644 --- a/cordova-js-src/exec.js +++ b/cordova-js-src/exec.js @@ -27,20 +27,9 @@ var cordova = require('cordova'), channel = require('cordova/channel'), utils = require('cordova/utils'), base64 = require('cordova/base64'), - // XHR mode does not work on iOS 4.2. - // XHR mode's main advantage is working around a bug in -webkit-scroll, which - // doesn't exist only on iOS 5.x devices. - // IFRAME_NAV is the fastest. - // IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature. jsToNativeModes = { IFRAME_NAV: 0, // Default. Uses a new iframe for each poke. - // XHR bridge appears to be flaky sometimes: CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134 - XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable. - XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant - XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant - IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously. - IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded. - WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :) + WK_WEBVIEW_BINDING: 1 // Only way that works for WKWebView :) }, bridgeMode, execIframe, @@ -53,21 +42,6 @@ var cordova = require('cordova'), isInContextOfEvalJs = 0, failSafeTimerId = 0; -function shouldBundleCommandJson() { - if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) { - return true; - } - if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) { - var payloadLength = 0; - for (var i = 0; i < commandQueue.length; ++i) { - payloadLength += commandQueue[i].length; - } - // The value here was determined using the benchmark within CordovaLibApp on an iPad 3. - return payloadLength < 4500; - } - return false; -} - function massageArgsJsToNative(args) { if (!args || utils.typeName(args) != 'Array') { return args; @@ -190,85 +164,33 @@ function iOSExec() { } function pokeNative() { - switch (bridgeMode) { - case jsToNativeModes.XHR_NO_PAYLOAD: - case jsToNativeModes.XHR_WITH_PAYLOAD: - case jsToNativeModes.XHR_OPTIONAL_PAYLOAD: - pokeNativeViaXhr(); - break; - default: // iframe-based. - pokeNativeViaIframe(); - } -} - -function pokeNativeViaXhr() { - // This prevents sending an XHR when there is already one being sent. - // This should happen only in rare circumstances (refer to unit tests). - if (execXhr && execXhr.readyState != 4) { - execXhr = null; - } - // Re-using the XHR improves exec() performance by about 10%. - execXhr = execXhr || new XMLHttpRequest(); - // Changing this to a GET will make the XHR reach the URIProtocol on 4.2. - // For some reason it still doesn't work though... - // Add a timestamp to the query param to prevent caching. - execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true); - if (!vcHeaderValue) { - vcHeaderValue = /.*\((.*)\)$/.exec(navigator.userAgent)[1]; - } - execXhr.setRequestHeader('vc', vcHeaderValue); - execXhr.setRequestHeader('rc', ++requestCount); - if (shouldBundleCommandJson()) { - execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages()); - } - execXhr.send(null); -} - -function pokeNativeViaIframe() { // CB-5488 - Don't attempt to create iframe before document.body is available. if (!document.body) { - setTimeout(pokeNativeViaIframe); + setTimeout(pokeNative); return; } - if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) { - // TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735) - if (!execHashIframe) { - execHashIframe = document.createElement('iframe'); - execHashIframe.style.display = 'none'; - document.body.appendChild(execHashIframe); - // Hash changes don't work on about:blank, so switch it to file:///. - execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#'); - } - // The delegate method is called only when the hash changes, so toggle it back and forth. - hashToggle = hashToggle ^ 3; - var hashValue = '%0' + hashToggle; - if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) { - hashValue += iOSExec.nativeFetchMessages(); - } - execHashIframe.contentWindow.location.hash = hashValue; + + // Check if they've removed it from the DOM, and put it back if so. + if (execIframe && execIframe.contentWindow) { + execIframe.contentWindow.location = 'gap://ready'; } else { - // Check if they've removed it from the DOM, and put it back if so. - if (execIframe && execIframe.contentWindow) { - execIframe.contentWindow.location = 'gap://ready'; - } else { - execIframe = document.createElement('iframe'); - execIframe.style.display = 'none'; - execIframe.src = 'gap://ready'; - document.body.appendChild(execIframe); + execIframe = document.createElement('iframe'); + execIframe.style.display = 'none'; + execIframe.src = 'gap://ready'; + document.body.appendChild(execIframe); + } + // Use a timer to protect against iframe being unloaded during the poke (CB-7735). + // This makes the bridge ~ 7% slower, but works around the poke getting lost + // when the iframe is removed from the DOM. + // An onunload listener could be used in the case where the iframe has just been + // created, but since unload events fire only once, it doesn't work in the normal + // case of iframe reuse (where unload will have already fired due to the attempted + // navigation of the page). + failSafeTimerId = setTimeout(function() { + if (commandQueue.length) { + pokeNative(); } - // Use a timer to protect against iframe being unloaded during the poke (CB-7735). - // This makes the bridge ~ 7% slower, but works around the poke getting lost - // when the iframe is removed from the DOM. - // An onunload listener could be used in the case where the iframe has just been - // created, but since unload events fire only once, it doesn't work in the normal - // case of iframe reuse (where unload will have already fired due to the attempted - // navigation of the page). - failSafeTimerId = setTimeout(function() { - if (commandQueue.length) { - pokeNative(); - } - }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire). - } + }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire). } iOSExec.jsToNativeModes = jsToNativeModes; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dcbdb943/guides/Changing the JavaScript to Native Bridge Mode.md ---------------------------------------------------------------------- diff --git a/guides/Changing the JavaScript to Native Bridge Mode.md b/guides/Changing the JavaScript to Native Bridge Mode.md deleted file mode 100644 index 91f0192..0000000 --- a/guides/Changing the JavaScript to Native Bridge Mode.md +++ /dev/null @@ -1,36 +0,0 @@ -<!-- -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---> -# Changing the JavaScript to Native Bridge Mode # - -In Cordova 2.1.0 for iOS, we changed the default bridge mode from using an **iframe** to using **xhr** (XmlHttpRequest). This has proved to fix some [UI issues](https://issues.apache.org/jira/browse/CB-593) and possibly fix [crash issues](https://issues.apache.org/jira/browse/CB-975). - -In iOS 4.2.1 however, Cordova defaults back to **iframe** mode because of [a bug](https://issues.apache.org/jira/browse/CB-1296) - -To change the bridge mode back to the **xhr** method, do this in your **deviceready** hander: - - var exec = cordova.require('cordova/exec'); - exec.setJsToNativeBridgeMode(exec.jsToNativeModes.XHR_OPTIONAL_PAYLOAD); - - -To change the bridge mode back to the **iframe** method: - - var exec = cordova.require('cordova/exec'); - exec.setJsToNativeBridgeMode(exec.jsToNativeModes.IFRAME_NAV); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org For additional commands, e-mail: commits-h...@cordova.apache.org