cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agri...@apache.org
Subject [06/21] git commit: Have launch working on iOS without Menu
Date Thu, 24 Oct 2013 01:55:45 GMT
Have launch working on iOS without Menu


Project: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/commit/d172011d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/d172011d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/d172011d

Branch: refs/heads/master
Commit: d172011de59aae1f7ff8605e476c7489997e0b60
Parents: 8ed807c
Author: Andrew Grieve <agrieve@chromium.org>
Authored: Tue Oct 15 22:58:50 2013 -0400
Committer: Andrew Grieve <agrieve@chromium.org>
Committed: Wed Oct 23 21:55:17 2013 -0400

----------------------------------------------------------------------
 AppBundle/appBundle.js                |   8 ++
 AppBundle/src/ios/AppBundle.m         | 214 +++++++++++++++--------------
 createproject.sh                      |   2 +-
 www/cdvah_js/AppBundleAlias.js        |  89 +++++-------
 www/cdvah_js/AppsService.js           |  60 ++------
 www/cdvah_js/ListCtrl.js              |  23 +---
 www/cdvah_js/ServeCordovaJSHandler.js |  50 ++++---
 7 files changed, 198 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/AppBundle/appBundle.js
----------------------------------------------------------------------
diff --git a/AppBundle/appBundle.js b/AppBundle/appBundle.js
index cde9ce3..80a57b8 100644
--- a/AppBundle/appBundle.js
+++ b/AppBundle/appBundle.js
@@ -30,6 +30,14 @@ exports.addAlias = function(sourceUriMatchRegex, sourceUriReplaceRegex,
replaceS
     exec(win, fail, 'AppBundle', 'addAlias', [sourceUriMatchRegex, sourceUriReplaceRegex,
replaceString, redirectToReplacedUrl]);
 };
 
+exports.setResetUrl = function(urlRegex, callback) {
+    exec(callback, null, 'AppBundle', 'setResetUrl', [urlRegex]);
+};
+
+exports.injectJsForUrl = function(urlRegex, jsSnippet, callback) {
+    exec(callback, null, 'AppBundle', 'injectJs', [urlRegex, jsSnippet]);
+};
+
 exports.clearAllAliases = function(callback){
     exec(callback, null, 'AppBundle', 'clearAllAliases', []);
 };

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/AppBundle/src/ios/AppBundle.m
----------------------------------------------------------------------
diff --git a/AppBundle/src/ios/AppBundle.m b/AppBundle/src/ios/AppBundle.m
index 3106531..2f7b2e6 100644
--- a/AppBundle/src/ios/AppBundle.m
+++ b/AppBundle/src/ios/AppBundle.m
@@ -22,37 +22,40 @@
 @class RouteParams;
 
 static NSString* const kAppBundlePrefix = @"app-bundle:///";
-static NSString* gPathPrefix;
-static UIWebView* gWebView;
-static NSMutableArray* gRerouteParams;
-static RouteParams* gAppBundleParams;
+static NSString* gPathPrefix = nil;
+static UIWebView* gWebView = nil;
+static NSMutableArray* gRerouteParams = nil;
+static RouteParams* gResetUrlParams = nil;
 
 @interface AppBundle : CDVPlugin {}
 - (void)addAlias:(CDVInvokedUrlCommand*)command;
 - (void)clearAllAliases:(CDVInvokedUrlCommand*)command;
 @end
 
-@interface AppBundle()
-{}
-- (void) resetMap;
+@interface AppBundle() {}
+- (void)resetMap;
 @end
 
-@interface RouteParams : NSObject
-{
-@public
+@interface RouteParams : NSObject {
+  @public
     NSRegularExpression* _matchRegex;
     NSRegularExpression* _replaceRegex;
     NSString* _replacer;
     BOOL _redirectToReplacedUrl;
+    NSString* _jsToInject;
+}
+@end
+
+@implementation RouteParams
+- (BOOL)matches:(NSString*)uriString {
+    NSRange wholeStringRange = NSMakeRange(0, [uriString length]);
+    NSInteger numMatches = [_matchRegex numberOfMatchesInString:uriString options:0 range:wholeStringRange];
+    return numMatches > 0;
 }
-- (RouteParams*)initWithMatchRegex:(NSRegularExpression*)matchRegex replaceRegex:(NSRegularExpression*)replaceRegex
replacer:(NSString*)replacer shouldRedirect:(BOOL)redirectToReplacedUrl;
 @end
 
 @interface AppBundleURLProtocol : NSURLProtocol
-+ (RouteParams*) getChosenParams:(NSString*)uriString;
-- (void)issueNSURLResponseForFile:(NSString*)file;
-- (void)issueRedirectResponseForFile:(NSString*)file;
-- (void)issueNotFoundResponse;
++ (RouteParams*)getChosenParams:(NSString*)uriString forInjection:(BOOL)forInjection;
 @end
 
 
@@ -60,48 +63,60 @@ static RouteParams* gAppBundleParams;
 
 @implementation AppBundle
 
-- (void)resetMap
-{
+- (void)resetMap {
     NSError *error = NULL;
     NSRegularExpression* bundleMatchRegex = [NSRegularExpression regularExpressionWithPattern:@"^app-bundle:///.*"
options:0 error:&error];
     NSRegularExpression* bundleReplaceRegex = [NSRegularExpression regularExpressionWithPattern:@"^app-bundle:///"
options:0 error:&error];
-    gAppBundleParams = [[RouteParams alloc] initWithMatchRegex:bundleMatchRegex replaceRegex:bundleReplaceRegex
replacer:gPathPrefix shouldRedirect:YES];
+    RouteParams* params = [[RouteParams alloc] init];
+    params->_matchRegex = bundleMatchRegex;
+    params->_replaceRegex = bundleReplaceRegex;
+    params->_replacer = gPathPrefix;
+    params->_redirectToReplacedUrl = YES;
     gRerouteParams = [[NSMutableArray alloc] init];
-    [gRerouteParams addObject:gAppBundleParams];
-}
-
-- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
-{
-    self = [super initWithWebView:theWebView];
-    gWebView = theWebView;
-    if (self) {
-        [NSURLProtocol registerClass:[AppBundleURLProtocol class]];
-        gPathPrefix = [[NSBundle mainBundle] pathForResource:@"cordova.js" ofType:@"" inDirectory:@"www"];
-        gPathPrefix = [gPathPrefix stringByDeletingLastPathComponent];
-        gPathPrefix = [[NSURL fileURLWithPath:gPathPrefix] absoluteString];
-        [self resetMap];
+    [gRerouteParams addObject:params];
+}
+
+- (void)pluginInitialize {
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad)
name:CDVPageDidLoadNotification object:self.webView];
+    gWebView = self.webView;
+    [NSURLProtocol registerClass:[AppBundleURLProtocol class]];
+    gPathPrefix = [[NSBundle mainBundle] pathForResource:@"cordova.js" ofType:@"" inDirectory:@"www"];
+    gPathPrefix = [gPathPrefix stringByDeletingLastPathComponent];
+    gPathPrefix = [[NSURL fileURLWithPath:gPathPrefix] absoluteString];
+    [self resetMap];
+}
+
+- (void)pageDidLoad {
+    if (gResetUrlParams != nil) {
+        NSString* url = [self.webView stringByEvaluatingJavaScriptFromString:@"location.href.replace(/#.*/,
'')"];
+        if ([gResetUrlParams matches:url]) {
+            [self resetMap];
+        }
     }
-    return self;
 }
 
-- (void)addAlias:(CDVInvokedUrlCommand*)command
-{
+
+- (void)addAlias:(CDVInvokedUrlCommand*)command {
     CDVPluginResult* pluginResult = nil;
     NSError* error = nil;
-    NSString* sourceUrlMatchRegexString = [[command.arguments objectAtIndex:0] stringByReplacingOccurrencesOfString:@"{BUNDLE_WWW}"
withString:[NSRegularExpression escapedPatternForString:gPathPrefix]];
+    NSString* sourceUrlMatchRegexString = [[command argumentAtIndex:0] stringByReplacingOccurrencesOfString:@"{BUNDLE_WWW}"
withString:[NSRegularExpression escapedPatternForString:gPathPrefix]];
     NSRegularExpression* sourceUrlMatchRegex = [NSRegularExpression regularExpressionWithPattern:sourceUrlMatchRegexString
options:0 error:&error];
     if(error) {
         pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Match
regex is invalid"];
     } else {
-        NSString* sourceUrlReplaceRegexString = [[command.arguments objectAtIndex:1] stringByReplacingOccurrencesOfString:@"{BUNDLE_WWW}"
withString:[NSRegularExpression escapedPatternForString:gPathPrefix]];
+        NSString* sourceUrlReplaceRegexString = [[command argumentAtIndex:1] stringByReplacingOccurrencesOfString:@"{BUNDLE_WWW}"
withString:[NSRegularExpression escapedPatternForString:gPathPrefix]];
         NSRegularExpression* sourceUrlReplaceRegex = [NSRegularExpression regularExpressionWithPattern:sourceUrlReplaceRegexString
options:0 error:&error];
         if(error) {
             pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Replace
regex is invalid"];
         } else {
-            NSString* replaceString = [[command.arguments objectAtIndex:2] stringByReplacingOccurrencesOfString:@"{BUNDLE_WWW}"
withString:gPathPrefix];
-            BOOL redirectToReplacedUrl = [[command.arguments objectAtIndex:3] boolValue];
+            NSString* replaceString = [[command argumentAtIndex:2] stringByReplacingOccurrencesOfString:@"{BUNDLE_WWW}"
withString:gPathPrefix];
 
-            RouteParams* params = [[RouteParams alloc] initWithMatchRegex:sourceUrlMatchRegex
replaceRegex:sourceUrlReplaceRegex replacer:replaceString shouldRedirect:redirectToReplacedUrl];
+            RouteParams* params = [[RouteParams alloc] init];
+            params->_matchRegex = sourceUrlMatchRegex;
+            params->_replaceRegex = sourceUrlReplaceRegex;
+            params->_replacer = replaceString;
+            params->_redirectToReplacedUrl = [[command argumentAtIndex:3] boolValue];
             [gRerouteParams addObject:params];
             pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
         }
@@ -109,83 +124,68 @@ static RouteParams* gAppBundleParams;
     [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
 }
 
-- (void)clearAllAliases:(CDVInvokedUrlCommand*)command
-{
+- (void)clearAllAliases:(CDVInvokedUrlCommand*)command {
     [self resetMap];
     CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
     [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
 }
-@end
 
-#pragma mark RouteParams
-
-@implementation RouteParams
-
-- (RouteParams*)initWithMatchRegex:(NSRegularExpression*)matchRegex replaceRegex:(NSRegularExpression*)replaceRegex
replacer:(NSString*)replacer shouldRedirect:(BOOL)redirectToReplacedUrl
-{
-    self = [super init];
-    if(self)
-    {
-        _matchRegex = matchRegex;
-        _replaceRegex = replaceRegex;
-        _replacer = replacer;
-        _redirectToReplacedUrl = redirectToReplacedUrl;
-    }
-    return self;
+- (void)injectJs:(CDVInvokedUrlCommand*)command {
+    RouteParams* params = [[RouteParams alloc] init];
+    params->_matchRegex = [NSRegularExpression regularExpressionWithPattern:[command argumentAtIndex:0]
options:0 error:nil];
+    params->_jsToInject = [command argumentAtIndex:1];
+    [gRerouteParams addObject:params];
+    [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
callbackId:command.callbackId];
 }
 
+- (void)setResetUrl:(CDVInvokedUrlCommand*)command {
+    RouteParams* params = [[RouteParams alloc] init];
+    params->_matchRegex = [NSRegularExpression regularExpressionWithPattern:[command argumentAtIndex:0]
options:0 error:nil];
+    gResetUrlParams = params;
+    [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
callbackId:command.callbackId];
+}
 @end
 
 #pragma mark AppBundleURLProtocol
 
 @implementation AppBundleURLProtocol
 
-+ (RouteParams*)getChosenParams:(NSString*)uriString
-{
-    NSRange wholeStringRange = NSMakeRange(0, [uriString length]);
-    for(RouteParams* param in gRerouteParams) {
-        NSInteger numMatches = [param->_matchRegex numberOfMatchesInString:uriString options:0
range:wholeStringRange];
-        if (numMatches > 0) {
++ (RouteParams*)getChosenParams:(NSString*)uriString forInjection:(BOOL)forInjection {
+    for (RouteParams* param in gRerouteParams) {
+        if (forInjection != !!param->_jsToInject) {
+            continue;
+        }
+        if ([param matches:uriString]) {
             return param;
         }
     }
     return nil;
 }
 
-+ (BOOL)canInitWithRequest:(NSURLRequest*)request
-{
++ (BOOL)canInitWithRequest:(NSURLRequest*)request {
     NSURL* url = [request URL];
     NSString* urlString = [url absoluteString];
-    RouteParams* params = [AppBundleURLProtocol getChosenParams:urlString];
+    RouteParams* params = [AppBundleURLProtocol getChosenParams:urlString forInjection:NO];
     return params != nil;
 }
 
-+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
-{
++ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request {
     return request;
 }
 
-- (void)issueNotFoundResponse
-{
+- (void)issueNotFoundResponse {
     NSURL* url = [[self request] URL];
     NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:404 HTTPVersion:@"HTTP/1.1"
headerFields:@{}];
     [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
     [[self client] URLProtocolDidFinishLoading:self];
 }
 
-- (void)issueNSURLResponseForFile:(NSString*)file
-{
-    NSURL* uri = [[self request] URL];
-    NSString* uriString = [uri absoluteString];
-    RouteParams* params = [AppBundleURLProtocol getChosenParams:uriString];
-    NSRange wholeStringRange = NSMakeRange(0, [uriString length]);
-    NSString* newUrlString = [params->_replaceRegex stringByReplacingMatchesInString:uriString
options:0 range:wholeStringRange withTemplate:params->_replacer];
-    if ([newUrlString hasPrefix:@"file://"]) {
-        NSURL *newUrl = [NSURL URLWithString:newUrlString];
-        NSString* path = [newUrl path];
+- (void)issueNSURLResponseForUrl:(NSURL*)url {
+    if ([[url scheme] isEqualToString:@"file"]) {
+        NSString* path = [url path];
         FILE* fp = fopen([path UTF8String], "r");
         if (fp) {
-            NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:uri statusCode:200
HTTPVersion:@"HTTP/1.1" headerFields:@{}];
+            NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:@"text/html"
expectedContentLength:-1 textEncodingName:@"utf8"];//[[NSHTTPURLResponse alloc] initWithURL:url
statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{}];
             [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
 
             char* buf = malloc(32768);
@@ -201,38 +201,44 @@ static RouteParams* gAppBundleParams;
             [self issueNotFoundResponse];
         }
     } else {
-        NSLog(@"Cannot redirect to %@. You can only redirect to file: uri's", newUrlString);
+        NSLog(@"Cannot redirect to %@. You can only redirect to file: uri's", url);
         [self issueNotFoundResponse];
     }
 }
 
-- (void)issueRedirectResponseForFile:(NSString*)uriString
-{
-    RouteParams* params = [AppBundleURLProtocol getChosenParams:uriString];
-    if(params != nil && params->_redirectToReplacedUrl)
-    {
-        if([gWebView isLoading]) {
-            [gWebView stopLoading];
-        }
-        NSRange wholeStringRange = NSMakeRange(0, [uriString length]);
-        NSString* newUrlString = [params->_replaceRegex stringByReplacingMatchesInString:uriString
options:0 range:wholeStringRange withTemplate:params->_replacer];
-        NSURL *newUrl = [NSURL URLWithString:newUrlString];
-        NSURLRequest *request = [NSURLRequest requestWithURL:newUrl];
-        [gWebView loadRequest:request];
+- (void)issueRedirectResponseForUrl:(NSURL*)url {
+    if([gWebView isLoading]) {
+        [gWebView stopLoading];
     }
+    NSURLRequest *request = [NSURLRequest requestWithURL:url];
+    [gWebView loadRequest:request];
 }
 
-- (void)startLoading
-{
-    NSURL *url = [[self request] URL];
-    NSString* urlString = [url absoluteString];
-    NSURL* mainUrl = [[self request] mainDocumentURL];
-    NSString* mainUrlString = [mainUrl absoluteString];
+- (void)issueTopLevelRedirect:(NSURL*)url origURL:(NSURL*)origURL {
+    if([gWebView isLoading]) {
+        [gWebView stopLoading];
+    }
+    [gWebView loadData:[NSData dataWithContentsOfURL:url] MIMEType:@"text/html" textEncodingName:@"utf8"
baseURL:origURL];
+}
+
+- (void)startLoading {
+    NSURLRequest* request = [self request];
+    NSString* urlString = [[request URL] absoluteString];
+    
+    RouteParams* params = [AppBundleURLProtocol getChosenParams:urlString forInjection:NO];
+    NSRange wholeStringRange = NSMakeRange(0, [urlString length]);
+    NSString* newUrlString = [params->_replaceRegex stringByReplacingMatchesInString:urlString
options:0 range:wholeStringRange withTemplate:params->_replacer];
+    NSURL* newUrl = [NSURL URLWithString:newUrlString];
+
+    BOOL isTopLevelNavigation = [request.URL isEqual:request.mainDocumentURL];
     
-    if([mainUrlString isEqualToString:urlString]){
-        [self issueRedirectResponseForFile:urlString];
+    // iOS 6+ just gives "Frame load interrupted" when you try and feed it data via a URLProtocol.
+    if (isTopLevelNavigation) {
+        [self issueTopLevelRedirect:newUrl origURL:[request URL]];
+    } else if(params->_redirectToReplacedUrl) {
+        [self issueRedirectResponseForUrl:newUrl];
     } else {
-        [self issueNSURLResponseForFile:urlString];
+        [self issueNSURLResponseForUrl:newUrl];
     }
 }
 

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/createproject.sh
----------------------------------------------------------------------
diff --git a/createproject.sh b/createproject.sh
index 435ef9d..a5512d5 100755
--- a/createproject.sh
+++ b/createproject.sh
@@ -39,7 +39,7 @@ ln -s ../www www
 $CORDOVA platform add ios
 ../../cordova-ios/bin/update_cordova_subproject platforms/ios/CordovaAppHarness.xcodeproj
 
-$CORDOVA plugin add ../../../mobile_chrome_apps/AppBundle
+$CORDOVA plugin add ../AppBundle
 $CORDOVA plugin add ../../../mobile_chrome_apps/zip
 $CORDOVA plugin add ../../../BarcodeScanner # https://github.com/wildabeast/BarcodeScanner.git
 $CORDOVA plugin add ../../cordova-plugin-file

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/www/cdvah_js/AppBundleAlias.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/AppBundleAlias.js b/www/cdvah_js/AppBundleAlias.js
index 5e1bbb8..bad75f2 100644
--- a/www/cdvah_js/AppBundleAlias.js
+++ b/www/cdvah_js/AppBundleAlias.js
@@ -1,70 +1,51 @@
-(function(){
+(function() {
     "use strict";
     /* global myApp */
-    myApp.run(["AppsService", function(AppsService){
+    myApp.factory("AppBundle", ['$window', function($window) {
 
         // URI aliasing : the ability to launch an app in the harness, query the document.location
and get the same location as would have been got if you run the app separately
         // Without URI aliasing, document.location in the harness would give something like
file:///APP_HARNESS_INSTALLED_APPS_LOCATION/www/index.html
 
         function aliasUri(sourceUriMatchRegex, sourceUriReplaceRegex, replaceString, redirectToReplacedUrl){
             var deferred = Q.defer();
-            var appBundle = cordova.require("AppBundle.AppBundle");
-            try {
-                appBundle.addAlias(sourceUriMatchRegex, sourceUriReplaceRegex, replaceString,
redirectToReplacedUrl, function(succeded){
-                    if(succeded){
-                        deferred.resolve();
-                    } else {
-                        deferred.reject(new Error("Unable to set up uri aliasing"));
-                    }
-                });
-            } catch(e) {
-                deferred.reject(new Error(e));
-            } finally {
-                return deferred.promise;
-            }
-        }
-
-        function replaceCharWithString(string, searchChar, replaceString){
-            var ret = "";
-            for(var i = 0; i < string.length; i++){
-                if(string[i] === searchChar){
-                    ret += replaceString;
+            cordova.plugins.appBundle.addAlias(sourceUriMatchRegex, sourceUriReplaceRegex,
replaceString, redirectToReplacedUrl, function(succeded) {
+                if (succeded){
+                    deferred.resolve();
                 } else {
-                    ret += string[i];
+                    deferred.reject(new Error("Unable to set up uri aliasing"));
                 }
-            }
-            return ret;
+            });
+            return deferred.promise;
         }
 
-        function getRegex(string){
-            string = replaceCharWithString(string, "\\", "\\\\");
-            string = replaceCharWithString(string, "[", "\\[");
-            string = replaceCharWithString(string, "^", "\\^");
-            string = replaceCharWithString(string, "$", "\\$");
-            string = replaceCharWithString(string, ".", "\\.");
-            string = replaceCharWithString(string, "|", "\\|");
-            string = replaceCharWithString(string, "?", "\\?");
-            string = replaceCharWithString(string, "*", "\\*");
-            string = replaceCharWithString(string, "+", "\\+");
-            string = replaceCharWithString(string, "(", "\\(");
-            string = replaceCharWithString(string, ")", "\\)");
-            return string;
+        function setResetUrl(url) {
+            var deferred = Q.defer();
+            cordova.plugins.appBundle.setResetUrl(url, deferred.resolve);
+            return deferred.promise;
         }
 
-        AppsService.addPreLaunchHook(function(appEntry, appInstallLocation, wwwLocation)
{
-            wwwLocation += (wwwLocation.charAt(wwwLocation.length - 1) === "/")? "" : "/";
-            appInstallLocation += (appInstallLocation.charAt(appInstallLocation.length -
1) === "/")? "" : "/";
-            //Make any direct references to the bundle paths such as file:///android_asset
point to the installed location without redirecting
-            //{BUNDLE_WWW} in the regex is automatically replaced by the appBundle component
-            return aliasUri("^{BUNDLE_WWW}.*", "^{BUNDLE_WWW}", wwwLocation, false /* redirect
*/)
-            .then(function(){
-                //For cordova serve apps, we additionally have to redirect requests to the
original cordova.js to a modified cordova.js we have locally
-                if(appEntry.Source === "serve"){
-                    var regexWWWLoc = getRegex(wwwLocation);
-                    var regex = "^" + regexWWWLoc + "cordova.js(\\?|#.*)?";
-                    return aliasUri(regex, regex, appInstallLocation + "cordova.js", false);
-                }
-            });
-        }, 500 /* Give it a priority */);
+        function injectJsForUrl(url, js) {
+            var deferred = Q.defer();
+            cordova.plugins.appBundle.injectJsForUrl(url, js, deferred.resolve);
+            return deferred.promise;
+        }
+
+        function reset() {
+            var deferred = Q.defer();
+            cordova.plugins.appBundle.clearAllAliases(deferred.resolve);
+            return deferred.promise;
+        }
+
+        function escapeRegExp(str) {
+            return str.replace(/[-\[\]\/{}()*+?.\\^$|]/g, '\\$&');
+        }
+
+        return {
+            aliasUri: aliasUri,
+            reset: reset,
+            setResetUrl: setResetUrl,
+            injectJsForUrl: injectJsForUrl
+        };
+
     }]);
 })();

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/www/cdvah_js/AppsService.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/AppsService.js b/www/cdvah_js/AppsService.js
index cd565d0..d5b53ec 100644
--- a/www/cdvah_js/AppsService.js
+++ b/www/cdvah_js/AppsService.js
@@ -6,8 +6,6 @@
         var platformId = cordova.platformId;
         // Map of type -> handler.
         var _installHandlerFactories = {};
-        // functions to run before launching an app
-        var preLaunchHooks = [];
 
         var _installHandlers = null;
         var _lastLaunchedAppId = null;
@@ -71,14 +69,13 @@
             return (path.match(/^[a-z0-9+.-]+:/) != null);
         }
 
-        function getAppStartPageFromConfig(configFile, appBaseLocation) {
-            appBaseLocation += (appBaseLocation.charAt(appBaseLocation.length - 1) === "/")?
"" : "/";
+        function getAppStartPageFromConfig(configFile) {
             return ResourcesLoader.readFileContents(configFile)
             .then(function(contents){
                 if(!contents) {
                     throw new Error("Config file is empty. Unable to find a start page for
your app.");
                 } else {
-                    var startLocation = appBaseLocation + "index.html";
+                    var startLocation = 'index.html';
                     var parser = new DOMParser();
                     var xmlDoc = parser.parseFromString(contents, "text/xml");
                     var els = xmlDoc.getElementsByTagName("content");
@@ -88,13 +85,8 @@
                         for(var i = els.length - 1; i >= 0; i--) {
                             var el = els[i];
                             var srcValue = el.getAttribute("src");
-                            if(srcValue) {
-                                if(isUrlAbsolute(srcValue)) {
-                                    startLocation = srcValue;
-                                } else {
-                                    srcValue = srcValue.charAt(0) === "/" ? srcValue.substring(1)
: srcValue;
-                                    startLocation = appBaseLocation + srcValue;
-                                }
+                            if (srcValue) {
+                                startLocation = srcValue;
                                 break;
                             }
                         }
@@ -118,25 +110,14 @@
             appPaths.platformWWWLocation = installPath + "/www/";
 
             return Q.fcall(function(){
-                return getAppStartPageFromConfig(appPaths.configLocation, appPaths.platformWWWLocation);
+                return getAppStartPageFromConfig(appPaths.configLocation);
             })
-            .then(function(startLocation){
-                appPaths.startLocation = startLocation;
+            .then(function(startLocation) {
+                appPaths.startLocation = cordova.require('cordova/urlutil').makeAbsolute(startLocation);
                 return appPaths;
             });
         }
 
-        function insertObjectAtPriority(objArr, handler, priority){
-            var i = 0;
-            var objToInsert = { "priority" : priority, "handler" : handler };
-            for(i = 0; i < objArr.length; i++){
-                if(objArr[i].priority > objToInsert.priority) {
-                    break;
-                }
-            }
-            objArr.splice(i, 0, objToInsert);
-        }
-
         return {
             // return promise with the array of apps
             getAppList : function() {
@@ -147,25 +128,17 @@
             },
 
             launchApp : function(handler) {
-                var appEntry;
-                var startLocation;
                 _lastLaunchedAppId = handler.appId;
                 return writeAppsJson()
                 .then(function(){
                     return getAppPathsForHandler(handler);
                 })
                 .then(function(appPaths){
-                    startLocation = appPaths.startLocation;
-                    var result = Q.resolve(0 /* dummy value to set up chain */);
-                    preLaunchHooks.forEach(function (currHook) {
-                        result = result.then(function(){
-                            return currHook.handler(appEntry, appPaths.appInstallLocation,
appPaths.platformWWWLocation);
-                        });
+                    var installPath = INSTALL_DIRECTORY + '/' + handler.appId;
+                    return handler.prepareForLaunch(installPath, appPaths.startLocation)
+                    .then(function() {
+                        window.location = appPaths.startLocation;
                     });
-                    return result;
-                })
-                .then(function() {
-                    window.location = startLocation;
                 });
             },
 
@@ -199,20 +172,13 @@
             updateApp : function(handler){
                 return Q.fcall(function() {
                     var installPath = INSTALL_DIRECTORY + '/' + handler.appId;
-                    return handler.updateApp(installPath);
+                    return handler.updateApp(installPath)
+                    .then(writeAppsJson);
                 });
             },
 
             registerInstallHandlerFactory : function(handlerFactory) {
                 _installHandlerFactories[handlerFactory.type] = handlerFactory;
-            },
-
-            addPreLaunchHook : function(handler, priority){
-                if(!priority) {
-                    // Assign a default priority
-                    priority = 500;
-                }
-                insertObjectAtPriority(preLaunchHooks, handler, priority);
             }
         };
     }]);

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/www/cdvah_js/ListCtrl.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/ListCtrl.js b/www/cdvah_js/ListCtrl.js
index 928fb48..566d134 100644
--- a/www/cdvah_js/ListCtrl.js
+++ b/www/cdvah_js/ListCtrl.js
@@ -1,34 +1,15 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.controller("ListCtrl", [ "notifier", "$rootScope", "$scope", "$location", "$routeParams",
"AppsService", function (notifier, $rootScope, $scope, $location, $routeParams, AppsService)
{
+    myApp.controller("ListCtrl", [ "AppBundle", "notifier", "$rootScope", "$scope", "$routeParams",
"AppsService", function (AppBundle, notifier, $rootScope, $scope, $routeParams, AppsService)
{
         $scope.appList = [];
         $rootScope.appTitle = 'Cordova App Harness';
 
         initialise();
 
-        function clearAppBundleAliases(){
-            var deferred = Q.defer();
-            var appBundle = cordova.require("AppBundle.AppBundle");
-
-            try {
-                appBundle.clearAllAliases(function(succeded){
-                    if(succeded){
-                        deferred.resolve();
-                    } else {
-                        deferred.reject(new Error("Unable to clear old url aliases. Please
restart App Harness."));
-                    }
-                });
-            } catch(e) {
-                deferred.reject(new Error(e));
-            } finally {
-                return deferred.promise;
-            }
-        }
-
         function initialise() {
             //if we are navigating here after running an app, reset any aliases set for the
app by app harness or any aliases setup by the previous app
-            return clearAppBundleAliases()
+            return AppBundle.reset()
             .then(function(){
                 if($routeParams.lastLaunched) {
                     return AppsService.getLastRunApp()

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d172011d/www/cdvah_js/ServeCordovaJSHandler.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/ServeCordovaJSHandler.js b/www/cdvah_js/ServeCordovaJSHandler.js
index eb8beed..5026de6 100644
--- a/www/cdvah_js/ServeCordovaJSHandler.js
+++ b/www/cdvah_js/ServeCordovaJSHandler.js
@@ -1,28 +1,9 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.run(["AppsService", "ResourcesLoader", "ContextMenuInjectScript", function(AppsService,
ResourcesLoader, ContextMenuInjectScript){
+    myApp.run(["$location", "AppBundle", "AppsService", "ResourcesLoader", "ContextMenuInjectScript",
function($location, AppBundle, AppsService, ResourcesLoader, ContextMenuInjectScript){
         var platformId = cordova.platformId;
 
-        AppsService.addPreLaunchHook(function(appEntry, appInstallLocation , wwwLocation)
{
-            if(appEntry.Source === "serve"){
-                return Q.fcall(function(){
-                    // We can't inject the context menu script into cordova.js remotely
-                    // So we create a local copy of the cordova.js used by the server,
-                    //      append the context menu script (requests for cordova.js are routed
to it)
-                    wwwLocation += (wwwLocation.charAt(wwwLocation.length - 1) === "/")?
"" : "/";
-                    var cordovaJSPath = wwwLocation + "cordova.js";
-                    return ResourcesLoader.xhrGet(cordovaJSPath);
-                })
-                .then(function(xhr){
-                    var dataToAppend = ContextMenuInjectScript.getInjectString(appEntry.Name);
-                    var completeText = xhr.responseText + dataToAppend;
-                    appInstallLocation += (appInstallLocation.charAt(appInstallLocation.length
- 1) === "/")? "" : "/";
-                    return ResourcesLoader.writeFileContents(appInstallLocation + "cordova.js",
completeText);
-                });
-            }
-        }, 250 /* Give it a priority */);
-
         function ServeHandler(url, appId) {
             this.url = url;
             this.appId = appId || '';
@@ -56,6 +37,10 @@
                 var files = self._cachedProjectJson['wwwFileList'];
                 var i = 0;
                 function downloadNext() {
+                    // Don't download cordova.js. We want to use the version bundled with
the harness.
+                    if (/\/cordova(?:_plugins)?.js$/.exec(files[i])) {
+                        ++i;
+                    }
                     if (!files[i]) {
                         self.lastUpdated = new Date();
                         return;
@@ -69,12 +54,35 @@
                 }
                 return ResourcesLoader.ensureDirectoryExists(installPath + '/config.xml')
                 .then(function() {
-                    return ResourcesLoader.writeFileContents(installPath + '/config.xml',
self._cachedConfigXml);
+                    return ResourcesLoader.writeFileContents(installPath + '/config.xml',
self._cachedConfigXml)
                 })
                 .then(downloadNext);
             });
         };
 
+        ServeHandler.prototype.prepareForLaunch = function(installPath, launchUrl) {
+            var harnessUrl = cordova.require('cordova/urlutil').makeAbsolute(location.pathname);
+            var harnessDir = harnessUrl.replace(/\/[^\/]*$/, '');
+            var installUrl = cordova.require('cordova/urlutil').makeAbsolute(installPath);
+            var injectString = ContextMenuInjectScript.getInjectString()
+            // Inject the context menu script for all pages except the harness menu.
+            return AppBundle.injectJsForUrl('^(?!' + harnessUrl + ')', injectString)
+            .then(function() {
+                // Allow navigations back to the menu.
+                return AppBundle.setResetUrl('^' + harnessUrl);
+            })
+            .then(function() {
+                // Make any references to www/ point to the app's install location.
+                return AppBundle.aliasUri('^' + harnessDir, '^' + harnessDir, installUrl
+ '/www', false /* redirect */);
+            })
+            .then(function() {
+                return AppBundle.aliasUri('/cordova\\.js.*', '.+', harnessDir + '/cordova.js',
false /* redirect */);
+            })
+            .then(function() {
+                return AppBundle.aliasUri('/cordova_plugins\\.js.*', '.+', harnessDir + '/cordova_plugins.js',
false /* redirect */);
+            });
+        };
+
         function createFromUrl(url) {
             // Strip platform and trailing slash if they exist.
             url = url.replace(/\/$/, '').replace(new RegExp(platformId + '$'), '').replace(/\/$/,
'');


Mime
View raw message