You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by br...@apache.org on 2013/06/25 20:57:59 UTC

[1/9] git commit: Support installation of crx files

Updated Branches:
  refs/heads/master d2d24aeaa -> f8f936997


Support installation of crx files


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/d045574b
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/d045574b
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/d045574b

Branch: refs/heads/master
Commit: d045574baae9631f747e5a412d28ce7615c74d8a
Parents: d2d24ae
Author: Shravan Narayan <sh...@google.com>
Authored: Fri Apr 26 14:39:15 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Wed Jun 19 16:09:03 2013 -0400

----------------------------------------------------------------------
 www/crx_files/config.android.xml                |  47 ++++
 www/crx_files/config.ios.xml                    |  51 +++++
 www/crx_files/www/chromeapp.html                |  15 ++
 www/crx_files/www/chromeappstyles.css           |  14 ++
 www/crx_files/www/chromebgpage.html             |  11 +
 www/crx_files/www/cordova_plugins.json          |   1 +
 .../www/plugins/chrome.common/events.js         |  53 +++++
 .../www/plugins/chrome.fileSystem/fileSystem.js | 142 ++++++++++++
 www/crx_files/www/plugins/chrome.i18n/i18n.js   | 185 ++++++++++++++++
 .../www/plugins/chrome.identity/identity.js     | 161 ++++++++++++++
 .../www/plugins/chrome.socket/socket.js         | 216 +++++++++++++++++++
 .../www/plugins/chrome.storage/storage.js       | 202 +++++++++++++++++
 .../www/plugins/chrome/api/app/runtime.js       |   7 +
 .../www/plugins/chrome/api/app/window.js        | 156 ++++++++++++++
 .../www/plugins/chrome/api/bootstrap.js         |  13 ++
 .../www/plugins/chrome/api/helpers/stubs.js     |  11 +
 www/crx_files/www/plugins/chrome/api/mobile.js  |  58 +++++
 www/crx_files/www/plugins/chrome/api/runtime.js |  58 +++++
 www/js/CrxPackageHandler.js                     |  54 +++++
 19 files changed, 1455 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/config.android.xml
----------------------------------------------------------------------
diff --git a/www/crx_files/config.android.xml b/www/crx_files/config.android.xml
new file mode 100644
index 0000000..27da959
--- /dev/null
+++ b/www/crx_files/config.android.xml
@@ -0,0 +1,47 @@
+<?xml version='1.0' encoding='utf-8'?>
+<cordova>
+    <content src="index.html" />
+    <log level="DEBUG" />
+    <plugins>
+        <plugin name="App" value="org.apache.cordova.App" />
+        <plugin name="Geolocation" value="org.apache.cordova.GeoBroker" />
+        <plugin name="Device" value="org.apache.cordova.Device" />
+        <plugin name="Accelerometer" value="org.apache.cordova.AccelListener" />
+        <plugin name="Compass" value="org.apache.cordova.CompassListener" />
+        <plugin name="Media" value="org.apache.cordova.AudioHandler" />
+        <plugin name="Camera" value="org.apache.cordova.CameraLauncher" />
+        <plugin name="Contacts" value="org.apache.cordova.ContactManager" />
+        <plugin name="File" value="org.apache.cordova.FileUtils" />
+        <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager" />
+        <plugin name="Notification" value="org.apache.cordova.Notification" />
+        <plugin name="Storage" value="org.apache.cordova.Storage" />
+        <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer" />
+        <plugin name="Capture" value="org.apache.cordova.Capture" />
+        <plugin name="Battery" value="org.apache.cordova.BatteryListener" />
+        <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen" />
+        <plugin name="Echo" value="org.apache.cordova.Echo" />
+        <plugin name="Globalization" value="org.apache.cordova.Globalization" />
+        <plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser" />
+        <plugin name="Zip" value="org.apache.cordova.Zip" />
+        <plugin name="ChromeExtensionURLs" value="com.google.cordova.ChromeExtensionURLs">
+            <url-filter value="chrome-extension://" />
+        </plugin>
+        <plugin name="ChromeI18n" onload="true" value="com.google.cordova.ChromeI18n" />
+        <plugin name="ChromeIdentity" value="com.google.cordova.ChromeIdentity" />
+        <plugin name="ChromeSocket" value="com.google.cordova.ChromeSocket" />
+        <plugin name="ChromeStorage" value="com.google.cordova.ChromeStorage" />
+        <plugin name="CordovaAppHarnessRedirect" value="org.apache.cordova.cordovaappharness.CordovaAppHarnessRedirect">
+            <url-filter value="cdv-app-harness://" />
+        </plugin>
+    </plugins>
+    <content src="chromeapp.html" />
+    <access origin="*" />
+    <access origin="chrome-extension://*" />
+    <access origin="cdv-app-harness://*" />
+    <preference name="useBrowserHistory" value="true" />
+    <preference name="exit-on-suspend" value="false" />
+    <preference name="phonegap-version" value="1.9.0" />
+    <preference name="orientation" value="default" />
+    <preference name="target-device" value="universal" />
+    <preference name="fullscreen" value="false" />
+</cordova>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/config.ios.xml
----------------------------------------------------------------------
diff --git a/www/crx_files/config.ios.xml b/www/crx_files/config.ios.xml
new file mode 100644
index 0000000..bfba1c9
--- /dev/null
+++ b/www/crx_files/config.ios.xml
@@ -0,0 +1,51 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget>
+    <content src="index.html" />
+    <plugins>
+        <plugin name="Device" value="CDVDevice" />
+        <plugin name="Logger" value="CDVLogger" />
+        <plugin name="Compass" value="CDVLocation" />
+        <plugin name="Accelerometer" value="CDVAccelerometer" />
+        <plugin name="Camera" value="CDVCamera" />
+        <plugin name="NetworkStatus" value="CDVConnection" />
+        <plugin name="Contacts" value="CDVContacts" />
+        <plugin name="Debug Console" value="CDVDebugConsole" />
+        <plugin name="Echo" value="CDVEcho" />
+        <plugin name="File" value="CDVFile" />
+        <plugin name="FileTransfer" value="CDVFileTransfer" />
+        <plugin name="Geolocation" value="CDVLocation" />
+        <plugin name="Notification" value="CDVNotification" />
+        <plugin name="Media" value="CDVSound" />
+        <plugin name="Capture" value="CDVCapture" />
+        <plugin name="SplashScreen" value="CDVSplashScreen" />
+        <plugin name="Battery" value="CDVBattery" />
+        <plugin name="Globalization" value="CDVGlobalization" />
+        <plugin name="InAppBrowser" value="CDVInAppBrowser" />
+        <plugin name="Zip" value="Zip" />
+        <plugin name="ChromeExtensionURLs" onload="true" value="ChromeExtensionURLs" />
+        <plugin name="ChromeI18n" value="ChromeI18n" />
+        <plugin name="ChromeSocket" value="ChromeSocket" />
+        <plugin name="ChromeStorage" value="ChromeStorage" />
+        <plugin name="CordovaAppHarnessRedirect" onload="true" value="CordovaAppHarnessRedirect" />
+    </plugins>
+    <content src="chromeapp.html" />
+    <access origin="*" />
+    <access origin="chrome-extension://*" />
+    <access origin="cdv-app-harness://*" />
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="UIWebViewBounce" value="true" />
+    <preference name="TopActivityIndicator" value="gray" />
+    <preference name="EnableLocation" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="ShowSplashScreenSpinner" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="OpenAllWhitelistURLsInWebView" value="false" />
+    <preference name="BackupWebStorage" value="cloud" />
+    <preference name="phonegap-version" value="1.9.0" />
+    <preference name="orientation" value="default" />
+    <preference name="target-device" value="universal" />
+    <preference name="fullscreen" value="false" />
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/chromeapp.html
----------------------------------------------------------------------
diff --git a/www/crx_files/www/chromeapp.html b/www/crx_files/www/chromeapp.html
new file mode 100644
index 0000000..3cbd68d
--- /dev/null
+++ b/www/crx_files/www/chromeapp.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <meta name="format-detection" content="telephone=no">
+        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
+        <script src="cordova.js"></script>
+    </head>
+    <body></body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/chromeappstyles.css
----------------------------------------------------------------------
diff --git a/www/crx_files/www/chromeappstyles.css b/www/crx_files/www/chromeappstyles.css
new file mode 100644
index 0000000..277f4fe
--- /dev/null
+++ b/www/crx_files/www/chromeappstyles.css
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+ * Contains extra user-agent styles to apply to all Chrome App windows.
+ *
+ * These should be kept in sync with:
+ * http://code.google.com/searchframe#OAMlx_jo-ck/src/chrome/renderer/resources/extensions/platform_app.css
+ */
+body { -webkit-user-select: none; }
+html, body { overflow: hidden; }

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/chromebgpage.html
----------------------------------------------------------------------
diff --git a/www/crx_files/www/chromebgpage.html b/www/crx_files/www/chromebgpage.html
new file mode 100644
index 0000000..b732eaa
--- /dev/null
+++ b/www/crx_files/www/chromebgpage.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<html>
+  <body>
+    <script>parent.chrome.mobile.impl.bgInit(this)</script>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/cordova_plugins.json
----------------------------------------------------------------------
diff --git a/www/crx_files/www/cordova_plugins.json b/www/crx_files/www/cordova_plugins.json
new file mode 100644
index 0000000..fe11f7c
--- /dev/null
+++ b/www/crx_files/www/cordova_plugins.json
@@ -0,0 +1 @@
+[{"file":"plugins/chrome/api/bootstrap.js","id":"chrome.bootstrap","runs":true},{"file":"plugins/chrome/api/app/runtime.js","id":"chrome.app.runtime","clobbers":["chrome.app.runtime"]},{"file":"plugins/chrome/api/app/window.js","id":"chrome.app.window","clobbers":["chrome.app.window"]},{"file":"plugins/chrome/api/helpers/stubs.js","id":"chrome.helpers.stubs"},{"file":"plugins/chrome/api/mobile.js","id":"chrome.mobile.impl","clobbers":["chrome.mobile.impl"]},{"file":"plugins/chrome/api/runtime.js","id":"chrome.runtime","clobbers":["chrome.runtime"]},{"file":"plugins/chrome.common/events.js","id":"chrome.common.events","clobbers":["chrome.Event"]},{"file":"plugins/chrome.fileSystem/fileSystem.js","id":"chrome.fileSystem.FileSystem","clobbers":["chrome.fileSystem"]},{"file":"plugins/chrome.i18n/i18n.js","id":"chrome.i18n.I18n","clobbers":["chrome.i18n"]},{"file":"plugins/chrome.identity/identity.js","id":"chrome.identity.Identity","clobbers":["chrome.identity","chrome.experimental.iden
 tity"]},{"file":"plugins/chrome.socket/socket.js","id":"chrome.socket.Socket","clobbers":["chrome.socket"]},{"file":"plugins/chrome.storage/storage.js","id":"chrome.storage.Storage","clobbers":["chrome.storage"]}]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome.common/events.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.common/events.js b/www/crx_files/www/plugins/chrome.common/events.js
new file mode 100644
index 0000000..6f868b1
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome.common/events.js
@@ -0,0 +1,53 @@
+cordova.define("chrome.common.events", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var Event = function(opt_eventName) {
+  this.name = opt_eventName || '';
+  this.listeners = [];
+};
+
+// Deliberately not filtering functions that are already added.
+// I tested on desktop and it will call your callback once for each addListener.
+Event.prototype.addListener = function(cb) {
+  this.listeners.push(cb);
+};
+
+Event.prototype.findListener_ = function(cb) {
+  for(var i = 0; i < this.listeners.length; i++) {
+    if (this.listeners[i] == cb) {
+      return i;
+    }
+  }
+
+  return -1;
+};
+
+Event.prototype.removeListener = function(cb) {
+  var index = this.findListener_(cb);
+  if (index >= 0) {
+    this.listeners.splice(index, 1);
+  }
+};
+
+Event.prototype.hasListener = function(cb) {
+  return this.findListener_(cb) >= 0;
+};
+
+Event.prototype.hasListeners = function() {
+  return this.listeners.length > 0;
+};
+
+Event.prototype.fire = function() {
+  for (var i = 0; i < this.listeners.length; i++) {
+    this.listeners[i].apply(this, arguments);
+  }
+};
+
+// Stubs since we don't support Rules.
+Event.prototype.addRules = function() { };
+Event.prototype.getRules = function() { };
+Event.prototype.removeRules = function() { };
+
+module.exports = Event;
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js b/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js
new file mode 100644
index 0000000..ce613e5
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js
@@ -0,0 +1,142 @@
+cordova.define("chrome.fileSystem.FileSystem", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var platformId = cordova.require('cordova/platform').id;
+var FileEntry = cordova.require('cordova/plugin/FileEntry');
+
+exports.getDisplayPath = function(fileEntry, callback) {
+  callback(fileEntry.fullPath);
+};
+
+exports.getWritableEntry = function(fileEntry, callback) {
+  callback(null);
+};
+
+exports.isWritableEntry = function(fileEntry, callback) {
+  callback(false);
+};
+
+exports.chooseEntry = function(options, callback) {
+  // Ensure that the type is either unspecified or specified as 'openFile', as nothing else is supported.
+  if (options.type && options.type != 'openFile') {
+    // TODO(maxw): Determine a "more correct" way to fail here.
+    callback(null);
+    return;
+  }
+
+  // Create the callback for getFile.
+  // It creates a file entry and passes it to the chooseEntry callback.
+  var onFileReceived = function(nativeUri) {
+    var onUriResolved = function(fileEntry) {
+      callback(fileEntry);
+    };
+
+    var onUriResolveError = function(e) {
+      console.log(e.target.error.code);
+    };
+
+    resolveLocalFileSystemURI(nativeUri, onUriResolved, onUriResolveError);
+  };
+
+  if (platformId == 'ios') {
+    getFileIos(options, onFileReceived);
+  } else if (platformId == 'android') {
+    getFileAndroid(options, onFileReceived);
+  }
+};
+
+function getFileIos(options, onFileReceivedCallback) {
+  // Determine the media type.
+  var mediaType = determineMediaType(options.accepts, options.acceptsAllTypes);
+
+  // Prepare the options for getting the file.
+  var getFileOptions = { destinationType: navigator.camera.DestinationType.NATIVE_URI,
+                         sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
+                         mediaType: mediaType };
+
+  // Use the camera to get an image or video.
+  navigator.camera.getPicture(onFileReceivedCallback, null, getFileOptions);
+}
+
+function getFileAndroid(options, onFileReceivedCallback) {
+  var AndroidFileChooser = cordova.require('cordova/plugin/android/filechooser');
+
+  // Determine the relevant mime types.
+  var mimeTypes = determineMimeTypes(options.accepts, options.acceptsAllTypes);
+
+  // Use the file chooser to get a file.
+  AndroidFileChooser.chooseFile(onFileReceivedCallback, null, mimeTypes);
+}
+
+function determineMediaType(acceptOptions, acceptsAllTypes) {
+  if (acceptsAllTypes) {
+    return navigator.camera.MediaType.ALLMEDIA;
+  }
+
+  var imageMimeTypeRegex = /^image\//;
+  var videoMimeTypeRegex = /^video\//;
+  var imageExtensionRegex = /^(?:jpg|png)$/;
+  var videoExtensionRegex = /^mov$/;
+  var imagesAllowed = false;
+  var videosAllowed = false;
+
+  // Iterate through all accept options.
+  // If we see anything image related, allow images.  If we see anything video related, allow videos.
+  if (acceptOptions) {
+    for (var i = 0; i < acceptOptions.length; i++) {
+      if (acceptOptions[i].mimeTypes) {
+        for (var j = 0; j < acceptOptions[i].mimeTypes.length; j++) {
+          if (imageMimeTypeRegex.test(acceptOptions[i].mimeTypes[j])) {
+            imagesAllowed = true;
+          } else if (videoMimeTypeRegex.test(acceptOptions[i].mimeTypes[j])) {
+            videosAllowed = true;
+          }
+        }
+      }
+      if (acceptOptions[i].extensions) {
+        for (var k = 0; k < acceptOptions[i].extensions.length; k++) {
+          if (imageExtensionRegex.test(acceptOptions[i].extensions[k])) {
+            imagesAllowed = true;
+          } else if (videoExtensionRegex.test(acceptOptions[i].extensions[k])) {
+            videosAllowed = true;
+          }
+        }
+      }
+    }
+  }
+
+  if (imagesAllowed && !videosAllowed) {
+    return navigator.camera.MediaType.PICTURE;
+  } else if (!imagesAllowed && videosAllowed) {
+    return navigator.camera.MediaType.VIDEO;
+  }
+
+  return navigator.camera.MediaType.ALLMEDIA;
+}
+
+function determineMimeTypes(acceptOptions, acceptsAllTypes) {
+  if (acceptsAllTypes) {
+    return [ '*/*' ];
+  }
+
+  // Pull out all the mime types.
+  // TODO(maxw): Determine mime types from extensions and add them to the returned list.
+  var mimeTypes = [ ];
+  if (acceptOptions) {
+    for (var i = 0; i < acceptOptions.length; i++) {
+      if (acceptOptions[i].mimeTypes) {
+        for (var j = 0; j < acceptOptions[i].mimeTypes.length; j++) {
+          mimeTypes.push(acceptOptions[i].mimeTypes[j]);
+        }
+      }
+    }
+  }
+
+  if (mimeTypes.length !== 0) {
+    return mimeTypes;
+  }
+
+  return [ '*/*' ];
+}
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome.i18n/i18n.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.i18n/i18n.js b/www/crx_files/www/plugins/chrome.i18n/i18n.js
new file mode 100644
index 0000000..905466c
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome.i18n/i18n.js
@@ -0,0 +1,185 @@
+cordova.define("chrome.i18n.I18n", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var exec = cordova.require('cordova/exec');
+var runtime = require('chrome.runtime');
+
+exports.getAcceptLanguages = function(callback) {
+    // In the chrome implementation, acceptLanguage value can change with updates so we make a native call to get the system language
+    exec(callback, callback, 'ChromeI18n', 'getAcceptLanguages', []);
+};
+
+exports.getMessage = function(messageName, substitutions) {
+    // In the chrome implementation, the locale to translate to DOES NOT change with updates, it is keyed of window.navigator.language which is static for a session.
+    // This is implemented in _getLocalesToUse()
+    if(
+        (typeof messageName !== 'string') ||
+        (Array.isArray(substitutions) && substitutions.length > 9)
+    ) {
+        return;
+    }
+    messageName = messageName.toLowerCase();
+    var ret = '';
+    var localeChain = _getLocalesToUse();
+    var contentsForMessageName = _getMessageFromMessageJson(messageName, localeChain);
+    if(contentsForMessageName) {
+        ret = _applySubstitutions(contentsForMessageName, substitutions);
+    }
+    return ret;
+};
+
+function _endsWith(string, endString) {
+    if(endString.length > string.length) {
+        return false;
+    } else {
+        return (string.lastIndexOf(endString) === string.length - endString.length);
+    }
+}
+
+function _getFilePathForLocale(locale) {
+    return 'locales/' + locale.toLowerCase() + '/messages.json';
+}
+
+function _toLowerCaseMessageAndPlaceholders(obj) {
+    if(typeof obj !== 'undefined') {
+        var newObj = {};
+        for(var field in obj) {
+            if(obj[field].placeholders) {
+                var newPlaceholders = {};
+                for(var placeholderField in obj[field].placeholders) {
+                    newPlaceholders[placeholderField.toLowerCase()] = obj[field].placeholders[placeholderField];
+                }
+                obj[field].placeholders = newPlaceholders;
+            }
+            newObj[field.toLowerCase()] = obj[field];
+        }
+        return newObj;
+    }
+}
+
+function _getDefaultLocale() {
+    var manifestJson = runtime.getManifest();
+    if(manifestJson.default_locale) {
+        return manifestJson.default_locale;
+    } else {
+        throw new Error('Default locale not defined');
+    }
+}
+
+var memoizedJsonContents = {};
+function _getMessageFromMessageJson(messageName, localeChain) {
+    for(var i = 0; i < localeChain.length; i++) {
+        var locale = localeChain[i];
+        if (!memoizedJsonContents[locale]) {
+            var fileName = _getFilePathForLocale(locale);
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', fileName, false /* sync */);
+            xhr.send(null);
+            var contents = eval('(' + xhr.responseText + ')');
+            // convert all fields to lower case to check case insensitively
+            contents = _toLowerCaseMessageAndPlaceholders(contents);
+            memoizedJsonContents[locale] = contents;
+        }
+        if(memoizedJsonContents[locale][messageName]) {
+            return memoizedJsonContents[locale][messageName];
+        }
+    }
+}
+
+function _isLocaleAvailable(locale) {
+    var fileName = _getFilePathForLocale(locale);
+    var xhr = new XMLHttpRequest();
+    xhr.open('HEAD', fileName, false /* sync */);
+    xhr.send(null);
+    availableLocales[locale] = (xhr.status === 200);
+}
+
+var chosenLocales;
+function _getLocalesToUse() {
+    if(!chosenLocales) {
+        // language returned by window.navigator is in format en-US, need to change it to en_us
+        var windowLocale = window.navigator.language.replace('-', '_').toLowerCase();
+        var localesToUse = [windowLocale];
+        // Construct fallback chain
+        var lastIndex;
+        while((lastIndex = windowLocale.lastIndexOf('_')) !== -1) {
+            windowLocale = windowLocale.substring(0, lastIndex);
+            localesToUse.push(windowLocale);
+        }
+        var defaultLocale = _getDefaultLocale().toLowerCase();
+        if(localesToUse.indexOf(defaultLocale) == -1) {
+            localesToUse.push(defaultLocale);
+        }
+
+        chosenLocales = [] ;
+        for(var i = 0; i < localesToUse.length; i++) {
+            var currentLocale = localesToUse[i];
+            if(_isLocaleAvailable(currentLocale)) {
+                chosenLocales.push(currentLocale);
+            }
+        }
+    }
+    if(chosenLocales.length == 0) {
+        throw new Error('No usable locale.');
+    }
+    return chosenLocales;
+}
+
+function _getSubstitutionString(match, substitutions) {
+    if(match == '$$') {
+        return '$';
+    } else if(match == '$') {
+        return '';
+    }
+    else {
+        var locBaseOne = parseInt(match.substring(1));
+        if(isNaN(locBaseOne) || locBaseOne <= 0) {
+            return '';
+        }
+
+        if(substitutions[locBaseOne - 1]) {
+            return substitutions[locBaseOne - 1];
+        } else {
+            return '';
+        }
+    }
+}
+
+function _getPlaceholderText(placeholders, substitutions, match) {
+    // Switch to lower case to do case insensitive checking for matches
+    var placeholderField = match.substring(1, match.length - 1);
+    placeholderField = placeholderField.toLowerCase();
+    if(placeholders[placeholderField]) {
+        // form $1, $2 etc or '$$' or '$'
+        var placeholderText = placeholders[placeholderField].content.replace(/\$(([0-9]+)|\$)?/g, function(match) {
+            var substitutionString = _getSubstitutionString(match, substitutions);
+            return substitutionString;
+        });
+        return placeholderText;
+    } else {
+        return '';
+    }
+}
+
+function _applySubstitutions(messageObject, substitutions) {
+    if(typeof substitutions === 'undefined') {
+        substitutions = [];
+    } else if(Object.prototype.toString.call(substitutions) !== '[object Array]') {
+        substitutions = [substitutions];
+    }
+    // Look for any strings of form $WORD$ eg: $1stName$, form $1, $2 etc or any lone '$'
+    // Order of preference is as in this comment
+    var ret = messageObject.message.replace( /\$(([0-9a-zA-Z_]*\$)|([0-9]*))?/g, function(matchedString) {
+        // check which category of matchedString it is
+        if(matchedString.match(/\$[0-9a-zA-Z_]+\$/)) { // form $WORD$
+            var placeholderText = _getPlaceholderText(messageObject.placeholders, substitutions, matchedString);
+            return placeholderText;
+        } else { // form $1, $2 etc or '$$' or '$'
+            var substitutionString = _getSubstitutionString(matchedString, substitutions);
+            return substitutionString;
+        }
+    });
+    return ret;
+}
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome.identity/identity.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.identity/identity.js b/www/crx_files/www/plugins/chrome.identity/identity.js
new file mode 100644
index 0000000..54f1597
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome.identity/identity.js
@@ -0,0 +1,161 @@
+cordova.define("chrome.identity.Identity", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var platformId = cordova.require('cordova/platform').id;
+var runtime = require('chrome.runtime');
+
+exports.TokenDetails = function(interactive) {
+    this.interactive = interactive || false;
+};
+
+exports.WebAuthFlowDetails = function(url, interactive, width, height, left, top) {
+    if (typeof url == 'undefined') {
+        throw new Error('Url required');
+    }
+    this.url = url;
+    this.interactive = interactive || false;
+    this.width = width;
+    this.height = height;
+    this.left = left;
+    this.top = top;
+};
+
+exports.getAuthToken = function(details, callback) {
+    if(typeof details == 'function') {
+        callback = details;
+        details = new exports.TokenDetails();
+    }
+    if (typeof callback == 'undefined') {
+        chrome.runtime.lastError = { 'message' : 'Callback function required' };
+        // Not calling callback as it wasnt provided
+        return;
+    }
+    var win = function(token) {
+        callback(token);
+    };
+    var fail = function() {
+        callback();
+    };
+
+    if (platformId == 'android') {
+        // Use native implementation for logging into google accounts
+        cordova.exec(win, fail, 'ChromeIdentity', 'getAuthToken', [details]);
+    } else {
+        // Use web app oauth flow
+        _getAuthTokenJS(win, fail, details);
+    }
+};
+
+exports.launchWebAuthFlow = function(details, callback) {
+    var failed = false;
+    var failMessage;
+    if (typeof details == 'undefined') {
+        failed = true;
+        failMessage = 'WebAuthFlowDetails required';
+    } else if (typeof callback == 'undefined') {
+        failed = true;
+        failMessage = 'Callback function required';
+    }
+
+    if(failed === true) {
+        chrome.runtime.lastError = { 'message' : failMessage };
+        // Not calling callback as it wasnt provided
+        return;
+    }
+
+    var finalURL = details.url;
+    var extractedRedirectedURL = _getParameterFromUrl(finalURL, 'redirect_uri', '?', '#');
+
+    if(typeof extractedRedirectedURL == 'undefined') {
+        chrome.runtime.lastError = { 'message' : 'launchWebAuthFlow: Parameter redirect_uri not found.' };
+        callback();
+    } else {
+        _launchInAppBrowser(finalURL, extractedRedirectedURL, callback);
+    }
+};
+
+function _getAuthTokenJS(win, fail , details) {
+    var failed = false;
+    var failMessage;
+    if(!details.interactive) {
+        // We cannot support non interactive mode.
+        // This requires the ability to use invisible InAppBrowser windows, which is not currently supported
+        failed = true;
+        failMessage = 'Unsupported mode - Non interactive mode is not supported';
+    }
+    var manifestJson = runtime.getManifest();
+    if(typeof manifestJson == 'undefined') {
+        failed = true;
+        failMessage = 'manifest.json is not defined';
+    } else if(typeof manifestJson.oauth2 == 'undefined') {
+        failed = true;
+        failMessage = 'oauth2 missing from manifest.json';
+    } else if(typeof manifestJson.oauth2.client_id == 'undefined') {
+        failed = true;
+        failMessage = 'client_id missing from manifest.json';
+    } else if(typeof manifestJson.oauth2.scopes == 'undefined') {
+        failed = true;
+        failMessage = 'scopes missing from manifest.json';
+    }
+
+    if(failed === true) {
+        chrome.runtime.lastError = { 'message' : failMessage };
+        fail();
+    }
+
+    var authURLBase = 'https://accounts.google.com/o/oauth2/auth?response_type=token';
+    var redirect_uri = 'http://www.google.com';
+    var client_id = manifestJson.oauth2.client_id;
+    var scope = manifestJson.oauth2.scopes;
+    var finalURL = authURLBase + '&redirect_uri=' + encodeURIComponent(redirect_uri) + '&client_id=' + encodeURIComponent(client_id) + '&scope=' + encodeURIComponent(scope.join('&'));
+
+    _launchInAppBrowser(finalURL, redirect_uri, function(newLoc) {
+        var token = _getParameterFromUrl(newLoc, 'access_token', '#');
+        if(typeof token == 'undefined') {
+            chrome.runtime.lastError = { 'message' : 'The redirect uri did not have the access token' };
+            fail();
+        } else {
+            win(token);
+        }
+    });
+}
+
+function _getParameterFromUrl(url, param, startString, endString) {
+    var splitUrl = url;
+    var urlParts;
+    if(typeof startString != 'undefined') {
+        urlParts = splitUrl.split(startString);
+        if(urlParts.length < 2) {
+            return;
+        } else {
+            splitUrl = urlParts[1];
+        }
+    }
+    if(typeof endString != 'undefined') {
+        urlParts = splitUrl.split(endString);
+        splitUrl = urlParts[0];
+    }
+    var vars = splitUrl.split('&');
+    for (var i = 0; i < vars.length; i++) {
+        var pair = vars[i].split('=');
+        // If first entry with this name
+        if (pair[0] === param) {
+            return decodeURIComponent(pair[1]);
+        }
+    }
+}
+
+function _launchInAppBrowser(authURL, redirectedURL, callback) {
+    var oAuthBrowser = window.open(authURL, '_blank', 'location=yes');
+    var listener = function(event) {
+        var newLoc = event.url;
+        if(newLoc.indexOf(redirectedURL) === 0 && newLoc.indexOf('#') !== -1) {
+            oAuthBrowser.removeEventListener('loadstart', listener);
+            oAuthBrowser.close();
+            callback(newLoc);
+        }
+    };
+    oAuthBrowser.addEventListener('loadstart', listener);
+}
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome.socket/socket.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.socket/socket.js b/www/crx_files/www/plugins/chrome.socket/socket.js
new file mode 100644
index 0000000..389eec9
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome.socket/socket.js
@@ -0,0 +1,216 @@
+cordova.define("chrome.socket.Socket", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var platform = cordova.require('cordova/platform');
+var exec = cordova.require('cordova/exec');
+
+exports.create = function(socketMode, stuff, callback) {
+    if (typeof stuff == 'function') {
+        callback = stuff;
+        stuff = {};
+    }
+    var win = callback && function(socketId) {
+        var socketInfo = {
+            socketId: socketId
+        };
+        callback(socketInfo);
+    };
+    exec(win, null, 'ChromeSocket', 'create', [socketMode]);
+};
+
+exports.destroy = function(socketId) {
+    exec(null, null, 'ChromeSocket', 'destroy', [socketId]);
+};
+
+
+exports.connect = function(socketId, address, port, callback) {
+    var win = callback && function() {
+        callback(0);
+    };
+    var fail = callback && function() {
+        callback(-1);
+    };
+    exec(win, fail, 'ChromeSocket', 'connect', [socketId, address, port]);
+};
+
+exports.bind = function(socketId, address, port, callback) {
+    var win = callback && function() {
+        callback(0);
+    };
+    var fail = callback && function() {
+        callback(-1);
+    };
+    exec(win, fail, 'ChromeSocket', 'bind', [socketId, address, port]);
+};
+
+exports.disconnect = function(socketId) {
+    exec(null, null, 'ChromeSocket', 'disconnect', [socketId]);
+};
+
+
+exports.read = function(socketId, bufferSize, callback) {
+    if (typeof bufferSize == 'function') {
+        callback = bufferSize;
+        bufferSize = 0;
+    }
+    var win = callback && function(data) {
+        var readInfo = {
+            resultCode: data.byteLength || 1,
+            data: data
+        };
+        callback(readInfo);
+    };
+    var fail = callback && function() {
+        var readInfo = {
+            resultCode: 0
+        };
+        callback(readInfo);
+    };
+    exec(win, fail, 'ChromeSocket', 'read', [socketId, bufferSize]);
+};
+
+exports.write = function(socketId, data, callback) {
+    var type = Object.prototype.toString.call(data).slice(8, -1);
+    if (type != 'ArrayBuffer') {
+        throw new Error('chrome.socket.write - data is not an ArrayBuffer! (Got: ' + type + ')');
+    }
+    var win = callback && function(bytesWritten) {
+        var writeInfo = {
+            bytesWritten: bytesWritten
+        };
+        callback(writeInfo);
+    };
+    var fail = callback && function() {
+        var writeInfo = {
+            bytesWritten: 0
+        };
+        callback(writeInfo);
+    };
+    exec(win, fail, 'ChromeSocket', 'write', [socketId, data]);
+};
+
+
+exports.recvFrom = function(socketId, bufferSize, callback) {
+    if (typeof bufferSize == 'function') {
+        callback = bufferSize;
+        bufferSize = 0;
+    }
+    var win;
+    if (platform.id == 'android') {
+        win = callback && (function() {
+            var data;
+            var call = 0;
+            return function(arg) {
+                if (call === 0) {
+                    data = arg;
+                    call++;
+                } else {
+                    var recvFromInfo = {
+                        resultCode: data.byteLength || 1,
+                        data: data,
+                        address: arg.address,
+                        port: arg.port
+                    };
+
+                    callback(recvFromInfo);
+                }
+            };
+        })();
+    } else {
+        win = callback && function(data, address, port) {
+            var recvFromInfo = {
+                resultCode: data.byteLength || 1,
+                data: data,
+                address: address,
+                port: port
+            };
+            callback(recvFromInfo);
+        };
+    }
+
+    var fail = callback && function() {
+        var readInfo = {
+            resultCode: 0
+        };
+        callback(readInfo);
+    };
+    exec(win, fail, 'ChromeSocket', 'recvFrom', [socketId, bufferSize]);
+};
+
+exports.sendTo = function(socketId, data, address, port, callback) {
+    var type = Object.prototype.toString.call(data).slice(8, -1);
+    if (type != 'ArrayBuffer') {
+        throw new Error('chrome.socket.write - data is not an ArrayBuffer! (Got: ' + type + ')');
+    }
+    var win = callback && function(bytesWritten) {
+        var writeInfo = {
+            bytesWritten: bytesWritten
+        };
+        callback(writeInfo);
+    };
+    var fail = callback && function() {
+        var writeInfo = {
+            bytesWritten: 0
+        };
+        callback(writeInfo);
+    };
+    exec(win, fail, 'ChromeSocket', 'sendTo', [{ socketId: socketId, address: address, port: port }, data]);
+};
+
+
+exports.listen = function(socketId, address, port, backlog, callback) {
+    if (typeof backlog == 'function') {
+        callback = backlog;
+        backlog = 0;
+    }
+    var win = callback && function() {
+        callback(0);
+    };
+    var fail = callback && function() {
+        callback(-1);
+    };
+    exec(win, fail, 'ChromeSocket', 'listen', [socketId, address, port, backlog]);
+};
+
+exports.accept = function(socketId, callback) {
+    var win = callback && function(acceptedSocketId) {
+        var acceptInfo = {
+            resultCode: 0,
+            socketId: acceptedSocketId
+        };
+        callback(acceptInfo);
+    };
+    exec(win, null, 'ChromeSocket', 'accept', [socketId]);
+};
+
+
+exports.setKeepAlive = function() {
+    console.warn('chrome.socket.setKeepAlive not implemented yet');
+};
+
+exports.setNoDelay = function() {
+    console.warn('chrome.socket.setNoDelay not implemented yet');
+};
+
+exports.getInfo = function(socketId, callback) {
+    if (platform.id == 'android') {
+        console.warn('chrome.socket.getInfo not implemented yet');
+        return;
+    }
+    var win = callback && function(result) {
+        result.connected = !!result.connected;
+        callback(result);
+    };
+    exec(win, null, 'ChromeSocket', 'getInfo', [socketId]);
+};
+
+exports.getNetworkList = function(callback) {
+    if (platform.id == 'android') {
+        console.warn('chrome.socket.getNetworkList not implemented yet');
+        return;
+    }
+    exec(callback, null, 'ChromeSocket', 'getNetworkList', []);
+};
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome.storage/storage.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.storage/storage.js b/www/crx_files/www/plugins/chrome.storage/storage.js
new file mode 100644
index 0000000..4d6da75
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome.storage/storage.js
@@ -0,0 +1,202 @@
+cordova.define("chrome.storage.Storage", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var exports = module.exports;
+var exec = cordova.require('cordova/exec');
+
+function StorageChange(oldValue, newValue) {
+    this.oldValue = oldValue;
+    this.newValue = newValue;
+}
+
+function _jsonReplacer(key) {
+    // Don't use the value passed in since it has already gone through toJSON().
+    var value = this[key];
+    // Refer to:
+    // chrome/src/content/renderer/v8_value_converter_impl.cc&l=165
+    if (value && (typeof value == 'object' || typeof value == 'function')) {
+        var typeName = Object.prototype.toString.call(value).slice(8, -1);
+        if (typeName != 'Array' && typeName != 'Object') {
+            value = {};
+        }
+    }
+    return value;
+}
+
+function _scrubValues(o) {
+    if (typeof o != 'undefined') {
+        var t = JSON.stringify(o, _jsonReplacer);
+        return JSON.parse(t);
+    }
+}
+
+function _calculateChanges(oldKeyVals, newKeyVals) {
+    var ret = {};
+    for(var key in newKeyVals) {
+        if (newKeyVals.hasOwnProperty(key)) {
+            ret[key] = new StorageChange(oldKeyVals[key], newKeyVals[key]);
+        }
+    }
+    return ret;
+}
+
+function _convertToObject(obj) {
+    var ret;
+    if (Array.isArray(obj)) {
+        ret = {};
+        for(var i = 0; i < obj.length; i++) {
+            ret[obj[i]] = undefined;
+        }
+    } else if (typeof obj == 'object') {
+        ret = obj;
+    } else if (typeof obj === 'string') {
+        ret = {};
+        ret[obj] = undefined;
+    }
+    return ret;
+}
+
+function StorageArea(syncStorage, changedEvent) {
+    this._sync = syncStorage;
+    this._changedEvent = changedEvent;
+}
+
+StorageArea.prototype._getAreaName = function() {
+    return (this._sync? 'sync' : 'local');
+};
+
+StorageArea.prototype.get = function(keys, callback) {
+    if (typeof keys == 'function') {
+        callback = keys;
+        keys = null;
+    } else if (typeof keys === 'string') {
+        keys = [keys];
+    }
+    var win = callback && function(args) {
+        callback(args);
+    };
+    var fail = callback && function() {
+        callback();
+    };
+    var param = _scrubValues(keys);
+    exec(win, fail, 'ChromeStorage', 'get', [this._sync, param]);
+};
+
+StorageArea.prototype.getBytesInUse = function(keys, callback) {
+    if (typeof keys == 'function') {
+        callback = keys;
+        keys = null;
+    } else if (typeof keys === 'string') {
+        keys = [keys];
+    }
+    var win = callback && function(bytes) {
+        callback(bytes);
+    };
+    var fail = callback && function() {
+        callback(-1);
+    };
+    var param = _scrubValues(keys);
+    exec(win, fail, 'ChromeStorage', 'getBytesInUse', [this._sync, param]);
+};
+
+StorageArea.prototype.set = function(keyVals, callback) {
+    if (typeof keyVals == 'function') {
+        callback = keyVals;
+        keyVals = null;
+    }
+    var self = this;
+    var param = _scrubValues(keyVals);
+    var fail = callback && function() {
+        callback(-1);
+    };
+    var win;
+    if(self._changedEvent.hasListeners()) {
+        win = function(oldKeyVals) {
+            if(callback) {
+                callback(0);
+            }
+            var newKeyVals = _convertToObject(param);
+            var storageChanges = _calculateChanges(oldKeyVals, newKeyVals);
+            self._changedEvent.fire(storageChanges, self._getAreaName());
+        };
+    } else {
+        win = callback && function() {
+            callback(0);
+        };
+    }
+    exec(win, fail, 'ChromeStorage', 'set', [self._sync, param]);
+};
+
+StorageArea.prototype.remove = function(keys, callback) {
+    if (typeof keys == 'function') {
+        callback = keys;
+        keys = null;
+    } else if (typeof keys === 'string') {
+        keys = [keys];
+    }
+    var self = this;
+    var param = _scrubValues(keys);
+    var fail = callback && function() {
+        callback(-1);
+    };
+    var win;
+    if(self._changedEvent.hasListeners()) {
+        win = function(oldKeyVals) {
+            if(callback) {
+                callback(0);
+            }
+            var newKeyVals = _convertToObject(Object.keys(oldKeyVals));
+            var storageChanges = _calculateChanges(oldKeyVals, newKeyVals);
+            self._changedEvent.fire(storageChanges, self._getAreaName());
+        };
+    } else {
+        win = callback && function() {
+            callback(0);
+        };
+    }
+    exec(win, fail, 'ChromeStorage', 'remove', [self._sync, param]);
+};
+
+StorageArea.prototype.clear = function(callback) {
+    var self = this;
+    var fail = callback && function() {
+        callback(-1);
+    };
+    var win;
+    if(self._changedEvent.hasListeners()) {
+       win = function(oldKeyVals) {
+           if(callback) {
+               callback(0);
+           }
+           var newKeyVals = _convertToObject(Object.keys(oldKeyVals));
+           var storageChanges = _calculateChanges(oldKeyVals, newKeyVals);
+           self._changedEvent.fire(storageChanges, self._getAreaName());
+       };
+    } else {
+        win = callback && function() {
+            callback(0);
+        };
+    }
+    exec(win, fail, 'ChromeStorage', 'clear', [self._sync]);
+};
+
+// TODO(braden): How do we want to handle this event when we're not in a Chrome app?
+var Event = require('chrome.common.events');
+if (Event) {
+  exports.onChanged = new Event('onChanged');
+}
+
+var local = new StorageArea(false, exports.onChanged);
+local.QUOTA_BYTES = 5242880;
+var sync = new StorageArea(true, exports.onChanged);
+sync.MAX_ITEMS = 512;
+sync.MAX_WRITE_OPERATIONS_PER_HOUR = 1000;
+sync.QUOTA_BYTES_PER_ITEM = 4096;
+sync.MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE = 10;
+sync.QUOTA_BYTES = 102400;
+
+exports.local = local;
+exports.sync = sync;
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome/api/app/runtime.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/app/runtime.js b/www/crx_files/www/plugins/chrome/api/app/runtime.js
new file mode 100644
index 0000000..4a2288c
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome/api/app/runtime.js
@@ -0,0 +1,7 @@
+cordova.define("chrome.app.runtime", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var Event = require('chrome.common.events');
+exports.onLaunched = new Event('onLaunched');
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome/api/app/window.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/app/window.js b/www/crx_files/www/plugins/chrome/api/app/window.js
new file mode 100644
index 0000000..3a6484d
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome/api/app/window.js
@@ -0,0 +1,156 @@
+cordova.define("chrome.app.window", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var Event = require('chrome.common.events');
+var mobile = require('chrome.mobile.impl');
+
+// The AppWindow created by chrome.app.window.create.
+var createdAppWindow = null;
+var dummyNode = document.createElement('a');
+
+function AppWindow() {
+  this.contentWindow = mobile.fgWindow;
+  this.id = '';
+}
+
+function unsupportedApi(api) {
+  return function() {
+    console.warn(api + ' is not supported on mobile.');
+  };
+}
+
+AppWindow.prototype = {
+  restore: unsupportedApi('AppWindow.restore'),
+  moveTo: unsupportedApi('AppWindow.moveTo'),
+  clearAttention: unsupportedApi('AppWindow.clearAttention'),
+  minimize: unsupportedApi('AppWindow.minimize'),
+  drawAttention: unsupportedApi('AppWindow.drawAttention'),
+  focus: unsupportedApi('AppWindow.focus'),
+  resizeTo: unsupportedApi('AppWindow.resizeTo'),
+  maximize: unsupportedApi('AppWindow.maximize'),
+  close: unsupportedApi('AppWindow.close'),
+  setBounds: unsupportedApi('AppWindow.setBounds'),
+  onBoundsChanged: new Event('onBoundsChanged'),
+  onClosed: new Event('onClosed')
+};
+AppWindow.prototype.getBounds = function() {
+  return {
+    width: 0,
+    height: 0,
+    left: 0,
+    top: 0
+  };
+};
+
+function copyAttributes(srcNode, destNode) {
+  var attrs = srcNode.attributes;
+  for (var i = 0, attr; attr = attrs[i]; ++i) {
+    destNode.setAttribute(attr.name, attr.value);
+  }
+}
+
+function applyAttributes(attrText, destNode) {
+  dummyNode.innerHTML = '<a ' + attrText + '>';
+  copyAttributes(dummyNode.firstChild, destNode);
+}
+
+// Evals the scripts serially since sometimes browsers don't execute
+// them in the order they are injected :(.
+// TODO: This is clearly slower for multiple scripts. We could maybe see if
+// injecting after DOM mutation events fire?
+function evalScripts(rootNode, afterFunc) {
+  var scripts = Array.prototype.slice.call(rootNode.getElementsByTagName('script'));
+  var doc = rootNode.ownerDocument;
+  function helper() {
+    var script = scripts.shift();
+    if (!script) {
+      afterFunc && afterFunc();
+      // Don't bother with inline scripts since they aren't evalled on desktop.
+    } else if (script.src) {
+      var replacement = doc.createElement('script');
+      copyAttributes(script, replacement);
+      replacement.onload = helper;
+      script.parentNode.replaceChild(replacement, script);
+    } else {
+      helper();
+    }
+  }
+  helper();
+}
+
+function rewritePage(pageContent, filePath) {
+  var fgBody = mobile.fgWindow.document.body;
+  var fgHead = fgBody.previousElementSibling;
+
+  // fgHead.innerHTML causes a DOMException on Android 2.3.
+  while (fgHead.lastChild) {
+    fgHead.removeChild(fgHead.lastChild);
+  }
+
+  var startIndex = pageContent.search(/<html([\s\S]*?)>/i);
+  if (startIndex != -1) {
+    startIndex += RegExp.lastMatch.length;
+    // Copy over the attributes of the <html> tag.
+    applyAttributes(RegExp.lastParen, fgBody.parentNode);
+  } else {
+    startIndex = 0;
+  }
+
+  function afterBase() {
+    fgHead.insertAdjacentHTML('beforeend', headHtml);
+    evalScripts(fgHead, function() {
+      mobile.eventIframe.insertAdjacentHTML('afterend', pageContent);
+      evalScripts(fgBody)
+    });
+  }
+  // Put everything before the body tag in the head.
+  var endIndex = pageContent.search(/<body([\s\S]*?)>/i);
+  if (endIndex == -1) {
+    mobile.eventIframe.insertAdjacentHTML('afterend', 'Load error: Page is missing body tag.');
+  } else {
+    applyAttributes(RegExp.lastParen, fgBody);
+
+    // Don't bother removing the <body>, </body>, </html>. The browser's sanitizer removes them for us.
+    var headHtml = pageContent.slice(startIndex, endIndex);
+    pageContent = pageContent.slice(endIndex);
+
+    fgHead.insertAdjacentHTML('beforeend', '<link rel="stylesheet" href="chromeappstyles.css">');
+    var baseUrl = filePath.replace(/\/.*?$/, '');
+    if (baseUrl != filePath) {
+      fgHead.insertAdjacentHTML('beforeend', '<base href="' + encodeURIComponent(baseUrl) + '/">\n');
+      // setTimeout required for <base> to take effect for <link> elements (browser bug).
+      window.setTimeout(afterBase, 0);
+    } else {
+      afterBase();
+    }
+  }
+}
+
+exports.create = function(filePath, options, callback) {
+  if (createdAppWindow) {
+    console.log('ERROR - chrome.app.window.create called multiple times. This is unsupported.');
+    return;
+  }
+  createdAppWindow = new AppWindow();
+  var xhr = new XMLHttpRequest();
+  xhr.open('GET', filePath, true);
+  xhr.onreadystatechange = function() {
+    if (xhr.readyState == 4) {
+      // Call the callback before the page contents loads.
+      if (callback) {
+        callback(createdAppWindow);
+      }
+      var pageContent = xhr.responseText || 'Page load failed.';
+      rewritePage(pageContent, filePath);
+      cordova.fireWindowEvent('DOMContentReady');
+      cordova.fireWindowEvent('load');
+    }
+  };
+  xhr.send();
+};
+
+exports.current = function() {
+  return window == mobile.fgWindow ? createdAppWindow : null;
+};
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome/api/bootstrap.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/bootstrap.js b/www/crx_files/www/plugins/chrome/api/bootstrap.js
new file mode 100644
index 0000000..51c28dc
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome/api/bootstrap.js
@@ -0,0 +1,13 @@
+cordova.define("chrome.bootstrap", function(require, exports, module) {// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Initialization code for the Chrome plugins API.
+// Adds a deviceready listener that initializes the Chrome wrapper.
+
+console.log('adding event');
+document.addEventListener('deviceready', function() {
+  console.log('deviceready caught');
+  require('chrome.mobile.impl').init();
+});
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome/api/helpers/stubs.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/helpers/stubs.js b/www/crx_files/www/plugins/chrome/api/helpers/stubs.js
new file mode 100644
index 0000000..ef57b83
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome/api/helpers/stubs.js
@@ -0,0 +1,11 @@
+cordova.define("chrome.helpers.stubs", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+exports.createStub = function(obj, propName, value) {
+  obj.__defineGetter__(propName, function() {
+    console.warn('Access made to stub: ' + obj.__namespace__ + '.' + propName);
+    return value;
+  });
+};
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome/api/mobile.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/mobile.js b/www/crx_files/www/plugins/chrome/api/mobile.js
new file mode 100644
index 0000000..28af8b8
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome/api/mobile.js
@@ -0,0 +1,58 @@
+cordova.define("chrome.mobile.impl", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var chrome = window.chrome;
+
+exports.fgWindow = window;
+exports.bgWindow = null;
+exports.eventIframe = null;
+
+function createBgChrome() {
+  return {
+    __proto__: chrome,
+    app: {
+      __proto__: chrome.app,
+      window: {
+        __proto__: chrome.app.window,
+        current: function() { return null; }
+      }
+    }
+  };
+}
+
+exports.init = function() {
+  // Self-destruct so that code in here can be GC'ed.
+  exports.init = null;
+  var iframe = document.createElement('iframe');
+  iframe.src = 'chromebgpage.html';
+  iframe.style.display = 'none';
+  exports.eventIframe = iframe;
+  document.body.appendChild(iframe);
+};
+
+exports.bgInit = function(bgWnd) {
+  // Self-destruct so that code in here can be GC'ed.
+  exports.bgInit = null;
+  exports.bgWindow = bgWnd;
+  bgWnd.chrome = createBgChrome();
+  bgWnd.cordova = cordova;
+  exports.fgWindow.opener = exports.bgWindow;
+
+  function onLoad() {
+    bgWnd.removeEventListener('load', onLoad, false);
+    setTimeout(function() {
+      chrome.app.runtime.onLaunched.fire();
+    }, 0);
+  }
+  bgWnd.addEventListener('load', onLoad, false);
+
+  var manifestJson = chrome.runtime.getManifest();
+  var scripts = manifestJson.app.background.scripts;
+  var toWrite = '';
+  for (var i = 0, src; src = scripts[i]; ++i) {
+    toWrite += '<script src="' + encodeURI(src) + '"></sc' + 'ript>\n';
+  }
+  bgWnd.document.write(toWrite);
+};
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/crx_files/www/plugins/chrome/api/runtime.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/runtime.js b/www/crx_files/www/plugins/chrome/api/runtime.js
new file mode 100644
index 0000000..58b3970
--- /dev/null
+++ b/www/crx_files/www/plugins/chrome/api/runtime.js
@@ -0,0 +1,58 @@
+cordova.define("chrome.runtime", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var argscheck = cordova.require('cordova/argscheck');
+var Event = require('chrome.common.events');
+var stubs = require('chrome.helpers.stubs');
+var mobile = require('chrome.mobile.impl');
+var manifestJson = null;
+
+exports.onSuspend = new Event('onSuspend');
+exports.onInstalled = new Event('onInstalled');
+exports.onStartup = new Event('onStartup');
+exports.onSuspendCanceled = new Event('onSuspendCanceled');
+exports.onUpdateAvailable = new Event('onUpdateAvailable');
+
+var original_addListener = exports.onSuspend.addListener;
+
+// Uses a trampoline to bind the Cordova pause event on the first call.
+exports.onSuspend.addListener = function(f) {
+  window.document.addEventListener('pause', exports.onSuspend.fire, false);
+  exports.onSuspend.addListener = original_addListener;
+  exports.onSuspend.addListener(f);
+};
+
+exports.getManifest = function() {
+  if (!manifestJson) {
+    var xhr = new XMLHttpRequest();
+    xhr.open('GET', 'manifest.json', false /* sync */);
+    xhr.send(null);
+    manifestJson = eval('(' + xhr.responseText + ')'); //JSON.parse(xhr.responseText);
+  }
+  return manifestJson;
+};
+
+exports.getBackgroundPage = function(callback) {
+  argscheck.checkArgs('f', 'chrome.runtime.getBackgroundPage', arguments);
+  setTimeout(function() {
+    callback(mobile.bgWindow);
+  }, 0);
+};
+
+exports.getURL = function(subResource) {
+  argscheck.checkArgs('s', 'chrome.runtime.getURL', arguments);
+  if (subResource.charAt(0) == '/') {
+    subResource = subResource.slice(1);
+  }
+  var prefix = location.href.replace(/[^\/]*$/, '');
+  return prefix + subResource;
+};
+
+exports.reload = function() {
+  location.reload();
+};
+
+stubs.createStub(exports, 'id', '{appId}');
+stubs.createStub(exports, 'requestUpdateCheck', function(){});
+});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d045574b/www/js/CrxPackageHandler.js
----------------------------------------------------------------------
diff --git a/www/js/CrxPackageHandler.js b/www/js/CrxPackageHandler.js
new file mode 100644
index 0000000..2627fd7
--- /dev/null
+++ b/www/js/CrxPackageHandler.js
@@ -0,0 +1,54 @@
+(function(){
+    "use strict";
+    /* global myApp */
+    myApp.run(["AppsService", "ResourcesLoader", function(AppsService, ResourcesLoader){
+
+        function copyFile(startUrl, targetLocation){
+            /************ Begin Work around for File system bug ************/
+            if(targetLocation.indexOf("file://") === 0) {
+                targetLocation = targetLocation.substring("file://".length);
+            }
+            /************ End Work around for File system bug **************/
+            return ResourcesLoader.xhrGet(startUrl)
+            .then(function(xhr){
+                return ResourcesLoader.ensureDirectoryExists(targetLocation)
+                .then(function(){
+                    return ResourcesLoader.writeFileContents(targetLocation, xhr.responseText);
+                });
+            });
+        }
+
+        AppsService.registerPackageHandler("crx", {
+            extractPackageToDirectory : function (fileName, outputDirectory){
+                return ResourcesLoader.ensureDirectoryExists(outputDirectory + "/www")
+                .then(function(){
+                    return ResourcesLoader.extractZipFile(fileName, outputDirectory + "/www");
+                })
+                .then(function(){
+                    return Q.all([
+                        copyFile("cdv-app-harness:///direct/cordova.js", outputDirectory + "/www/cordova.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/config.android.xml", outputDirectory + "/config.android.xml"),
+                        copyFile("cdv-app-harness:///direct/crx_files/config.ios.xml", outputDirectory + "/config.ios.xml"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/cordova_plugins.json", outputDirectory + "/www/cordova_plugins.json"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/chromeapp.html", outputDirectory + "/www/chromeapp.html"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/chromeappstyles.css", outputDirectory + "/www/chromeappstyles.css"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/chromebgpage.html", outputDirectory + "/www/chromebgpage.html"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/app/runtime.js", outputDirectory + "/www/plugins/chrome/api/app/runtime.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/app/window.js", outputDirectory + "/www/plugins/chrome/api/app/window.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/bootstrap.js", outputDirectory + "/www/plugins/chrome/api/bootstrap.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/helpers/stubs.js", outputDirectory + "/www/plugins/chrome/api/helpers/stubs.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/mobile.js", outputDirectory + "/www/plugins/chrome/api/mobile.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/runtime.js", outputDirectory + "/www/plugins/chrome/api/runtime.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.common/events.js", outputDirectory + "/www/plugins/chrome.common/events.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.fileSystem/fileSystem.js", outputDirectory + "/www/plugins/chrome.fileSystem/fileSystem.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.i18n/i18n.js", outputDirectory + "/www/plugins/chrome.i18n/i18n.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.identity/identity.js", outputDirectory + "/www/plugins/chrome.identity/identity.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.socket/socket.js", outputDirectory + "/www/plugins/chrome.socket/socket.js"),
+                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.storage/storage.js", outputDirectory + "/www/plugins/chrome.storage/storage.js")
+                    ]);
+                });
+            }
+        });
+
+    }]);
+})();
\ No newline at end of file


[9/9] git commit: Add BarcodeScanner support (optional dependency)

Posted by br...@apache.org.
Add BarcodeScanner support (optional dependency)


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/f8f93699
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/f8f93699
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/f8f93699

Branch: refs/heads/master
Commit: f8f936997ff29fd10175370871bc452149ddfae1
Parents: 8c5698e
Author: Braden Shepherdson <br...@gmail.com>
Authored: Tue Jun 25 11:57:03 2013 -0700
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Tue Jun 25 11:57:03 2013 -0700

----------------------------------------------------------------------
 README.md                |  3 ++-
 www/cdvah_js/AddCtrl.js  | 28 +++++++++++++++++++++++++++-
 www/cdvah_views/add.html |  1 +
 3 files changed, 30 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/f8f93699/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 8e36c2c..36567cb 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,8 @@ An wrapper app for Cordova that can download and run Cordova apps as well as Chr
 
         cordova platform add android ios
 
-* Add the `zip` ([](https://github.com/MobileChromeApps/zip)) and `AppBundle` ([](https://github.com/MobileChromeApps/AppBundle)) plugins to the project (`cordova plugin add ...`).
+* Add the `zip` ([](https://github.com/MobileChromeApps/zip)) and `AppBundle` ([](https://github.com/MobileChromeApps/AppBundle)) plugins to the project (`cordova plugin add ...`)
+* If you want to be able to scan QR codes instead of typing URLs, add the `BarcodeScanner` ([](https://github.com/filmaj/BarcodeScanner)) plugin.
 * If you want to support Chrome apps, also add the `MobileChromeApps` `chrome-bootstrap` plugin, and any other Chrome APIs you want to support (`socket`, `identity`, etc.).
     * After each `cordova prepare`, you'll have to edit the `config.xml` on each platform to remove the new `<content>` tag that looks like this:
 

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/f8f93699/www/cdvah_js/AddCtrl.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/AddCtrl.js b/www/cdvah_js/AddCtrl.js
index 394531c..54e73b0 100644
--- a/www/cdvah_js/AddCtrl.js
+++ b/www/cdvah_js/AddCtrl.js
@@ -1,7 +1,7 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.controller("AddCtrl", ["notifier", "$rootScope", "$scope", "$location", "AppsService", function (notifier, $rootScope, $scope, $location, AppsService) {
+    myApp.controller("AddCtrl", ["notifier", "$rootScope", "$scope", "$location", "$window", "AppsService", function (notifier, $rootScope, $scope, $location, $window, AppsService) {
 
         $rootScope.appTitle = 'Add App';
 
@@ -40,5 +40,31 @@
                 notifier.error('Error adding application: Unrecognized application source: ' + $scope.appData.appSource);
             }
         };
+
+        // True if the optional barcodescanner plugin is installed.
+        $scope.qr_enabled = !!$window.barcodescanner;
+
+        // Scans a QR code, placing the URL into the currently selected of source and pattern.
+        $scope.fetchQR = function() {
+            console.log('calling');
+            $window.barcodescanner.scan(function(result) {
+                console.log('success');
+                if (!result || result.cancelled || !result.text) {
+                    notifier.error('No QR code received.');
+                } else {
+                    if ($scope.appData.appSource == 'pattern') {
+                        $scope.appData.appSourcePattern = result.text;
+                    } else {
+                        $scope.appData.appSourceServe = result.text;
+                    }
+                    notifier.success('QR code received');
+                    $scope.$apply();
+                }
+            },
+            function(error) {
+                console.log('error: ' + error);
+                notifier.error('Error retrieving QR code: ' + error);
+            });
+        };
     }]);
 })();

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/f8f93699/www/cdvah_views/add.html
----------------------------------------------------------------------
diff --git a/www/cdvah_views/add.html b/www/cdvah_views/add.html
index a9eaaf4..a2602c8 100644
--- a/www/cdvah_views/add.html
+++ b/www/cdvah_views/add.html
@@ -18,6 +18,7 @@
         <span ng-show="addForm.appSourceServe.$error.pattern">Url must point to a config.xml file</span>
         <br />
     <div class="buttons">
+        <button class="topcoat-button" ng-click="fetchQR()" ng-show="qr_enabled">Scan QR Code</button><br />
         <button class="topcoat-button--cta" ng-click="addApp()" ng-disabled="!(addForm.$valid)">Add</button>
         <a href="#/"><button class="topcoat-button" ng-click="back()">Back</button></a>
     </div>


[5/9] git commit: Delete old copies of Chrome files from www/crx_files.

Posted by br...@apache.org.
Delete old copies of Chrome files from www/crx_files.

Only the config.platform.xml files are still used.


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/ee57b46c
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/ee57b46c
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/ee57b46c

Branch: refs/heads/master
Commit: ee57b46c34d4d6b518b4c9a15cb6778e2ee78629
Parents: e80bb1d
Author: Braden Shepherdson <br...@gmail.com>
Authored: Fri Jun 14 09:57:12 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:43:56 2013 -0400

----------------------------------------------------------------------
 www/crx_files/www/chromeapp.html                |  15 --
 www/crx_files/www/chromeappstyles.css           |  14 --
 www/crx_files/www/chromebgpage.html             |  11 -
 www/crx_files/www/cordova_plugins.json          |   1 -
 .../www/plugins/chrome.common/events.js         |  53 -----
 .../www/plugins/chrome.fileSystem/fileSystem.js | 142 ------------
 www/crx_files/www/plugins/chrome.i18n/i18n.js   | 185 ----------------
 .../www/plugins/chrome.identity/identity.js     | 161 --------------
 .../www/plugins/chrome.socket/socket.js         | 216 -------------------
 .../www/plugins/chrome.storage/storage.js       | 202 -----------------
 .../www/plugins/chrome/api/app/runtime.js       |   7 -
 .../www/plugins/chrome/api/app/window.js        | 156 --------------
 .../www/plugins/chrome/api/bootstrap.js         |  13 --
 .../www/plugins/chrome/api/helpers/stubs.js     |  11 -
 www/crx_files/www/plugins/chrome/api/mobile.js  |  58 -----
 www/crx_files/www/plugins/chrome/api/runtime.js |  58 -----
 16 files changed, 1303 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/chromeapp.html
----------------------------------------------------------------------
diff --git a/www/crx_files/www/chromeapp.html b/www/crx_files/www/chromeapp.html
deleted file mode 100644
index 3cbd68d..0000000
--- a/www/crx_files/www/chromeapp.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2012 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<html>
-    <head>
-        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-        <meta name="format-detection" content="telephone=no">
-        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
-        <script src="cordova.js"></script>
-    </head>
-    <body></body>
-</html>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/chromeappstyles.css
----------------------------------------------------------------------
diff --git a/www/crx_files/www/chromeappstyles.css b/www/crx_files/www/chromeappstyles.css
deleted file mode 100644
index 277f4fe..0000000
--- a/www/crx_files/www/chromeappstyles.css
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Contains extra user-agent styles to apply to all Chrome App windows.
- *
- * These should be kept in sync with:
- * http://code.google.com/searchframe#OAMlx_jo-ck/src/chrome/renderer/resources/extensions/platform_app.css
- */
-body { -webkit-user-select: none; }
-html, body { overflow: hidden; }

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/chromebgpage.html
----------------------------------------------------------------------
diff --git a/www/crx_files/www/chromebgpage.html b/www/crx_files/www/chromebgpage.html
deleted file mode 100644
index b732eaa..0000000
--- a/www/crx_files/www/chromebgpage.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2012 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<html>
-  <body>
-    <script>parent.chrome.mobile.impl.bgInit(this)</script>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/cordova_plugins.json
----------------------------------------------------------------------
diff --git a/www/crx_files/www/cordova_plugins.json b/www/crx_files/www/cordova_plugins.json
deleted file mode 100644
index fe11f7c..0000000
--- a/www/crx_files/www/cordova_plugins.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"file":"plugins/chrome/api/bootstrap.js","id":"chrome.bootstrap","runs":true},{"file":"plugins/chrome/api/app/runtime.js","id":"chrome.app.runtime","clobbers":["chrome.app.runtime"]},{"file":"plugins/chrome/api/app/window.js","id":"chrome.app.window","clobbers":["chrome.app.window"]},{"file":"plugins/chrome/api/helpers/stubs.js","id":"chrome.helpers.stubs"},{"file":"plugins/chrome/api/mobile.js","id":"chrome.mobile.impl","clobbers":["chrome.mobile.impl"]},{"file":"plugins/chrome/api/runtime.js","id":"chrome.runtime","clobbers":["chrome.runtime"]},{"file":"plugins/chrome.common/events.js","id":"chrome.common.events","clobbers":["chrome.Event"]},{"file":"plugins/chrome.fileSystem/fileSystem.js","id":"chrome.fileSystem.FileSystem","clobbers":["chrome.fileSystem"]},{"file":"plugins/chrome.i18n/i18n.js","id":"chrome.i18n.I18n","clobbers":["chrome.i18n"]},{"file":"plugins/chrome.identity/identity.js","id":"chrome.identity.Identity","clobbers":["chrome.identity","chrome.experimental.iden
 tity"]},{"file":"plugins/chrome.socket/socket.js","id":"chrome.socket.Socket","clobbers":["chrome.socket"]},{"file":"plugins/chrome.storage/storage.js","id":"chrome.storage.Storage","clobbers":["chrome.storage"]}]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome.common/events.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.common/events.js b/www/crx_files/www/plugins/chrome.common/events.js
deleted file mode 100644
index 6f868b1..0000000
--- a/www/crx_files/www/plugins/chrome.common/events.js
+++ /dev/null
@@ -1,53 +0,0 @@
-cordova.define("chrome.common.events", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var Event = function(opt_eventName) {
-  this.name = opt_eventName || '';
-  this.listeners = [];
-};
-
-// Deliberately not filtering functions that are already added.
-// I tested on desktop and it will call your callback once for each addListener.
-Event.prototype.addListener = function(cb) {
-  this.listeners.push(cb);
-};
-
-Event.prototype.findListener_ = function(cb) {
-  for(var i = 0; i < this.listeners.length; i++) {
-    if (this.listeners[i] == cb) {
-      return i;
-    }
-  }
-
-  return -1;
-};
-
-Event.prototype.removeListener = function(cb) {
-  var index = this.findListener_(cb);
-  if (index >= 0) {
-    this.listeners.splice(index, 1);
-  }
-};
-
-Event.prototype.hasListener = function(cb) {
-  return this.findListener_(cb) >= 0;
-};
-
-Event.prototype.hasListeners = function() {
-  return this.listeners.length > 0;
-};
-
-Event.prototype.fire = function() {
-  for (var i = 0; i < this.listeners.length; i++) {
-    this.listeners[i].apply(this, arguments);
-  }
-};
-
-// Stubs since we don't support Rules.
-Event.prototype.addRules = function() { };
-Event.prototype.getRules = function() { };
-Event.prototype.removeRules = function() { };
-
-module.exports = Event;
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js b/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js
deleted file mode 100644
index ce613e5..0000000
--- a/www/crx_files/www/plugins/chrome.fileSystem/fileSystem.js
+++ /dev/null
@@ -1,142 +0,0 @@
-cordova.define("chrome.fileSystem.FileSystem", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var platformId = cordova.require('cordova/platform').id;
-var FileEntry = cordova.require('cordova/plugin/FileEntry');
-
-exports.getDisplayPath = function(fileEntry, callback) {
-  callback(fileEntry.fullPath);
-};
-
-exports.getWritableEntry = function(fileEntry, callback) {
-  callback(null);
-};
-
-exports.isWritableEntry = function(fileEntry, callback) {
-  callback(false);
-};
-
-exports.chooseEntry = function(options, callback) {
-  // Ensure that the type is either unspecified or specified as 'openFile', as nothing else is supported.
-  if (options.type && options.type != 'openFile') {
-    // TODO(maxw): Determine a "more correct" way to fail here.
-    callback(null);
-    return;
-  }
-
-  // Create the callback for getFile.
-  // It creates a file entry and passes it to the chooseEntry callback.
-  var onFileReceived = function(nativeUri) {
-    var onUriResolved = function(fileEntry) {
-      callback(fileEntry);
-    };
-
-    var onUriResolveError = function(e) {
-      console.log(e.target.error.code);
-    };
-
-    resolveLocalFileSystemURI(nativeUri, onUriResolved, onUriResolveError);
-  };
-
-  if (platformId == 'ios') {
-    getFileIos(options, onFileReceived);
-  } else if (platformId == 'android') {
-    getFileAndroid(options, onFileReceived);
-  }
-};
-
-function getFileIos(options, onFileReceivedCallback) {
-  // Determine the media type.
-  var mediaType = determineMediaType(options.accepts, options.acceptsAllTypes);
-
-  // Prepare the options for getting the file.
-  var getFileOptions = { destinationType: navigator.camera.DestinationType.NATIVE_URI,
-                         sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
-                         mediaType: mediaType };
-
-  // Use the camera to get an image or video.
-  navigator.camera.getPicture(onFileReceivedCallback, null, getFileOptions);
-}
-
-function getFileAndroid(options, onFileReceivedCallback) {
-  var AndroidFileChooser = cordova.require('cordova/plugin/android/filechooser');
-
-  // Determine the relevant mime types.
-  var mimeTypes = determineMimeTypes(options.accepts, options.acceptsAllTypes);
-
-  // Use the file chooser to get a file.
-  AndroidFileChooser.chooseFile(onFileReceivedCallback, null, mimeTypes);
-}
-
-function determineMediaType(acceptOptions, acceptsAllTypes) {
-  if (acceptsAllTypes) {
-    return navigator.camera.MediaType.ALLMEDIA;
-  }
-
-  var imageMimeTypeRegex = /^image\//;
-  var videoMimeTypeRegex = /^video\//;
-  var imageExtensionRegex = /^(?:jpg|png)$/;
-  var videoExtensionRegex = /^mov$/;
-  var imagesAllowed = false;
-  var videosAllowed = false;
-
-  // Iterate through all accept options.
-  // If we see anything image related, allow images.  If we see anything video related, allow videos.
-  if (acceptOptions) {
-    for (var i = 0; i < acceptOptions.length; i++) {
-      if (acceptOptions[i].mimeTypes) {
-        for (var j = 0; j < acceptOptions[i].mimeTypes.length; j++) {
-          if (imageMimeTypeRegex.test(acceptOptions[i].mimeTypes[j])) {
-            imagesAllowed = true;
-          } else if (videoMimeTypeRegex.test(acceptOptions[i].mimeTypes[j])) {
-            videosAllowed = true;
-          }
-        }
-      }
-      if (acceptOptions[i].extensions) {
-        for (var k = 0; k < acceptOptions[i].extensions.length; k++) {
-          if (imageExtensionRegex.test(acceptOptions[i].extensions[k])) {
-            imagesAllowed = true;
-          } else if (videoExtensionRegex.test(acceptOptions[i].extensions[k])) {
-            videosAllowed = true;
-          }
-        }
-      }
-    }
-  }
-
-  if (imagesAllowed && !videosAllowed) {
-    return navigator.camera.MediaType.PICTURE;
-  } else if (!imagesAllowed && videosAllowed) {
-    return navigator.camera.MediaType.VIDEO;
-  }
-
-  return navigator.camera.MediaType.ALLMEDIA;
-}
-
-function determineMimeTypes(acceptOptions, acceptsAllTypes) {
-  if (acceptsAllTypes) {
-    return [ '*/*' ];
-  }
-
-  // Pull out all the mime types.
-  // TODO(maxw): Determine mime types from extensions and add them to the returned list.
-  var mimeTypes = [ ];
-  if (acceptOptions) {
-    for (var i = 0; i < acceptOptions.length; i++) {
-      if (acceptOptions[i].mimeTypes) {
-        for (var j = 0; j < acceptOptions[i].mimeTypes.length; j++) {
-          mimeTypes.push(acceptOptions[i].mimeTypes[j]);
-        }
-      }
-    }
-  }
-
-  if (mimeTypes.length !== 0) {
-    return mimeTypes;
-  }
-
-  return [ '*/*' ];
-}
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome.i18n/i18n.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.i18n/i18n.js b/www/crx_files/www/plugins/chrome.i18n/i18n.js
deleted file mode 100644
index 905466c..0000000
--- a/www/crx_files/www/plugins/chrome.i18n/i18n.js
+++ /dev/null
@@ -1,185 +0,0 @@
-cordova.define("chrome.i18n.I18n", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var exec = cordova.require('cordova/exec');
-var runtime = require('chrome.runtime');
-
-exports.getAcceptLanguages = function(callback) {
-    // In the chrome implementation, acceptLanguage value can change with updates so we make a native call to get the system language
-    exec(callback, callback, 'ChromeI18n', 'getAcceptLanguages', []);
-};
-
-exports.getMessage = function(messageName, substitutions) {
-    // In the chrome implementation, the locale to translate to DOES NOT change with updates, it is keyed of window.navigator.language which is static for a session.
-    // This is implemented in _getLocalesToUse()
-    if(
-        (typeof messageName !== 'string') ||
-        (Array.isArray(substitutions) && substitutions.length > 9)
-    ) {
-        return;
-    }
-    messageName = messageName.toLowerCase();
-    var ret = '';
-    var localeChain = _getLocalesToUse();
-    var contentsForMessageName = _getMessageFromMessageJson(messageName, localeChain);
-    if(contentsForMessageName) {
-        ret = _applySubstitutions(contentsForMessageName, substitutions);
-    }
-    return ret;
-};
-
-function _endsWith(string, endString) {
-    if(endString.length > string.length) {
-        return false;
-    } else {
-        return (string.lastIndexOf(endString) === string.length - endString.length);
-    }
-}
-
-function _getFilePathForLocale(locale) {
-    return 'locales/' + locale.toLowerCase() + '/messages.json';
-}
-
-function _toLowerCaseMessageAndPlaceholders(obj) {
-    if(typeof obj !== 'undefined') {
-        var newObj = {};
-        for(var field in obj) {
-            if(obj[field].placeholders) {
-                var newPlaceholders = {};
-                for(var placeholderField in obj[field].placeholders) {
-                    newPlaceholders[placeholderField.toLowerCase()] = obj[field].placeholders[placeholderField];
-                }
-                obj[field].placeholders = newPlaceholders;
-            }
-            newObj[field.toLowerCase()] = obj[field];
-        }
-        return newObj;
-    }
-}
-
-function _getDefaultLocale() {
-    var manifestJson = runtime.getManifest();
-    if(manifestJson.default_locale) {
-        return manifestJson.default_locale;
-    } else {
-        throw new Error('Default locale not defined');
-    }
-}
-
-var memoizedJsonContents = {};
-function _getMessageFromMessageJson(messageName, localeChain) {
-    for(var i = 0; i < localeChain.length; i++) {
-        var locale = localeChain[i];
-        if (!memoizedJsonContents[locale]) {
-            var fileName = _getFilePathForLocale(locale);
-            var xhr = new XMLHttpRequest();
-            xhr.open('GET', fileName, false /* sync */);
-            xhr.send(null);
-            var contents = eval('(' + xhr.responseText + ')');
-            // convert all fields to lower case to check case insensitively
-            contents = _toLowerCaseMessageAndPlaceholders(contents);
-            memoizedJsonContents[locale] = contents;
-        }
-        if(memoizedJsonContents[locale][messageName]) {
-            return memoizedJsonContents[locale][messageName];
-        }
-    }
-}
-
-function _isLocaleAvailable(locale) {
-    var fileName = _getFilePathForLocale(locale);
-    var xhr = new XMLHttpRequest();
-    xhr.open('HEAD', fileName, false /* sync */);
-    xhr.send(null);
-    availableLocales[locale] = (xhr.status === 200);
-}
-
-var chosenLocales;
-function _getLocalesToUse() {
-    if(!chosenLocales) {
-        // language returned by window.navigator is in format en-US, need to change it to en_us
-        var windowLocale = window.navigator.language.replace('-', '_').toLowerCase();
-        var localesToUse = [windowLocale];
-        // Construct fallback chain
-        var lastIndex;
-        while((lastIndex = windowLocale.lastIndexOf('_')) !== -1) {
-            windowLocale = windowLocale.substring(0, lastIndex);
-            localesToUse.push(windowLocale);
-        }
-        var defaultLocale = _getDefaultLocale().toLowerCase();
-        if(localesToUse.indexOf(defaultLocale) == -1) {
-            localesToUse.push(defaultLocale);
-        }
-
-        chosenLocales = [] ;
-        for(var i = 0; i < localesToUse.length; i++) {
-            var currentLocale = localesToUse[i];
-            if(_isLocaleAvailable(currentLocale)) {
-                chosenLocales.push(currentLocale);
-            }
-        }
-    }
-    if(chosenLocales.length == 0) {
-        throw new Error('No usable locale.');
-    }
-    return chosenLocales;
-}
-
-function _getSubstitutionString(match, substitutions) {
-    if(match == '$$') {
-        return '$';
-    } else if(match == '$') {
-        return '';
-    }
-    else {
-        var locBaseOne = parseInt(match.substring(1));
-        if(isNaN(locBaseOne) || locBaseOne <= 0) {
-            return '';
-        }
-
-        if(substitutions[locBaseOne - 1]) {
-            return substitutions[locBaseOne - 1];
-        } else {
-            return '';
-        }
-    }
-}
-
-function _getPlaceholderText(placeholders, substitutions, match) {
-    // Switch to lower case to do case insensitive checking for matches
-    var placeholderField = match.substring(1, match.length - 1);
-    placeholderField = placeholderField.toLowerCase();
-    if(placeholders[placeholderField]) {
-        // form $1, $2 etc or '$$' or '$'
-        var placeholderText = placeholders[placeholderField].content.replace(/\$(([0-9]+)|\$)?/g, function(match) {
-            var substitutionString = _getSubstitutionString(match, substitutions);
-            return substitutionString;
-        });
-        return placeholderText;
-    } else {
-        return '';
-    }
-}
-
-function _applySubstitutions(messageObject, substitutions) {
-    if(typeof substitutions === 'undefined') {
-        substitutions = [];
-    } else if(Object.prototype.toString.call(substitutions) !== '[object Array]') {
-        substitutions = [substitutions];
-    }
-    // Look for any strings of form $WORD$ eg: $1stName$, form $1, $2 etc or any lone '$'
-    // Order of preference is as in this comment
-    var ret = messageObject.message.replace( /\$(([0-9a-zA-Z_]*\$)|([0-9]*))?/g, function(matchedString) {
-        // check which category of matchedString it is
-        if(matchedString.match(/\$[0-9a-zA-Z_]+\$/)) { // form $WORD$
-            var placeholderText = _getPlaceholderText(messageObject.placeholders, substitutions, matchedString);
-            return placeholderText;
-        } else { // form $1, $2 etc or '$$' or '$'
-            var substitutionString = _getSubstitutionString(matchedString, substitutions);
-            return substitutionString;
-        }
-    });
-    return ret;
-}
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome.identity/identity.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.identity/identity.js b/www/crx_files/www/plugins/chrome.identity/identity.js
deleted file mode 100644
index 54f1597..0000000
--- a/www/crx_files/www/plugins/chrome.identity/identity.js
+++ /dev/null
@@ -1,161 +0,0 @@
-cordova.define("chrome.identity.Identity", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var platformId = cordova.require('cordova/platform').id;
-var runtime = require('chrome.runtime');
-
-exports.TokenDetails = function(interactive) {
-    this.interactive = interactive || false;
-};
-
-exports.WebAuthFlowDetails = function(url, interactive, width, height, left, top) {
-    if (typeof url == 'undefined') {
-        throw new Error('Url required');
-    }
-    this.url = url;
-    this.interactive = interactive || false;
-    this.width = width;
-    this.height = height;
-    this.left = left;
-    this.top = top;
-};
-
-exports.getAuthToken = function(details, callback) {
-    if(typeof details == 'function') {
-        callback = details;
-        details = new exports.TokenDetails();
-    }
-    if (typeof callback == 'undefined') {
-        chrome.runtime.lastError = { 'message' : 'Callback function required' };
-        // Not calling callback as it wasnt provided
-        return;
-    }
-    var win = function(token) {
-        callback(token);
-    };
-    var fail = function() {
-        callback();
-    };
-
-    if (platformId == 'android') {
-        // Use native implementation for logging into google accounts
-        cordova.exec(win, fail, 'ChromeIdentity', 'getAuthToken', [details]);
-    } else {
-        // Use web app oauth flow
-        _getAuthTokenJS(win, fail, details);
-    }
-};
-
-exports.launchWebAuthFlow = function(details, callback) {
-    var failed = false;
-    var failMessage;
-    if (typeof details == 'undefined') {
-        failed = true;
-        failMessage = 'WebAuthFlowDetails required';
-    } else if (typeof callback == 'undefined') {
-        failed = true;
-        failMessage = 'Callback function required';
-    }
-
-    if(failed === true) {
-        chrome.runtime.lastError = { 'message' : failMessage };
-        // Not calling callback as it wasnt provided
-        return;
-    }
-
-    var finalURL = details.url;
-    var extractedRedirectedURL = _getParameterFromUrl(finalURL, 'redirect_uri', '?', '#');
-
-    if(typeof extractedRedirectedURL == 'undefined') {
-        chrome.runtime.lastError = { 'message' : 'launchWebAuthFlow: Parameter redirect_uri not found.' };
-        callback();
-    } else {
-        _launchInAppBrowser(finalURL, extractedRedirectedURL, callback);
-    }
-};
-
-function _getAuthTokenJS(win, fail , details) {
-    var failed = false;
-    var failMessage;
-    if(!details.interactive) {
-        // We cannot support non interactive mode.
-        // This requires the ability to use invisible InAppBrowser windows, which is not currently supported
-        failed = true;
-        failMessage = 'Unsupported mode - Non interactive mode is not supported';
-    }
-    var manifestJson = runtime.getManifest();
-    if(typeof manifestJson == 'undefined') {
-        failed = true;
-        failMessage = 'manifest.json is not defined';
-    } else if(typeof manifestJson.oauth2 == 'undefined') {
-        failed = true;
-        failMessage = 'oauth2 missing from manifest.json';
-    } else if(typeof manifestJson.oauth2.client_id == 'undefined') {
-        failed = true;
-        failMessage = 'client_id missing from manifest.json';
-    } else if(typeof manifestJson.oauth2.scopes == 'undefined') {
-        failed = true;
-        failMessage = 'scopes missing from manifest.json';
-    }
-
-    if(failed === true) {
-        chrome.runtime.lastError = { 'message' : failMessage };
-        fail();
-    }
-
-    var authURLBase = 'https://accounts.google.com/o/oauth2/auth?response_type=token';
-    var redirect_uri = 'http://www.google.com';
-    var client_id = manifestJson.oauth2.client_id;
-    var scope = manifestJson.oauth2.scopes;
-    var finalURL = authURLBase + '&redirect_uri=' + encodeURIComponent(redirect_uri) + '&client_id=' + encodeURIComponent(client_id) + '&scope=' + encodeURIComponent(scope.join('&'));
-
-    _launchInAppBrowser(finalURL, redirect_uri, function(newLoc) {
-        var token = _getParameterFromUrl(newLoc, 'access_token', '#');
-        if(typeof token == 'undefined') {
-            chrome.runtime.lastError = { 'message' : 'The redirect uri did not have the access token' };
-            fail();
-        } else {
-            win(token);
-        }
-    });
-}
-
-function _getParameterFromUrl(url, param, startString, endString) {
-    var splitUrl = url;
-    var urlParts;
-    if(typeof startString != 'undefined') {
-        urlParts = splitUrl.split(startString);
-        if(urlParts.length < 2) {
-            return;
-        } else {
-            splitUrl = urlParts[1];
-        }
-    }
-    if(typeof endString != 'undefined') {
-        urlParts = splitUrl.split(endString);
-        splitUrl = urlParts[0];
-    }
-    var vars = splitUrl.split('&');
-    for (var i = 0; i < vars.length; i++) {
-        var pair = vars[i].split('=');
-        // If first entry with this name
-        if (pair[0] === param) {
-            return decodeURIComponent(pair[1]);
-        }
-    }
-}
-
-function _launchInAppBrowser(authURL, redirectedURL, callback) {
-    var oAuthBrowser = window.open(authURL, '_blank', 'location=yes');
-    var listener = function(event) {
-        var newLoc = event.url;
-        if(newLoc.indexOf(redirectedURL) === 0 && newLoc.indexOf('#') !== -1) {
-            oAuthBrowser.removeEventListener('loadstart', listener);
-            oAuthBrowser.close();
-            callback(newLoc);
-        }
-    };
-    oAuthBrowser.addEventListener('loadstart', listener);
-}
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome.socket/socket.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.socket/socket.js b/www/crx_files/www/plugins/chrome.socket/socket.js
deleted file mode 100644
index 389eec9..0000000
--- a/www/crx_files/www/plugins/chrome.socket/socket.js
+++ /dev/null
@@ -1,216 +0,0 @@
-cordova.define("chrome.socket.Socket", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var platform = cordova.require('cordova/platform');
-var exec = cordova.require('cordova/exec');
-
-exports.create = function(socketMode, stuff, callback) {
-    if (typeof stuff == 'function') {
-        callback = stuff;
-        stuff = {};
-    }
-    var win = callback && function(socketId) {
-        var socketInfo = {
-            socketId: socketId
-        };
-        callback(socketInfo);
-    };
-    exec(win, null, 'ChromeSocket', 'create', [socketMode]);
-};
-
-exports.destroy = function(socketId) {
-    exec(null, null, 'ChromeSocket', 'destroy', [socketId]);
-};
-
-
-exports.connect = function(socketId, address, port, callback) {
-    var win = callback && function() {
-        callback(0);
-    };
-    var fail = callback && function() {
-        callback(-1);
-    };
-    exec(win, fail, 'ChromeSocket', 'connect', [socketId, address, port]);
-};
-
-exports.bind = function(socketId, address, port, callback) {
-    var win = callback && function() {
-        callback(0);
-    };
-    var fail = callback && function() {
-        callback(-1);
-    };
-    exec(win, fail, 'ChromeSocket', 'bind', [socketId, address, port]);
-};
-
-exports.disconnect = function(socketId) {
-    exec(null, null, 'ChromeSocket', 'disconnect', [socketId]);
-};
-
-
-exports.read = function(socketId, bufferSize, callback) {
-    if (typeof bufferSize == 'function') {
-        callback = bufferSize;
-        bufferSize = 0;
-    }
-    var win = callback && function(data) {
-        var readInfo = {
-            resultCode: data.byteLength || 1,
-            data: data
-        };
-        callback(readInfo);
-    };
-    var fail = callback && function() {
-        var readInfo = {
-            resultCode: 0
-        };
-        callback(readInfo);
-    };
-    exec(win, fail, 'ChromeSocket', 'read', [socketId, bufferSize]);
-};
-
-exports.write = function(socketId, data, callback) {
-    var type = Object.prototype.toString.call(data).slice(8, -1);
-    if (type != 'ArrayBuffer') {
-        throw new Error('chrome.socket.write - data is not an ArrayBuffer! (Got: ' + type + ')');
-    }
-    var win = callback && function(bytesWritten) {
-        var writeInfo = {
-            bytesWritten: bytesWritten
-        };
-        callback(writeInfo);
-    };
-    var fail = callback && function() {
-        var writeInfo = {
-            bytesWritten: 0
-        };
-        callback(writeInfo);
-    };
-    exec(win, fail, 'ChromeSocket', 'write', [socketId, data]);
-};
-
-
-exports.recvFrom = function(socketId, bufferSize, callback) {
-    if (typeof bufferSize == 'function') {
-        callback = bufferSize;
-        bufferSize = 0;
-    }
-    var win;
-    if (platform.id == 'android') {
-        win = callback && (function() {
-            var data;
-            var call = 0;
-            return function(arg) {
-                if (call === 0) {
-                    data = arg;
-                    call++;
-                } else {
-                    var recvFromInfo = {
-                        resultCode: data.byteLength || 1,
-                        data: data,
-                        address: arg.address,
-                        port: arg.port
-                    };
-
-                    callback(recvFromInfo);
-                }
-            };
-        })();
-    } else {
-        win = callback && function(data, address, port) {
-            var recvFromInfo = {
-                resultCode: data.byteLength || 1,
-                data: data,
-                address: address,
-                port: port
-            };
-            callback(recvFromInfo);
-        };
-    }
-
-    var fail = callback && function() {
-        var readInfo = {
-            resultCode: 0
-        };
-        callback(readInfo);
-    };
-    exec(win, fail, 'ChromeSocket', 'recvFrom', [socketId, bufferSize]);
-};
-
-exports.sendTo = function(socketId, data, address, port, callback) {
-    var type = Object.prototype.toString.call(data).slice(8, -1);
-    if (type != 'ArrayBuffer') {
-        throw new Error('chrome.socket.write - data is not an ArrayBuffer! (Got: ' + type + ')');
-    }
-    var win = callback && function(bytesWritten) {
-        var writeInfo = {
-            bytesWritten: bytesWritten
-        };
-        callback(writeInfo);
-    };
-    var fail = callback && function() {
-        var writeInfo = {
-            bytesWritten: 0
-        };
-        callback(writeInfo);
-    };
-    exec(win, fail, 'ChromeSocket', 'sendTo', [{ socketId: socketId, address: address, port: port }, data]);
-};
-
-
-exports.listen = function(socketId, address, port, backlog, callback) {
-    if (typeof backlog == 'function') {
-        callback = backlog;
-        backlog = 0;
-    }
-    var win = callback && function() {
-        callback(0);
-    };
-    var fail = callback && function() {
-        callback(-1);
-    };
-    exec(win, fail, 'ChromeSocket', 'listen', [socketId, address, port, backlog]);
-};
-
-exports.accept = function(socketId, callback) {
-    var win = callback && function(acceptedSocketId) {
-        var acceptInfo = {
-            resultCode: 0,
-            socketId: acceptedSocketId
-        };
-        callback(acceptInfo);
-    };
-    exec(win, null, 'ChromeSocket', 'accept', [socketId]);
-};
-
-
-exports.setKeepAlive = function() {
-    console.warn('chrome.socket.setKeepAlive not implemented yet');
-};
-
-exports.setNoDelay = function() {
-    console.warn('chrome.socket.setNoDelay not implemented yet');
-};
-
-exports.getInfo = function(socketId, callback) {
-    if (platform.id == 'android') {
-        console.warn('chrome.socket.getInfo not implemented yet');
-        return;
-    }
-    var win = callback && function(result) {
-        result.connected = !!result.connected;
-        callback(result);
-    };
-    exec(win, null, 'ChromeSocket', 'getInfo', [socketId]);
-};
-
-exports.getNetworkList = function(callback) {
-    if (platform.id == 'android') {
-        console.warn('chrome.socket.getNetworkList not implemented yet');
-        return;
-    }
-    exec(callback, null, 'ChromeSocket', 'getNetworkList', []);
-};
-
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome.storage/storage.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome.storage/storage.js b/www/crx_files/www/plugins/chrome.storage/storage.js
deleted file mode 100644
index 4d6da75..0000000
--- a/www/crx_files/www/plugins/chrome.storage/storage.js
+++ /dev/null
@@ -1,202 +0,0 @@
-cordova.define("chrome.storage.Storage", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var exports = module.exports;
-var exec = cordova.require('cordova/exec');
-
-function StorageChange(oldValue, newValue) {
-    this.oldValue = oldValue;
-    this.newValue = newValue;
-}
-
-function _jsonReplacer(key) {
-    // Don't use the value passed in since it has already gone through toJSON().
-    var value = this[key];
-    // Refer to:
-    // chrome/src/content/renderer/v8_value_converter_impl.cc&l=165
-    if (value && (typeof value == 'object' || typeof value == 'function')) {
-        var typeName = Object.prototype.toString.call(value).slice(8, -1);
-        if (typeName != 'Array' && typeName != 'Object') {
-            value = {};
-        }
-    }
-    return value;
-}
-
-function _scrubValues(o) {
-    if (typeof o != 'undefined') {
-        var t = JSON.stringify(o, _jsonReplacer);
-        return JSON.parse(t);
-    }
-}
-
-function _calculateChanges(oldKeyVals, newKeyVals) {
-    var ret = {};
-    for(var key in newKeyVals) {
-        if (newKeyVals.hasOwnProperty(key)) {
-            ret[key] = new StorageChange(oldKeyVals[key], newKeyVals[key]);
-        }
-    }
-    return ret;
-}
-
-function _convertToObject(obj) {
-    var ret;
-    if (Array.isArray(obj)) {
-        ret = {};
-        for(var i = 0; i < obj.length; i++) {
-            ret[obj[i]] = undefined;
-        }
-    } else if (typeof obj == 'object') {
-        ret = obj;
-    } else if (typeof obj === 'string') {
-        ret = {};
-        ret[obj] = undefined;
-    }
-    return ret;
-}
-
-function StorageArea(syncStorage, changedEvent) {
-    this._sync = syncStorage;
-    this._changedEvent = changedEvent;
-}
-
-StorageArea.prototype._getAreaName = function() {
-    return (this._sync? 'sync' : 'local');
-};
-
-StorageArea.prototype.get = function(keys, callback) {
-    if (typeof keys == 'function') {
-        callback = keys;
-        keys = null;
-    } else if (typeof keys === 'string') {
-        keys = [keys];
-    }
-    var win = callback && function(args) {
-        callback(args);
-    };
-    var fail = callback && function() {
-        callback();
-    };
-    var param = _scrubValues(keys);
-    exec(win, fail, 'ChromeStorage', 'get', [this._sync, param]);
-};
-
-StorageArea.prototype.getBytesInUse = function(keys, callback) {
-    if (typeof keys == 'function') {
-        callback = keys;
-        keys = null;
-    } else if (typeof keys === 'string') {
-        keys = [keys];
-    }
-    var win = callback && function(bytes) {
-        callback(bytes);
-    };
-    var fail = callback && function() {
-        callback(-1);
-    };
-    var param = _scrubValues(keys);
-    exec(win, fail, 'ChromeStorage', 'getBytesInUse', [this._sync, param]);
-};
-
-StorageArea.prototype.set = function(keyVals, callback) {
-    if (typeof keyVals == 'function') {
-        callback = keyVals;
-        keyVals = null;
-    }
-    var self = this;
-    var param = _scrubValues(keyVals);
-    var fail = callback && function() {
-        callback(-1);
-    };
-    var win;
-    if(self._changedEvent.hasListeners()) {
-        win = function(oldKeyVals) {
-            if(callback) {
-                callback(0);
-            }
-            var newKeyVals = _convertToObject(param);
-            var storageChanges = _calculateChanges(oldKeyVals, newKeyVals);
-            self._changedEvent.fire(storageChanges, self._getAreaName());
-        };
-    } else {
-        win = callback && function() {
-            callback(0);
-        };
-    }
-    exec(win, fail, 'ChromeStorage', 'set', [self._sync, param]);
-};
-
-StorageArea.prototype.remove = function(keys, callback) {
-    if (typeof keys == 'function') {
-        callback = keys;
-        keys = null;
-    } else if (typeof keys === 'string') {
-        keys = [keys];
-    }
-    var self = this;
-    var param = _scrubValues(keys);
-    var fail = callback && function() {
-        callback(-1);
-    };
-    var win;
-    if(self._changedEvent.hasListeners()) {
-        win = function(oldKeyVals) {
-            if(callback) {
-                callback(0);
-            }
-            var newKeyVals = _convertToObject(Object.keys(oldKeyVals));
-            var storageChanges = _calculateChanges(oldKeyVals, newKeyVals);
-            self._changedEvent.fire(storageChanges, self._getAreaName());
-        };
-    } else {
-        win = callback && function() {
-            callback(0);
-        };
-    }
-    exec(win, fail, 'ChromeStorage', 'remove', [self._sync, param]);
-};
-
-StorageArea.prototype.clear = function(callback) {
-    var self = this;
-    var fail = callback && function() {
-        callback(-1);
-    };
-    var win;
-    if(self._changedEvent.hasListeners()) {
-       win = function(oldKeyVals) {
-           if(callback) {
-               callback(0);
-           }
-           var newKeyVals = _convertToObject(Object.keys(oldKeyVals));
-           var storageChanges = _calculateChanges(oldKeyVals, newKeyVals);
-           self._changedEvent.fire(storageChanges, self._getAreaName());
-       };
-    } else {
-        win = callback && function() {
-            callback(0);
-        };
-    }
-    exec(win, fail, 'ChromeStorage', 'clear', [self._sync]);
-};
-
-// TODO(braden): How do we want to handle this event when we're not in a Chrome app?
-var Event = require('chrome.common.events');
-if (Event) {
-  exports.onChanged = new Event('onChanged');
-}
-
-var local = new StorageArea(false, exports.onChanged);
-local.QUOTA_BYTES = 5242880;
-var sync = new StorageArea(true, exports.onChanged);
-sync.MAX_ITEMS = 512;
-sync.MAX_WRITE_OPERATIONS_PER_HOUR = 1000;
-sync.QUOTA_BYTES_PER_ITEM = 4096;
-sync.MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE = 10;
-sync.QUOTA_BYTES = 102400;
-
-exports.local = local;
-exports.sync = sync;
-
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome/api/app/runtime.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/app/runtime.js b/www/crx_files/www/plugins/chrome/api/app/runtime.js
deleted file mode 100644
index 4a2288c..0000000
--- a/www/crx_files/www/plugins/chrome/api/app/runtime.js
+++ /dev/null
@@ -1,7 +0,0 @@
-cordova.define("chrome.app.runtime", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var Event = require('chrome.common.events');
-exports.onLaunched = new Event('onLaunched');
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome/api/app/window.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/app/window.js b/www/crx_files/www/plugins/chrome/api/app/window.js
deleted file mode 100644
index 3a6484d..0000000
--- a/www/crx_files/www/plugins/chrome/api/app/window.js
+++ /dev/null
@@ -1,156 +0,0 @@
-cordova.define("chrome.app.window", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var Event = require('chrome.common.events');
-var mobile = require('chrome.mobile.impl');
-
-// The AppWindow created by chrome.app.window.create.
-var createdAppWindow = null;
-var dummyNode = document.createElement('a');
-
-function AppWindow() {
-  this.contentWindow = mobile.fgWindow;
-  this.id = '';
-}
-
-function unsupportedApi(api) {
-  return function() {
-    console.warn(api + ' is not supported on mobile.');
-  };
-}
-
-AppWindow.prototype = {
-  restore: unsupportedApi('AppWindow.restore'),
-  moveTo: unsupportedApi('AppWindow.moveTo'),
-  clearAttention: unsupportedApi('AppWindow.clearAttention'),
-  minimize: unsupportedApi('AppWindow.minimize'),
-  drawAttention: unsupportedApi('AppWindow.drawAttention'),
-  focus: unsupportedApi('AppWindow.focus'),
-  resizeTo: unsupportedApi('AppWindow.resizeTo'),
-  maximize: unsupportedApi('AppWindow.maximize'),
-  close: unsupportedApi('AppWindow.close'),
-  setBounds: unsupportedApi('AppWindow.setBounds'),
-  onBoundsChanged: new Event('onBoundsChanged'),
-  onClosed: new Event('onClosed')
-};
-AppWindow.prototype.getBounds = function() {
-  return {
-    width: 0,
-    height: 0,
-    left: 0,
-    top: 0
-  };
-};
-
-function copyAttributes(srcNode, destNode) {
-  var attrs = srcNode.attributes;
-  for (var i = 0, attr; attr = attrs[i]; ++i) {
-    destNode.setAttribute(attr.name, attr.value);
-  }
-}
-
-function applyAttributes(attrText, destNode) {
-  dummyNode.innerHTML = '<a ' + attrText + '>';
-  copyAttributes(dummyNode.firstChild, destNode);
-}
-
-// Evals the scripts serially since sometimes browsers don't execute
-// them in the order they are injected :(.
-// TODO: This is clearly slower for multiple scripts. We could maybe see if
-// injecting after DOM mutation events fire?
-function evalScripts(rootNode, afterFunc) {
-  var scripts = Array.prototype.slice.call(rootNode.getElementsByTagName('script'));
-  var doc = rootNode.ownerDocument;
-  function helper() {
-    var script = scripts.shift();
-    if (!script) {
-      afterFunc && afterFunc();
-      // Don't bother with inline scripts since they aren't evalled on desktop.
-    } else if (script.src) {
-      var replacement = doc.createElement('script');
-      copyAttributes(script, replacement);
-      replacement.onload = helper;
-      script.parentNode.replaceChild(replacement, script);
-    } else {
-      helper();
-    }
-  }
-  helper();
-}
-
-function rewritePage(pageContent, filePath) {
-  var fgBody = mobile.fgWindow.document.body;
-  var fgHead = fgBody.previousElementSibling;
-
-  // fgHead.innerHTML causes a DOMException on Android 2.3.
-  while (fgHead.lastChild) {
-    fgHead.removeChild(fgHead.lastChild);
-  }
-
-  var startIndex = pageContent.search(/<html([\s\S]*?)>/i);
-  if (startIndex != -1) {
-    startIndex += RegExp.lastMatch.length;
-    // Copy over the attributes of the <html> tag.
-    applyAttributes(RegExp.lastParen, fgBody.parentNode);
-  } else {
-    startIndex = 0;
-  }
-
-  function afterBase() {
-    fgHead.insertAdjacentHTML('beforeend', headHtml);
-    evalScripts(fgHead, function() {
-      mobile.eventIframe.insertAdjacentHTML('afterend', pageContent);
-      evalScripts(fgBody)
-    });
-  }
-  // Put everything before the body tag in the head.
-  var endIndex = pageContent.search(/<body([\s\S]*?)>/i);
-  if (endIndex == -1) {
-    mobile.eventIframe.insertAdjacentHTML('afterend', 'Load error: Page is missing body tag.');
-  } else {
-    applyAttributes(RegExp.lastParen, fgBody);
-
-    // Don't bother removing the <body>, </body>, </html>. The browser's sanitizer removes them for us.
-    var headHtml = pageContent.slice(startIndex, endIndex);
-    pageContent = pageContent.slice(endIndex);
-
-    fgHead.insertAdjacentHTML('beforeend', '<link rel="stylesheet" href="chromeappstyles.css">');
-    var baseUrl = filePath.replace(/\/.*?$/, '');
-    if (baseUrl != filePath) {
-      fgHead.insertAdjacentHTML('beforeend', '<base href="' + encodeURIComponent(baseUrl) + '/">\n');
-      // setTimeout required for <base> to take effect for <link> elements (browser bug).
-      window.setTimeout(afterBase, 0);
-    } else {
-      afterBase();
-    }
-  }
-}
-
-exports.create = function(filePath, options, callback) {
-  if (createdAppWindow) {
-    console.log('ERROR - chrome.app.window.create called multiple times. This is unsupported.');
-    return;
-  }
-  createdAppWindow = new AppWindow();
-  var xhr = new XMLHttpRequest();
-  xhr.open('GET', filePath, true);
-  xhr.onreadystatechange = function() {
-    if (xhr.readyState == 4) {
-      // Call the callback before the page contents loads.
-      if (callback) {
-        callback(createdAppWindow);
-      }
-      var pageContent = xhr.responseText || 'Page load failed.';
-      rewritePage(pageContent, filePath);
-      cordova.fireWindowEvent('DOMContentReady');
-      cordova.fireWindowEvent('load');
-    }
-  };
-  xhr.send();
-};
-
-exports.current = function() {
-  return window == mobile.fgWindow ? createdAppWindow : null;
-};
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome/api/bootstrap.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/bootstrap.js b/www/crx_files/www/plugins/chrome/api/bootstrap.js
deleted file mode 100644
index 51c28dc..0000000
--- a/www/crx_files/www/plugins/chrome/api/bootstrap.js
+++ /dev/null
@@ -1,13 +0,0 @@
-cordova.define("chrome.bootstrap", function(require, exports, module) {// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Initialization code for the Chrome plugins API.
-// Adds a deviceready listener that initializes the Chrome wrapper.
-
-console.log('adding event');
-document.addEventListener('deviceready', function() {
-  console.log('deviceready caught');
-  require('chrome.mobile.impl').init();
-});
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome/api/helpers/stubs.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/helpers/stubs.js b/www/crx_files/www/plugins/chrome/api/helpers/stubs.js
deleted file mode 100644
index ef57b83..0000000
--- a/www/crx_files/www/plugins/chrome/api/helpers/stubs.js
+++ /dev/null
@@ -1,11 +0,0 @@
-cordova.define("chrome.helpers.stubs", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-exports.createStub = function(obj, propName, value) {
-  obj.__defineGetter__(propName, function() {
-    console.warn('Access made to stub: ' + obj.__namespace__ + '.' + propName);
-    return value;
-  });
-};
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome/api/mobile.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/mobile.js b/www/crx_files/www/plugins/chrome/api/mobile.js
deleted file mode 100644
index 28af8b8..0000000
--- a/www/crx_files/www/plugins/chrome/api/mobile.js
+++ /dev/null
@@ -1,58 +0,0 @@
-cordova.define("chrome.mobile.impl", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var chrome = window.chrome;
-
-exports.fgWindow = window;
-exports.bgWindow = null;
-exports.eventIframe = null;
-
-function createBgChrome() {
-  return {
-    __proto__: chrome,
-    app: {
-      __proto__: chrome.app,
-      window: {
-        __proto__: chrome.app.window,
-        current: function() { return null; }
-      }
-    }
-  };
-}
-
-exports.init = function() {
-  // Self-destruct so that code in here can be GC'ed.
-  exports.init = null;
-  var iframe = document.createElement('iframe');
-  iframe.src = 'chromebgpage.html';
-  iframe.style.display = 'none';
-  exports.eventIframe = iframe;
-  document.body.appendChild(iframe);
-};
-
-exports.bgInit = function(bgWnd) {
-  // Self-destruct so that code in here can be GC'ed.
-  exports.bgInit = null;
-  exports.bgWindow = bgWnd;
-  bgWnd.chrome = createBgChrome();
-  bgWnd.cordova = cordova;
-  exports.fgWindow.opener = exports.bgWindow;
-
-  function onLoad() {
-    bgWnd.removeEventListener('load', onLoad, false);
-    setTimeout(function() {
-      chrome.app.runtime.onLaunched.fire();
-    }, 0);
-  }
-  bgWnd.addEventListener('load', onLoad, false);
-
-  var manifestJson = chrome.runtime.getManifest();
-  var scripts = manifestJson.app.background.scripts;
-  var toWrite = '';
-  for (var i = 0, src; src = scripts[i]; ++i) {
-    toWrite += '<script src="' + encodeURI(src) + '"></sc' + 'ript>\n';
-  }
-  bgWnd.document.write(toWrite);
-};
-});

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/ee57b46c/www/crx_files/www/plugins/chrome/api/runtime.js
----------------------------------------------------------------------
diff --git a/www/crx_files/www/plugins/chrome/api/runtime.js b/www/crx_files/www/plugins/chrome/api/runtime.js
deleted file mode 100644
index 58b3970..0000000
--- a/www/crx_files/www/plugins/chrome/api/runtime.js
+++ /dev/null
@@ -1,58 +0,0 @@
-cordova.define("chrome.runtime", function(require, exports, module) {// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var argscheck = cordova.require('cordova/argscheck');
-var Event = require('chrome.common.events');
-var stubs = require('chrome.helpers.stubs');
-var mobile = require('chrome.mobile.impl');
-var manifestJson = null;
-
-exports.onSuspend = new Event('onSuspend');
-exports.onInstalled = new Event('onInstalled');
-exports.onStartup = new Event('onStartup');
-exports.onSuspendCanceled = new Event('onSuspendCanceled');
-exports.onUpdateAvailable = new Event('onUpdateAvailable');
-
-var original_addListener = exports.onSuspend.addListener;
-
-// Uses a trampoline to bind the Cordova pause event on the first call.
-exports.onSuspend.addListener = function(f) {
-  window.document.addEventListener('pause', exports.onSuspend.fire, false);
-  exports.onSuspend.addListener = original_addListener;
-  exports.onSuspend.addListener(f);
-};
-
-exports.getManifest = function() {
-  if (!manifestJson) {
-    var xhr = new XMLHttpRequest();
-    xhr.open('GET', 'manifest.json', false /* sync */);
-    xhr.send(null);
-    manifestJson = eval('(' + xhr.responseText + ')'); //JSON.parse(xhr.responseText);
-  }
-  return manifestJson;
-};
-
-exports.getBackgroundPage = function(callback) {
-  argscheck.checkArgs('f', 'chrome.runtime.getBackgroundPage', arguments);
-  setTimeout(function() {
-    callback(mobile.bgWindow);
-  }, 0);
-};
-
-exports.getURL = function(subResource) {
-  argscheck.checkArgs('s', 'chrome.runtime.getURL', arguments);
-  if (subResource.charAt(0) == '/') {
-    subResource = subResource.slice(1);
-  }
-  var prefix = location.href.replace(/[^\/]*$/, '');
-  return prefix + subResource;
-};
-
-exports.reload = function() {
-  location.reload();
-};
-
-stubs.createStub(exports, 'id', '{appId}');
-stubs.createStub(exports, 'requestUpdateCheck', function(){});
-});


[4/9] git commit: Restyle to use Topcoat, popup notifications, and better UX.

Posted by br...@apache.org.
Restyle to use Topcoat, popup notifications, and better UX.


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/d871da2a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/d871da2a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/d871da2a

Branch: refs/heads/master
Commit: d871da2aca9297d6545b10e576e119d66f72a550
Parents: 9b881f4
Author: Braden Shepherdson <br...@gmail.com>
Authored: Wed Jun 19 16:02:16 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:43:56 2013 -0400

----------------------------------------------------------------------
 www/cdvah_index.html                 |  16 ++++-
 www/cdvah_js/AddCtrl.js              |  18 +++---
 www/cdvah_js/ListCtrl.js             |  22 ++++---
 www/cdvah_js/Notify.js               |  40 +++++++++++++
 www/cdvah_js/app.js                  |   2 +-
 www/cdvah_views/add.html             |  15 ++---
 www/cdvah_views/list.html            |  27 +++++----
 www/css/style.css                    |  30 ++++++++++
 www/css/topcoat-mobile-light.min.css |   1 +
 www/font/LICENSE.txt                 |  93 ++++++++++++++++++++++++++++++
 www/font/SourceSansPro-Light.otf     | Bin 0 -> 98972 bytes
 www/font/SourceSansPro-Regular.otf   | Bin 0 -> 101820 bytes
 www/font/SourceSansPro-Semibold.otf  | Bin 0 -> 101772 bytes
 13 files changed, 226 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_index.html
----------------------------------------------------------------------
diff --git a/www/cdvah_index.html b/www/cdvah_index.html
index 8850f80..64787aa 100644
--- a/www/cdvah_index.html
+++ b/www/cdvah_index.html
@@ -16,7 +16,19 @@
         <script type="text/javascript" src="cdvah_js/CdvhPackageHandler.js"></script>
         <script type="text/javascript" src="cdvah_js/ListCtrl.js"></script>
         <script type="text/javascript" src="cdvah_js/AddCtrl.js"></script>
+        <script type="text/javascript" src="cdvah_js/Notify.js"></script>
+        <link rel="stylesheet" type="text/css" href="css/topcoat-mobile-light.min.css" />
+        <link rel="stylesheet" type="text/css" href="css/style.css" />
     </head>
-    <body ng-app="CordovaAppHarness" ng-view>
+    <body ng-app="CordovaAppHarness">
+        <div class="topcoat-navigation-bar">
+            <div class="topcoat-navigation-bar__item center full">
+                <h1 class="topcoat-navigation-bar__title">{{ appTitle }}</h1>
+            </div>
+        </div>
+
+        <cdvah-notify></cdvah-notify>
+
+        <div ng-view></div>
     </body>
-</html>
\ No newline at end of file
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/AddCtrl.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/AddCtrl.js b/www/cdvah_js/AddCtrl.js
index 4fc52a4..394531c 100644
--- a/www/cdvah_js/AddCtrl.js
+++ b/www/cdvah_js/AddCtrl.js
@@ -1,7 +1,9 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.controller("AddCtrl", ["$scope", "AppsService", function ($scope, AppsService) {
+    myApp.controller("AddCtrl", ["notifier", "$rootScope", "$scope", "$location", "AppsService", function (notifier, $rootScope, $scope, $location, AppsService) {
+
+        $rootScope.appTitle = 'Add App';
 
         $scope.appData = {
             appName : "",
@@ -14,13 +16,13 @@
             var serviceCall;
             if($scope.appData.appSource === "pattern") {
                 if(!$scope.appData.appSourcePattern) {
-                    alert("Url of package not specified");
+                    notifier.error('Url of package not specified');
                     return;
                 }
                 serviceCall = AppsService.addAppFromPattern($scope.appData.appName, $scope.appData.appSourcePattern);
             } else if($scope.appData.appSource === "serve") {
                 if(!$scope.appData.appSourceServe) {
-                    alert("Url of config file not specified");
+                    notifier.error('Url of config file not specified');
                     return;
                 }
                 serviceCall = AppsService.addAppFromServe($scope.appData.appName, $scope.appData.appSourceServe);
@@ -28,15 +30,15 @@
 
             if(serviceCall){
                 serviceCall.then(function() {
-                    alert("Successfully installed");
+                    console.log('successfully installed');
+                    notifier.success('Successfully installed');
                 }, function(error) {
                     console.error(error);
-                    alert("Unable to add application because: \n" + error);
+                    notifier.error('Unable to add application because: ' + error.message);
                 });
             } else {
-                alert("Add application error: Unrecognized application source - " + $scope.appData.appSource);
+                notifier.error('Error adding application: Unrecognized application source: ' + $scope.appData.appSource);
             }
         };
     }]);
-
-})();
\ No newline at end of file
+})();

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/ListCtrl.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/ListCtrl.js b/www/cdvah_js/ListCtrl.js
index 938b5b2..3940554 100644
--- a/www/cdvah_js/ListCtrl.js
+++ b/www/cdvah_js/ListCtrl.js
@@ -1,9 +1,10 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.controller("ListCtrl", [ "$scope", "$routeParams", "AppsService", function ($scope, $routeParams, AppsService) {
+    myApp.controller("ListCtrl", [ "notifier", "$rootScope", "$scope", "$location", "$routeParams", "AppsService", function (notifier, $rootScope, $scope, $location, $routeParams, AppsService) {
 
         $scope.appsList = [];
+        $rootScope.appTitle = 'Cordova App Harness';
 
         function clearAppBundleAliases(){
             var deferred = Q.defer();
@@ -33,7 +34,7 @@
                     .then(AppsService.launchApp, function(e){
                         e = e || {};
                         console.error("Error launching last run app: " + e);
-                        alert("Error launching last run app. Please try again.");
+                        notifier.error("Error launching last run app. Please try again.");
                     });
                 }
                 else if($routeParams.updateLastLaunched) {
@@ -50,7 +51,7 @@
                     }, function(e){
                         e = e || {};
                         console.error("Error updating last run app: " + e);
-                        alert("Error updating last run app. Please try again.");
+                        notifier.error("Error updating last run app. Please try again.");
                     });
                 }
                 else {
@@ -79,7 +80,7 @@
             }, function(error){
                 var str = "There was an error retrieving the apps list";
                 console.error(str + ": " + error);
-                alert(str);
+                notifier.error(str);
             });
         };
 
@@ -87,17 +88,18 @@
             return AppsService.launchApp(app)
             .then(null, function(error){
                 console.error("Error during loading of app " + app + ": " + error);
-                alert("Something went wrong during the loading of the app. Please try again." + error);
+                notifier.error("Something went wrong during the loading of the app. Please try again." + error);
             });
         };
 
         $scope.updateApp = function(app) {
             return AppsService.updateApp(app)
             .then(function(){
-                alert("Updated successfully");
+                notifier.success("Updated successfully");
+                console.log('successfully updated');
             }, function(error){
                 console.error("Error during updating of app " + app + ": " + error);
-                alert("Something went wrong during the updating of the app. Please try again.");
+                notifier.error("Something went wrong during the updating of the app. Please try again.");
             });
         };
 
@@ -107,11 +109,13 @@
                 return AppsService.uninstallApp(app)
                 .then(function() { $scope.loadAppsList(true); }, function(error){
                     console.error("Error during uninstall of app " + app + ": " + error);
-                    alert("Something went wrong during the uninstall of the app. Please try again.");
+                    notifier.error("Something went wrong during the uninstall of the app. Please try again.");
                 });
             }
         };
 
         document.addEventListener("deviceready", initialise, false);
     }]);
-})();
\ No newline at end of file
+})();
+
+

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/Notify.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/Notify.js b/www/cdvah_js/Notify.js
new file mode 100644
index 0000000..921d15d
--- /dev/null
+++ b/www/cdvah_js/Notify.js
@@ -0,0 +1,40 @@
+(function() {
+    "use strict";
+    /* global myApp */
+    myApp.directive("cdvahNotify", [ "$rootScope", "$timeout", function($rootScope, $timeout) {
+        return {
+            scope: {},
+            restrict: 'E',
+            template: '<div class="notification-container" ng-show="showNotify"><div class="notification" ng-class="notification.css">{{ notification.message }}</div></div>',
+            replace: true,
+            link: function(scope, element, attrs) {
+                $rootScope.$watch('notification', function(newValue) {
+                    scope.showNotify = !!newValue;
+                    if (newValue) {
+                        scope.notification = {};
+                        scope.notification.message = newValue.message;
+                        scope.notification.css = 'notification-' + newValue.type;
+
+                        $timeout(function() {
+                            $rootScope.notification = undefined;
+                        }, 5000);
+                    }
+                });
+            }
+        };
+    }]);
+
+    myApp.factory('notifier', ['$rootScope', function($rootScope) {
+        return {
+            success: function(msg) {
+                $rootScope.notification = { message: msg, type: 'success' };
+                $rootScope.$apply();
+            },
+            error: function(msg) {
+                $rootScope.notification = { message: msg, type: 'error' };
+                $rootScope.$apply();
+            }
+        };
+    }]);
+})();
+

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/app.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/app.js b/www/cdvah_js/app.js
index a2d5488..105a10b 100644
--- a/www/cdvah_js/app.js
+++ b/www/cdvah_js/app.js
@@ -8,4 +8,4 @@ myApp.config(["$routeProvider", function($routeProvider){
         templateUrl: "cdvah_views/add.html",
         controller: "AddCtrl"
     });
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_views/add.html
----------------------------------------------------------------------
diff --git a/www/cdvah_views/add.html b/www/cdvah_views/add.html
index edb4dfb..a9eaaf4 100644
--- a/www/cdvah_views/add.html
+++ b/www/cdvah_views/add.html
@@ -1,6 +1,6 @@
 <form name="addForm" ng-controller="AddCtrl">
     <label for="inputAppName">Enter the App Name</label><br />
-    <input type="text" name="appName" ng-model="appData.appName" ng-pattern="/^[\w ]*$/" ng-maxlength="64" required />
+    <input class="topcoat-text-input" type="text" name="appName" ng-model="appData.appName" ng-pattern="/^[\w ]*$/" ng-maxlength="64" required />
     <span ng-show="addForm.appName.$error.required">Required</span>
     <span ng-show="addForm.appName.$error.pattern">Invalid characters used</span>
     <span ng-show="addForm.appName.$error.maxlength">Too long</span>
@@ -8,16 +8,17 @@
 
     <input type="radio" ng-model="appData.appSource" name="appSource" value="pattern" ng-checked="appData.appSource=='pattern'" />
         <label for="inputAppPattern">Enter the URL to a file</label><br />
-        <input id="inputAppPattern" type="text" name="appSourcePattern" ng-model="appData.appSourcePattern" ng-disabled="appData.appSource!='pattern'" ng-required="appData.appSource=='pattern'" autocorrect="off" autocapitalize="off" />
+        <input class="topcoat-text-input" id="inputAppPattern" type="text" name="appSourcePattern" ng-model="appData.appSourcePattern" ng-disabled="appData.appSource!='pattern'" ng-required="appData.appSource=='pattern'" autocorrect="off" autocapitalize="off" />
         <span ng-show="addForm.appSourcePattern.$error.required">Required</span>
         <br />
     <input type="radio" ng-model="appData.appSource" name="appSource" value="serve" ng-checked="appData.appSource=='serve'" />
         <label for="inputAppServe">Enter the URL to the server hosting the app</label><br />
-        <input id="inputAppServe" type="text" name="appSourceServe" ng-model="appData.appSourceServe" ng-disabled="appData.appSource!='serve'" ng-pattern="/.*\/config.xml(\?.*|#.*)?$/" ng-required="appData.appSource=='serve'" autocorrect="off" autocapitalize="off" />
+        <input class="topcoat-text-input" id="inputAppServe" type="text" name="appSourceServe" ng-model="appData.appSourceServe" ng-disabled="appData.appSource!='serve'" ng-pattern="/.*\/config.xml(\?.*|#.*)?$/" ng-required="appData.appSource=='serve'" autocorrect="off" autocapitalize="off" />
         <span ng-show="addForm.appSourceServe.$error.required">Required</span>
         <span ng-show="addForm.appSourceServe.$error.pattern">Url must point to a config.xml file</span>
         <br />
-    <button ng-click="addApp()" ng-disabled="!(addForm.$valid)">Add</button>
-    <br />
-    <a href="#/">Back To Main Menu</a>
-</form>
\ No newline at end of file
+    <div class="buttons">
+        <button class="topcoat-button--cta" ng-click="addApp()" ng-disabled="!(addForm.$valid)">Add</button>
+        <a href="#/"><button class="topcoat-button" ng-click="back()">Back</button></a>
+    </div>
+</form>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_views/list.html
----------------------------------------------------------------------
diff --git a/www/cdvah_views/list.html b/www/cdvah_views/list.html
index b563845..bc69941 100644
--- a/www/cdvah_views/list.html
+++ b/www/cdvah_views/list.html
@@ -1,12 +1,17 @@
-<ul>
-	<li ng-repeat="app in appsList"> 
-        <p>{{app.Name}}</p>
-        <p>Installed on: {{app.Installed}}</p>
-        <button ng-click="launchApp(app.Name)">Launch</button>
-		<button ng-click="updateApp(app.Name)" ng-disabled="app.Source==='serve'">Update</button>
-		<button ng-click="removeApp(app.Name)">Remove</button>
-	</li>
-</ul>
-<button ng-click="loadAppsList()">Reload Apps List</button>
+<div class="topcoat-list__container">
+    <h3 class="topcoat-list__header">Installed Apps</h3>
+    <ul class="topcoat-list">
+        <li class="topcoat-list__item" ng-repeat="app in appsList">
+            <p>{{app.Name}}</p>
+            <p>Installed on: {{app.Installed}}</p>
+            <button ng-click="launchApp(app.Name)">Launch</button>
+            <button ng-click="updateApp(app.Name)" ng-disabled="app.Source==='serve'">Update</button>
+            <button ng-click="removeApp(app.Name)">Remove</button>
+        </li>
+    </ul>
+</div>
 <br />
-<a href="#/add">Add new App</a>
\ No newline at end of file
+<div class="buttons">
+    <a href="#/add"><button class="topcoat-button--cta">Add app</button></a>
+    <button class="topcoat-button" ng-click="loadAppsList()">Reload</button>
+</div>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/css/style.css
----------------------------------------------------------------------
diff --git a/www/css/style.css b/www/css/style.css
new file mode 100644
index 0000000..d8554d1
--- /dev/null
+++ b/www/css/style.css
@@ -0,0 +1,30 @@
+.buttons {
+    margin: 15px;
+}
+
+.notification-container {
+    margin: 0;
+    padding: 0;
+
+    position: fixed;
+    bottom: 20px;
+    left: 0px;
+    right: 0px;
+    z-index: 3;
+}
+
+.notification {
+    border: 1px solid black;
+    border-radius: 10px;
+
+    margin: 0 20px;
+    padding: 10px 20px;
+}
+
+.notification-success {
+    background-color: #dff0d8;
+}
+
+.notification-error {
+    background-color: #f2dede;
+}

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/css/topcoat-mobile-light.min.css
----------------------------------------------------------------------
diff --git a/www/css/topcoat-mobile-light.min.css b/www/css/topcoat-mobile-light.min.css
new file mode 100644
index 0000000..1fa533a
--- /dev/null
+++ b/www/css/topcoat-mobile-light.min.css
@@ -0,0 +1 @@
+@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Regular.otf)}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Light.otf);font-weight:200}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Semibold.otf);font-weight:600}body{margin:0;padding:0;background:#dfe2e2;color:#000;font:16px "Source Sans",helvetica,arial,sans-serif;font-weight:200;text-rendering:optimizeLegibility}.topcoat-icon--menu-stack{background:url(../img/hamburger_dark.svg) no-repeat;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover}.quarter{width:25%}.half{width:50%}.three-quarters{width:75%}.third{width:33.333%}.two-thirds{width:66.666%}.full{width:100%}.left{text-align:left}.center{text-align:center}.right{text-align:right}.reset-ui{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;
 vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;padding:0 1.25rem;font-size:16px;line-height:3rem;letter-spacing:1px;color:#454545;text
 -shadow:0 1px #fff;vertical-align:top;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff;border:1px solid #a5a8a8;-webkit-border-radius:6px;border-radius:6px}.topcoat-button:active,.topcoat-button.is-active,.topcoat-button--large:active,.topcoat-button--large.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button:disabled,.topcoat-button.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--quiet:active,.topcoat-button--quiet.is-active,.topcoat-button--large--quiet:active,.topcoat-button--large--quiet.is-active{color:#454545;text-shadow:0 1px #fff;background-color:#d3d7d7;border:1px solid #a5a8a8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--quiet:disabled,.topcoat-button--qu
 iet.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--large,.topcoat-button--large--quiet{font-size:1.3rem;line-height:4rem}.topcoat-button--large:disabled,.topcoat-button--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--large--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--large--quiet:disabled,.topcoat-button--large--quiet.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--cta,.topcoat-button--large--cta{border:1px solid #143250;background-color:#288edf;-webkit-box-shadow:inset 0 1px rgba(255,255,255,.36);box-shadow:inset 0 1px rgba(255,255,255,.36);color:#fff;font-weight:500;text-shadow:0 -1px rgba(0,0,0,.36)}.topcoat-button--cta:active,.topcoat-button--cta.is-active,.topcoat-button--large--cta:active,.topcoat-button--large--cta.is-active{background-color:#0380e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px 
 rgba(0,0,0,.12)}.topcoat-button--cta:disabled,.topcoat-button--cta.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--large--cta{font-size:1.3rem;line-height:4rem}.topcoat-button--large-cta:disabled,.topcoat-button--large--cta.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button,.topcoat-icon-button--quiet,.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;padding:0 .75rem;line-height:3rem;letter-spacing:1px;color:#454545;text-shadow:0 1px #ff
 f;vertical-align:baseline;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff;border:1px solid #a5a8a8;-webkit-border-radius:6px;border-radius:6px}.topcoat-icon-button:active,.topcoat-icon-button.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-icon-button:disabled,.topcoat-icon-button.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-icon-button--quiet:active,.topcoat-icon-button--quiet.is-active,.topcoat-icon-button--large--quiet:active,.topcoat-icon-button--large--quiet.is-active{color:#454545;text-shadow:0 1px #fff;background-color:#d3d7d7;border:1px solid #a5a8a8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-icon-button--quiet:disabled,.topcoat-icon-button--quiet.is-disabled{opac
 ity:.3;cursor:default;pointer-events:none}.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{width:4rem;height:4rem;line-height:4rem}.topcoat-icon-button--large:active,.topcoat-icon-button--large.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-icon-button--large:disabled,.topcoat-icon-button--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button--large--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-icon-button--large--quiet:disabled,.topcoat-icon-button--large--quiet.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon,.topcoat-icon--large{position:relative;display:inline-block;vertical-align:top;overflow:hidden;width:1.5rem;height:1.5rem;vertical-align:middle}.topcoat-icon--large{width:2.5rem;height:2.5rem}.topcoat-list__container{padding:0;margin:0;font:inherit;color:inherit;back
 ground:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch;border-top:1px solid #bcbfbf;border-bottom:1px solid #eff1f1;background-color:#dfe2e2}.topcoat-list__header{margin:0;padding:4px 20px;font-size:.9em;font-weight:400;background-color:#cccfcf;color:#656565;text-shadow:0 1px 0 rgba(255,255,255,.5);border-top:solid 1px rgba(255,255,255,.5);border-bottom:solid 1px rgba(255,255,255,.23)}.topcoat-list{padding:0;margin:0;list-style-type:none;border-top:1px solid #bcbfbf;color:#454545}.topcoat-list__item{margin:0;padding:0;padding:1.25rem;border-top:1px solid #eff1f1;border-bottom:1px solid #bcbfbf}.topcoat-list__item:first-child{border-top:1px solid rgba(0,0,0,.05)}.topcoat-navigation-bar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;white-space:now
 rap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;height:4rem;padding-left:1rem;padding-right:1rem;background:#e5e9e8;color:#000;-webkit-box-shadow:inset 0 -1 #b9bcbc,0 1px rgba(0,0,0,.95);box-shadow:inset 0 -1 #b9bcbc,0 1px rgba(0,0,0,.95)}.topcoat-navigation-bar__item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;margin:var-margin;line-height:4rem;vertical-align:top}.topcoat-navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:1.
 3rem;font-weight:400;color:#000}.topcoat-search-input,.topcoat-search-input--large{vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 1.25rem;-webkit-border-radius:6px;border-radius:6px;margin:5px;height:3rem;font:inherit;font-weight:200;outline:0;border:1px solid #a5a8a8;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545;-webkit-appearance:none;padding:0 0 0 2.7em;-webkit-border-radius:30px;border-radius:30px;background-image:url(../img/search.svg);background-position:1em center;background-repeat:no-repeat;-webkit-background-size:16px;-moz-background-size:16px;background-size:16px}.topcoat-search-input:focus,.topcoat-search-input--large:focus{background-color:#fff;color:var-color-focus}.topcoat-search-input::-webkit-search-cancel-button,.topcoat-search-input::-webkit-search-decoration{margin-right:5px}.topcoat-search-input:focus::-webkit-input-placehold
 er,.topcoat-search-input:focus::-webkit-input-placeholder{color:#c6c8c8}.topcoat-search-input:disabled,.topcoat-search-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-search-input--large{height:4rem;font-size:1.3rem;font-weight:200;padding-left:2.8em;-webkit-border-radius:40px;border-radius:40px;background-position:1.2em center;-webkit-background-size:1.3rem;-moz-background-size:1.3rem;background-size:1.3rem}.topcoat-search-input--large:disabled,.topcoat-search-input--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input,.topcoat-text-input--large{vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 1.25rem;-webkit-border-radius:6px;border-radius:6px;margin:5px;height:3rem;font:inherit;font-weight:200;outline:0;border:1px solid #a5a8a8;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545}.topcoat-text-in
 put:focus{background-color:#fff;color:#000}.topcoat-text-input:disabled,.topcoat-text-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input--large{height:4rem;font-size:1.3rem}.topcoat-text-input--large:focus{background-color:#fff;color:#000}.topcoat-text-input--large.is-disabled,.topcoat-text-input--large:disabled{opacity:.3;cursor:default;pointer-events:none}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/LICENSE.txt
----------------------------------------------------------------------
diff --git a/www/font/LICENSE.txt b/www/font/LICENSE.txt
new file mode 100644
index 0000000..d154618
--- /dev/null
+++ b/www/font/LICENSE.txt
@@ -0,0 +1,93 @@
+Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded, 
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/SourceSansPro-Light.otf
----------------------------------------------------------------------
diff --git a/www/font/SourceSansPro-Light.otf b/www/font/SourceSansPro-Light.otf
new file mode 100644
index 0000000..9d8fb28
Binary files /dev/null and b/www/font/SourceSansPro-Light.otf differ

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/SourceSansPro-Regular.otf
----------------------------------------------------------------------
diff --git a/www/font/SourceSansPro-Regular.otf b/www/font/SourceSansPro-Regular.otf
new file mode 100644
index 0000000..7b6fa55
Binary files /dev/null and b/www/font/SourceSansPro-Regular.otf differ

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/SourceSansPro-Semibold.otf
----------------------------------------------------------------------
diff --git a/www/font/SourceSansPro-Semibold.otf b/www/font/SourceSansPro-Semibold.otf
new file mode 100644
index 0000000..6b39aa4
Binary files /dev/null and b/www/font/SourceSansPro-Semibold.otf differ


[8/9] git commit: Updating the README to reflect the modern state of the AppHarness.

Posted by br...@apache.org.
Updating the README to reflect the modern state of the AppHarness.


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/8c5698e3
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/8c5698e3
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/8c5698e3

Branch: refs/heads/master
Commit: 8c5698e3a12aebe329219d07457061bfbe7832d2
Parents: d871da2
Author: Braden Shepherdson <br...@gmail.com>
Authored: Wed Jun 19 16:02:49 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:45:48 2013 -0400

----------------------------------------------------------------------
 README.md | 104 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 52 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/8c5698e3/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 57181c9..8e36c2c 100644
--- a/README.md
+++ b/README.md
@@ -1,72 +1,67 @@
 cordova-app-harness
 ===================
 
-An App harness for Cordova that can download and run Cordova apps as well as Chrome packaged apps. This enables an edit &amp; refresh workflow. Also enables local development of apps without needing the Android / iOS SDK.
-
-##Setting up environment
-
-*   Clone the the `cordova-app-harness`, `cordova-android`, `cordova-ios`, `cordova-js`, `plugman`, `cordova-cli`, `chrome-cordova`, `zip` ([](https://github.com/MobileChromeApps/zip)) and `AppBundle` ([](https://github.com/MobileChromeApps/AppBundle)) repos into folders of the same name in a common directory - eg 'Repo'.
-*   Use the `future` branch for `cordova-cli` and `master` everywhere else
-*   Link these `plugman` and `cordova-cli` of this branch as the globally symlinked `plugman` and `cordova-cli` commands. (You may want to see `npm link`)
-*   Build the `cordova-js` repo and grab the `cordova.android.js` and `cordova.ios.js`
-*   Replace the `cordova-cli/lib/cordova-android/framework/assets/js/cordova.android.js` and the `cordova-cli/lib/cordova-ios/CordovaLib/cordova.ios.js` files with the ones above
-*   Build the `cordova-android` repository and generate new `cordova.jar`
-*   Run the following commands
-
-        cordova create CordovaAppHarness
-        cd CordovaAppHarness
-        cordova platform add android
-        cordova platform add ios
-        cordova plugin add ../Repo/AppBundle
-        cordova plugin add ../Repo/zip/
-        cordova plugin add ../Repo/chrome-cordova/plugins/*
-        cp -rf ../Repo/cordova-app-harness/www app/www
-        cordova prepare
+An wrapper app for Cordova that can download and run Cordova apps as well as Chrome packaged apps. This enables an edit &amp; refresh workflow. Also enables local development of apps without needing the Android / iOS SDK.
 
-*   Put the `cordova.jar` in the `CordovaAppHarness/platforms/android/libs` folder. (Note you may want to link the `cordova-android` project directly instead of adding a built jar so you can easily make changes to `cordova-android` and test the app harness)
-*   Replace the contents of `CordovaAppHarness/platforms/ios/CordovaLib` with `/Repo/cordova-ios/CordovaLib`
-*   Go to Eclipse and got to new, other, android, android project from existing code. Navigate to `CordovaAppHarness/platforms/android` and then add the project
-*   Double click the  `.xcodeproj` file in `CordovaAppHarnessNew/platforms/ios/`
-*   Ensure the `config.xml` for Android (Project Folder In IDE/res/xml/config.xml) and iOS (Project Folder In IDE/config.xml) have the content tag's `src` set to
+## Building the App Harness
 
-        <content src="app-bundle:///cdvah_index.html" />
+* Install `plugman` and `cordova-cli`.
+* Create a new CLI app:
 
-*   Remove the additional `content` tag added by the `chrome-cordova` plugins later in the file. The line to remove should be something like
+        cordova create CordovaAppHarness com.yourcompany.appharness CordovaAppHarness
 
-        <content src="chrome-extension://sdfsdfdfssf/chromeapp.html" />
+* Add whichever platforms you want:
 
-*   Ensure the `config.xml` for iOS has the tag
+        cordova platform add android ios
 
-        <access origin="app-bundle://*" />
-        <access origin="chrome-extension://*" />
+* Add the `zip` ([](https://github.com/MobileChromeApps/zip)) and `AppBundle` ([](https://github.com/MobileChromeApps/AppBundle)) plugins to the project (`cordova plugin add ...`).
+* If you want to support Chrome apps, also add the `MobileChromeApps` `chrome-bootstrap` plugin, and any other Chrome APIs you want to support (`socket`, `identity`, etc.).
+    * After each `cordova prepare`, you'll have to edit the `config.xml` on each platform to remove the new `<content>` tag that looks like this:
+
+            <content src="chrome-extension://some_junk_here/chromeapp.html" />
+
+* Clone the the `cordova-app-harness` repository.
+* Copy the `www` directory into the project:
+
+     cp -a cordova-app-harness/www CordovaAppHarness/www
 
-*   Open the `cordova_plugins.json` file in Eclipse and Xcode and ensure replace the contents with
+* Run `cordova prepare`.
+* Remove all `<content>` tags in `platforms/android/res/xml/config.xml`, and add:
 
-        [{"file":"plugins/AppBundle/appBundle.js","id":"AppBundle.AppBundle"},{"file":"plugins/zip/zip.js","id":"zip.Zip","clobbers":["zip"]}]
+        <content src="cdvah_index.html" />
 
-*   You can now build the app harness from the IDEs or with `cordova compile`
+* Remove all `<content>` tags in `platforms/ios/CordovaAppHarness/config.xml`, and add:
+
+        <content src="cdvah_index.html" />
+
+* Also ensure the `config.xml` for iOS has the tags
+
+        <access origin="app-bundle://*" />
+        <access origin="chrome-extension://*" />
+
+* Now you can build the AppHarness with Eclipse/Xcode or `cordova compile`. Don't run `cordova build`, and if you run `cordova prepare` make sure you redo the above edits to the `<content>` tags.
 
 ##Features
 
 *   Install and test multiple applications.
-*   Install crx files directly or from the Chrome App Store.
-*   In App context menu to switch between apps.
+*   Install `.crx` files directly or from the Chrome Web Store.
+*   In-app context menu to switch between child apps.
 *   Firebug Lite and Weinre support for debugging.
-*   Support for bundle paths such as `file:///android_asset/www` - These point to the tested application's bundle and not the app harness' bundle. (In development)
 
 ##Install an app in the harness
 
-*   Install the app in one of the two ways below
+There are two ways to install an app, detailed below.
 
 ###Test by installing the app on the phone through app harness
-*   Run the `packapp` script and point it to a cordova project of the app you want to test. This will package the app into a `cdvh` file. (Note: it is expected that you have added all relevant platforms. For example, if you want to test on the iphone, you need to have added the ios platform to the project)
+
+*   Run the `packapp` script and point it to a Cordova project of the app you want to test. This will package the app into a `.cdvh` file. (Note: it is expected that you have added all relevant platforms. For example, if you want to test on the iPhone, you need to have added the `ios` platform to the project.)
 
         Repo/cordova-app-harness/packapp -p ./TestApp TestApp.cdvh
 
-*   Upload the the `cdvh` onto any hosting site.
+*   Upload the the `cdvh` file onto any hosting site.
 *   Run the app harness
-*   Click add new app
-*   Give a name and the url to the cdvh file.
+*   Click the "Add" button.
+*   Give the app a name and enter the URL to the `cdvh` file.
 
         Name: App1
         URL to file: http://www.somesite.com/myapp.cdvh
@@ -80,27 +75,32 @@ An App harness for Cordova that can download and run Cordova apps as well as Chr
         Name: App1
         URL to file: http://www.somesite.com/myapp.crx
 
-*   Alternately you can use the url of the app in the apps store for example https://chrome.google.com/webstore/detail/appName/appid
 
-###Test by using cordova serve
-*   Go to cordova project of the app you want to test in a terminal and run.
+Alternately you can use the URL of an app in the Chrome Web Store, for example `https://chrome.google.com/webstore/detail/appName/appid`.
+
+### Test by using `cordova serve`
+
+*   Go to Cordova project of the app you want to test in a terminal and run.
 
+        cordova prepare
         cordova serve <platform>
 
 *   If you want to test the app in an actual device, find the network address of your computer by running
+
         ifconfig
-*   If you are running this on a simulator, you can use `http://localhost` as your address
-*   Click add new app
+
+*   If you are running this on a simulator, you can use `http://localhost` as your address, or on Android `10.0.0.22`.
+*   Click the "Add" button.
 *   Choose the option "Enter the URL to the server hosting the app"
-*   Give a name and the url as follows. Let's assume the network address discovered above is `a.b.c.d`
+*   Give a name and the URL as follows. Let's assume the network address discovered above is `a.b.c.d`.
 
         Name: App1
         URL to server: http://a.b.c.d:8000/config.xml
 
-*   Go back to the main screen after you see the prompt "successfully installed"
 
 ##Running an app in the harness
+
 *   Click launch on the installed app
 *   See if the app looks as expected
-*   Use the 3 finger tap to access the app menu while testing your app
-*   The context menu that pops up, will allow you to return to the main screen, restart or update the app, open a firebug console in the device, setup remote debugging using weinre etc.
+*   Use a 3 finger tap to access the app menu while testing your app. This is unfortunately challenging in simulators.
+*   The context menu that pops up allows you to return to the main screen, restart or update the app, open a Firebug console on the device, or set up remote debugging using Weinre.


[2/9] git commit: Some Markdown formatting cleanup. (cherry picked from commit 6492417bdaa8b1eaa8fc44097c45e9f2c2897308)

Posted by br...@apache.org.
Some Markdown formatting cleanup.
(cherry picked from commit 6492417bdaa8b1eaa8fc44097c45e9f2c2897308)


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/a7a877b2
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/a7a877b2
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/a7a877b2

Branch: refs/heads/master
Commit: a7a877b2b49ffc9d8710ed9dc39d39bbba40af98
Parents: d045574
Author: Braden Shepherdson <br...@google.com>
Authored: Thu May 16 15:20:54 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:42:36 2013 -0400

----------------------------------------------------------------------
 README.md | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/a7a877b2/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 5610c12..57181c9 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ An App harness for Cordova that can download and run Cordova apps as well as Chr
 
 ##Setting up environment
 
-*   Clone the the `cordova-app-harness`, `cordova-android`, `cordova-ios`, `cordova-js`, `chrome-cordova`, `plugman`, `cordova-cli`, `zip` ([](https://github.com/MobileChromeApps/zip)) and `AppBundle` ([](https://github.com/MobileChromeApps/AppBundle)) repos into folders of the same name in a common directory - eg 'Repo'.
+*   Clone the the `cordova-app-harness`, `cordova-android`, `cordova-ios`, `cordova-js`, `plugman`, `cordova-cli`, `chrome-cordova`, `zip` ([](https://github.com/MobileChromeApps/zip)) and `AppBundle` ([](https://github.com/MobileChromeApps/AppBundle)) repos into folders of the same name in a common directory - eg 'Repo'.
 *   Use the `future` branch for `cordova-cli` and `master` everywhere else
 *   Link these `plugman` and `cordova-cli` of this branch as the globally symlinked `plugman` and `cordova-cli` commands. (You may want to see `npm link`)
 *   Build the `cordova-js` repo and grab the `cordova.android.js` and `cordova.ios.js`
@@ -35,7 +35,7 @@ An App harness for Cordova that can download and run Cordova apps as well as Chr
 
         <content src="chrome-extension://sdfsdfdfssf/chromeapp.html" />
 
-*   Ensure the config.xml for ios has the tags
+*   Ensure the `config.xml` for iOS has the tag
 
         <access origin="app-bundle://*" />
         <access origin="chrome-extension://*" />
@@ -50,8 +50,6 @@ An App harness for Cordova that can download and run Cordova apps as well as Chr
 
 *   Install and test multiple applications.
 *   Install crx files directly or from the Chrome App Store.
-*   Run apps locally or run them directly from `cordova serve`.
-*   Edit and Refresh workflow with `cordova serve`.
 *   In App context menu to switch between apps.
 *   Firebug Lite and Weinre support for debugging.
 *   Support for bundle paths such as `file:///android_asset/www` - These point to the tested application's bundle and not the app harness' bundle. (In development)
@@ -89,13 +87,9 @@ An App harness for Cordova that can download and run Cordova apps as well as Chr
 
         cordova serve <platform>
 
-*   Open a new terminal to the same location and run
-
-        cordova prepare
-
-*   If you want to test the app in an actual device, find the network address of your computer by running ifconfig
-    If you are running this on the iOS simulator, you can use "http://localhost" as your address
-    If you are running this on the android simulator, you can use "http://10.0.2.2" as your address
+*   If you want to test the app in an actual device, find the network address of your computer by running
+        ifconfig
+*   If you are running this on a simulator, you can use `http://localhost` as your address
 *   Click add new app
 *   Choose the option "Enter the URL to the server hosting the app"
 *   Give a name and the url as follows. Let's assume the network address discovered above is `a.b.c.d`


[6/9] git commit: Update config..xml files with modern format

Posted by br...@apache.org.
Update config.<platform>.xml files with modern format


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/34c9a89a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/34c9a89a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/34c9a89a

Branch: refs/heads/master
Commit: 34c9a89a6a7cb348e94474bb15ec3a2a0e628e82
Parents: ee57b46
Author: Braden Shepherdson <br...@gmail.com>
Authored: Fri Jun 14 10:06:31 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:43:56 2013 -0400

----------------------------------------------------------------------
 www/crx_files/config.android.xml | 125 +++++++++++++++++++++++++---------
 www/crx_files/config.ios.xml     | 114 +++++++++++++++++++++++--------
 2 files changed, 179 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/34c9a89a/www/crx_files/config.android.xml
----------------------------------------------------------------------
diff --git a/www/crx_files/config.android.xml b/www/crx_files/config.android.xml
index 27da959..de9a737 100644
--- a/www/crx_files/config.android.xml
+++ b/www/crx_files/config.android.xml
@@ -1,39 +1,98 @@
 <?xml version='1.0' encoding='utf-8'?>
-<cordova>
-    <content src="index.html" />
+<widget id="io.cordova.helloCordova" version="2.0.0" xmlns="http://www.w3.org/ns/widgets">
+    <name>Hello Cordova</name>
+    <description>
+        Default config.xml for Chrome apps launched through the app harness.
+    </description>
+    <author email="cordova-team@google.com" href="https://github.com/MobileChromeApps/cordova-app-harness">
+        Google Mobile Chrome Apps team
+    </author>
+
     <log level="DEBUG" />
+
+
+    <feature name="App">
+        <param name="android-package" value="org.apache.cordova.App" />
+    </feature>
+    <feature name="Geolocation">
+        <param name="android-package" value="org.apache.cordova.GeoBroker" />
+    </feature>
+    <feature name="Device">
+        <param name="android-package" value="org.apache.cordova.Device" />
+    </feature>
+    <feature name="Accelerometer">
+        <param name="android-package" value="org.apache.cordova.AccelListener" />
+    </feature>
+    <feature name="Compass">
+        <param name="android-package" value="org.apache.cordova.CompassListener" />
+    </feature>
+    <feature name="Media">
+        <param name="android-package" value="org.apache.cordova.AudioHandler" />
+    </feature>
+    <feature name="Camera">
+        <param name="android-package" value="org.apache.cordova.CameraLauncher" />
+    </feature>
+    <feature name="Contacts">
+        <param name="android-package" value="org.apache.cordova.ContactManager" />
+    </feature>
+    <feature name="File">
+        <param name="android-package" value="org.apache.cordova.FileUtils" />
+    </feature>
+    <feature name="NetworkStatus">
+        <param name="android-package" value="org.apache.cordova.NetworkManager" />
+    </feature>
+    <feature name="Notification">
+        <param name="android-package" value="org.apache.cordova.Notification" />
+    </feature>
+    <feature name="Storage">
+        <param name="android-package" value="org.apache.cordova.Storage" />
+    </feature>
+    <feature name="FileTransfer">
+        <param name="android-package" value="org.apache.cordova.FileTransfer" />
+    </feature>
+    <feature name="Capture">
+        <param name="android-package" value="org.apache.cordova.Capture" />
+    </feature>
+    <feature name="Battery">
+        <param name="android-package" value="org.apache.cordova.BatteryListener" />
+    </feature>
+    <feature name="SplashScreen">
+        <param name="android-package" value="org.apache.cordova.SplashScreen" />
+    </feature>
+    <feature name="Echo">
+        <param name="android-package" value="org.apache.cordova.Echo" />
+    </feature>
+    <feature name="Globalization">
+        <param name="android-package" value="org.apache.cordova.Globalization" />
+    </feature>
+    <feature name="InAppBrowser">
+        <param name="android-package" value="org.apache.cordova.InAppBrowser" />
+    </feature>
     <plugins>
-        <plugin name="App" value="org.apache.cordova.App" />
-        <plugin name="Geolocation" value="org.apache.cordova.GeoBroker" />
-        <plugin name="Device" value="org.apache.cordova.Device" />
-        <plugin name="Accelerometer" value="org.apache.cordova.AccelListener" />
-        <plugin name="Compass" value="org.apache.cordova.CompassListener" />
-        <plugin name="Media" value="org.apache.cordova.AudioHandler" />
-        <plugin name="Camera" value="org.apache.cordova.CameraLauncher" />
-        <plugin name="Contacts" value="org.apache.cordova.ContactManager" />
-        <plugin name="File" value="org.apache.cordova.FileUtils" />
-        <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager" />
-        <plugin name="Notification" value="org.apache.cordova.Notification" />
-        <plugin name="Storage" value="org.apache.cordova.Storage" />
-        <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer" />
-        <plugin name="Capture" value="org.apache.cordova.Capture" />
-        <plugin name="Battery" value="org.apache.cordova.BatteryListener" />
-        <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen" />
-        <plugin name="Echo" value="org.apache.cordova.Echo" />
-        <plugin name="Globalization" value="org.apache.cordova.Globalization" />
-        <plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser" />
-        <plugin name="Zip" value="org.apache.cordova.Zip" />
-        <plugin name="ChromeExtensionURLs" value="com.google.cordova.ChromeExtensionURLs">
-            <url-filter value="chrome-extension://" />
-        </plugin>
-        <plugin name="ChromeI18n" onload="true" value="com.google.cordova.ChromeI18n" />
-        <plugin name="ChromeIdentity" value="com.google.cordova.ChromeIdentity" />
-        <plugin name="ChromeSocket" value="com.google.cordova.ChromeSocket" />
-        <plugin name="ChromeStorage" value="com.google.cordova.ChromeStorage" />
-        <plugin name="CordovaAppHarnessRedirect" value="org.apache.cordova.cordovaappharness.CordovaAppHarnessRedirect">
-            <url-filter value="cdv-app-harness://" />
-        </plugin>
     </plugins>
+    <feature name="ChromeBootstrap">
+        <param name="android-package" value="com.google.cordova.ChromeBootstrap" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="ChromeExtensionURLs">
+        <param name="android-package" value="com.google.cordova.ChromeExtensionURLs" />
+        <param name="onload" value="true" />
+    </feature>
+    <content src="app-bundle:///cdvah_index.html" />
+    <feature name="ChromeStorage">
+        <param name="android-package" value="com.google.cordova.ChromeStorage" />
+    </feature>
+    <feature name="ChromeSocket">
+        <param name="android-package" value="com.google.cordova.ChromeSocket" />
+    </feature>
+    <feature name="Zip">
+        <param name="android-package" value="org.apache.cordova.Zip" />
+    </feature>
+    <feature name="AppBundle">
+        <param name="android-package" value="org.apache.cordova.AppBundle" />
+        <param name="onload" value="true" />
+    </feature>
+
     <content src="chromeapp.html" />
     <access origin="*" />
     <access origin="chrome-extension://*" />
@@ -44,4 +103,4 @@
     <preference name="orientation" value="default" />
     <preference name="target-device" value="universal" />
     <preference name="fullscreen" value="false" />
-</cordova>
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/34c9a89a/www/crx_files/config.ios.xml
----------------------------------------------------------------------
diff --git a/www/crx_files/config.ios.xml b/www/crx_files/config.ios.xml
index bfba1c9..9254738 100644
--- a/www/crx_files/config.ios.xml
+++ b/www/crx_files/config.ios.xml
@@ -1,33 +1,93 @@
 <?xml version='1.0' encoding='utf-8'?>
-<widget>
-    <content src="index.html" />
+<widget id="io.cordova.helloCordova" version="2.0.0" xmlns="http://www.w3.org/ns/widgets">
+    <name>Hello Cordova</name>
+    <description>
+        Default config.xml for iOS apps in the Cordova App Harness
+    </description>
+    <author email="cordova-team@google.com" href="https://github.com/MobileChromeApps/cordova-app-harness">
+        Google Mobile Chrome Apps Team
+    </author>
+    <feature name="Geolocation">
+        <param name="ios-package" value="CDVLocation" />
+    </feature>
+    <feature name="Device">
+        <param name="ios-package" value="CDVDevice" />
+    </feature>
+    <feature name="Accelerometer">
+        <param name="ios-package" value="CDVAccelerometer" />
+    </feature>
+    <feature name="Compass">
+        <param name="ios-package" value="CDVLocation" />
+    </feature>
+    <feature name="Media">
+        <param name="ios-package" value="CDVSound" />
+    </feature>
+    <feature name="Camera">
+        <param name="ios-package" value="CDVCamera" />
+    </feature>
+    <feature name="Contacts">
+        <param name="ios-package" value="CDVContacts" />
+    </feature>
+    <feature name="File">
+        <param name="ios-package" value="CDVFile" />
+    </feature>
+    <feature name="NetworkStatus">
+        <param name="ios-package" value="CDVConnection" />
+    </feature>
+    <feature name="Notification">
+        <param name="ios-package" value="CDVNotification" />
+    </feature>
+    <feature name="FileTransfer">
+        <param name="ios-package" value="CDVFileTransfer" />
+    </feature>
+    <feature name="Capture">
+        <param name="ios-package" value="CDVCapture" />
+    </feature>
+    <feature name="Battery">
+        <param name="ios-package" value="CDVBattery" />
+    </feature>
+    <feature name="SplashScreen">
+        <param name="ios-package" value="CDVSplashScreen" />
+    </feature>
+    <feature name="Echo">
+        <param name="ios-package" value="CDVEcho" />
+    </feature>
+    <feature name="Globalization">
+        <param name="ios-package" value="CDVGlobalization" />
+    </feature>
+    <feature name="InAppBrowser">
+        <param name="ios-package" value="CDVInAppBrowser" />
+    </feature>
+    <feature name="Logger">
+        <param name="ios-package" value="CDVLogger" />
+    </feature>
+    <feature name="LocalStorage">
+        <param name="ios-package" value="CDVLocalStorage" />
+    </feature>
     <plugins>
-        <plugin name="Device" value="CDVDevice" />
-        <plugin name="Logger" value="CDVLogger" />
-        <plugin name="Compass" value="CDVLocation" />
-        <plugin name="Accelerometer" value="CDVAccelerometer" />
-        <plugin name="Camera" value="CDVCamera" />
-        <plugin name="NetworkStatus" value="CDVConnection" />
-        <plugin name="Contacts" value="CDVContacts" />
-        <plugin name="Debug Console" value="CDVDebugConsole" />
-        <plugin name="Echo" value="CDVEcho" />
-        <plugin name="File" value="CDVFile" />
-        <plugin name="FileTransfer" value="CDVFileTransfer" />
-        <plugin name="Geolocation" value="CDVLocation" />
-        <plugin name="Notification" value="CDVNotification" />
-        <plugin name="Media" value="CDVSound" />
-        <plugin name="Capture" value="CDVCapture" />
-        <plugin name="SplashScreen" value="CDVSplashScreen" />
-        <plugin name="Battery" value="CDVBattery" />
-        <plugin name="Globalization" value="CDVGlobalization" />
-        <plugin name="InAppBrowser" value="CDVInAppBrowser" />
-        <plugin name="Zip" value="Zip" />
-        <plugin name="ChromeExtensionURLs" onload="true" value="ChromeExtensionURLs" />
-        <plugin name="ChromeI18n" value="ChromeI18n" />
-        <plugin name="ChromeSocket" value="ChromeSocket" />
-        <plugin name="ChromeStorage" value="ChromeStorage" />
-        <plugin name="CordovaAppHarnessRedirect" onload="true" value="CordovaAppHarnessRedirect" />
     </plugins>
+    <feature name="AppBundle">
+        <param name="ios-package" value="AppBundle" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="ChromeBootstrap">
+        <param name="ios-package" value="ChromeBootstrap" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="ChromeExtensionURLs">
+        <param name="ios-package" value="ChromeExtensionURLs" />
+        <param name="onload" value="true" />
+    </feature>
+    <content src="chrome-extension://ohgfbmefaoadakchflddcopcmphnlcba/chromeapp.html" />
+    <feature name="ChromeSocket">
+        <param name="ios-package" value="ChromeSocket" />
+    </feature>
+    <feature name="ChromeStorage">
+        <param name="ios-package" value="ChromeStorage" />
+    </feature>
+    <feature name="Zip">
+        <param name="ios-package" value="Zip" />
+    </feature>
     <content src="chromeapp.html" />
     <access origin="*" />
     <access origin="chrome-extension://*" />


[7/9] git commit: Don't load the context menu until deviceready fires

Posted by br...@apache.org.
Don't load the context menu until deviceready fires


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/9b881f49
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/9b881f49
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/9b881f49

Branch: refs/heads/master
Commit: 9b881f490e8bf2f256bcf98e13435291f1e6fad4
Parents: 34c9a89
Author: Braden Shepherdson <br...@gmail.com>
Authored: Mon Jun 17 13:41:25 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:43:56 2013 -0400

----------------------------------------------------------------------
 www/cdvah_js/ContextMenu.js             | 16 ++++++++++------
 www/cdvah_js/ContextMenuInjectScript.js | 16 +++++++++-------
 2 files changed, 19 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/9b881f49/www/cdvah_js/ContextMenu.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/ContextMenu.js b/www/cdvah_js/ContextMenu.js
index 48d5ac8..12d20ae 100644
--- a/www/cdvah_js/ContextMenu.js
+++ b/www/cdvah_js/ContextMenu.js
@@ -4,7 +4,7 @@
         setupIframe();
         sendAppNameToIframe();
         setupIframeMessaging();
-        loadFirebug(false);
+        //loadFirebug(false);
         attachErrorListener();
     }
 
@@ -85,11 +85,15 @@
     };
     function setupIframeMessaging(){
         window.addEventListener("message", function(e){
+            if (!e || !e.data || typeof e.data !== 'string') {
+                return;
+            }
+
             var messageParts = [ e.data ];
-            var location = e.data.indexOf(":");
-            if(location !== -1){
-                messageParts = [ e.data.substring(0, location),
-                    e.data.substring(location + 1)
+            var loc = e.data.indexOf(":");
+            if(loc !== -1){
+                messageParts = [ e.data.substring(0, loc),
+                    e.data.substring(loc + 1)
                 ];
             }
             if(messageHandler[messageParts[0]]){
@@ -101,7 +105,7 @@
     function loadFirebug(startOpened){
         var el = document.createElement("script");
         el.setAttribute("id", "FirebugLite");
-        el.setAttribute("src", "https://getfirebug.com/firebug-lite.js");
+        el.setAttribute("src", "https://getfirebug.com/firebug-lite-beta.js");
         el.setAttribute("FirebugLite", "4");
         el.innerHTML = el.innerHTML = "{ debug : false, startOpened : "  + startOpened + ", showIconWhenHidden : false, saveCommandLineHistory : true, saveCookies : false }";
         document.head.appendChild(el);

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/9b881f49/www/cdvah_js/ContextMenuInjectScript.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/ContextMenuInjectScript.js b/www/cdvah_js/ContextMenuInjectScript.js
index 70c06aa..5a703cc 100644
--- a/www/cdvah_js/ContextMenuInjectScript.js
+++ b/www/cdvah_js/ContextMenuInjectScript.js
@@ -3,12 +3,14 @@
     /* global myApp */
     myApp.factory("ContextMenuInjectScript", [ function () {
         var toInject = function() {
-            console.log("Injecting menu script");
-            var contextScript = document.createElement("script");
-            contextScript.setAttribute("type","text/javascript");
-            contextScript.setAttribute("src", "app-bundle:///cdvah_js/ContextMenu.js");
-            window.__cordovaAppHarnessAppName = "appPlaceHolder";
-            document.getElementsByTagName("head")[0].appendChild(contextScript);
+            document.addEventListener('deviceready', function() {
+                console.log("Injecting menu script");
+                var contextScript = document.createElement("script");
+                contextScript.setAttribute("type","text/javascript");
+                contextScript.setAttribute("src", "app-bundle:///cdvah_js/ContextMenu.js");
+                window.__cordovaAppHarnessAppName = "appPlaceHolder";
+                document.getElementsByTagName("head")[0].appendChild(contextScript);
+            });
         };
 
         return {
@@ -19,4 +21,4 @@
             }
         };
     }]);
-})();
\ No newline at end of file
+})();


[3/9] git commit: Remove redundant and unused duplicate file, and improve Chrome loading

Posted by br...@apache.org.
Remove redundant and unused duplicate file, and improve Chrome loading

It now draws on the same Chrome app bootstrap files as exist in the app
harness itself. This ensures that the Javascript always matches the
native side.


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/e80bb1dc
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/e80bb1dc
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/e80bb1dc

Branch: refs/heads/master
Commit: e80bb1dcb813eb04f0f4177a7ecdd634fdfc84d4
Parents: a7a877b
Author: Braden Shepherdson <br...@gmail.com>
Authored: Fri Jun 14 09:55:42 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:43:42 2013 -0400

----------------------------------------------------------------------
 www/cdvah_js/CrxPackageHandler.js | 69 ++++++++++++++++++++++++++++++++++
 www/js/CrxPackageHandler.js       | 54 --------------------------
 2 files changed, 69 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/e80bb1dc/www/cdvah_js/CrxPackageHandler.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/CrxPackageHandler.js b/www/cdvah_js/CrxPackageHandler.js
new file mode 100644
index 0000000..8019d5d
--- /dev/null
+++ b/www/cdvah_js/CrxPackageHandler.js
@@ -0,0 +1,69 @@
+(function(){
+    "use strict";
+    /* global myApp */
+    myApp.run(["AppsService", "ResourcesLoader", "ContextMenuInjectScript", function(AppsService, ResourcesLoader, ContextMenuInjectScript){
+
+        var platformId = cordova.require("cordova/platform").id;
+
+        function copyFile(startUrl, targetLocation){
+            /************ Begin Work around for File system bug ************/
+            if(targetLocation.indexOf("file://") === 0) {
+                targetLocation = targetLocation.substring("file://".length);
+            }
+            /************ End Work around for File system bug **************/
+            return ResourcesLoader.xhrGet(startUrl)
+            .then(function(xhr){
+                return ResourcesLoader.ensureDirectoryExists(targetLocation)
+                .then(function(){
+                    return ResourcesLoader.writeFileContents(targetLocation, xhr.responseText);
+                });
+            });
+        }
+
+        AppsService.registerPackageHandler("crx", {
+            extractPackageToDirectory : function (appName, fileName, outputDirectory){
+                console.log('extracting the crx');
+                var dataToAppend = ContextMenuInjectScript.getInjectString(appName);
+                var platformDirectory = outputDirectory + "/" + platformId + "/";
+                var platformWWWDirectory = platformDirectory + "www/";
+                var cordovaFile = platformWWWDirectory + "cordova.js";
+
+                // We need to
+                // 1) Copy over the files required to convert a crx to a normal web app
+                // 2) Modify the cordova.js file
+                return ResourcesLoader.extractZipFile(fileName, platformWWWDirectory)
+                .then(function(){
+                    // Read cordova_plugins.json and use it to copy the plugin Javascript files.
+                    return ResourcesLoader.xhrGet("app-bundle:///cordova_plugins.json");
+                })
+                .then(function(xhr) {
+                    return JSON.parse(xhr.responseText.trim());
+                })
+                .then(function(plugins){
+                    if (!plugins) {
+                        throw new Error('Error loading cordova_plugins.json');
+                    }
+
+                    var copies = [
+                        copyFile("app-bundle:///cordova.js", cordovaFile),
+                        copyFile("app-bundle:///crx_files/config." + platformId + ".xml", platformDirectory + "config.xml"),
+                        copyFile("app-bundle:///cordova_plugins.json", platformWWWDirectory + "cordova_plugins.json"),
+                        copyFile("app-bundle:///chromeapp.html", platformWWWDirectory + "chromeapp.html"),
+                        copyFile("app-bundle:///chromeappstyles.css", platformWWWDirectory + "chromeappstyles.css"),
+                        copyFile("app-bundle:///chromebgpage.html", platformWWWDirectory + "chromebgpage.html")
+                    ];
+
+                    for(var i = 0; i < plugins.length; i++) {
+                        console.log('copying ' + plugins[i].file);
+                        copies.push(copyFile("app-bundle:///" + plugins[i].file, platformWWWDirectory + plugins[i].file));
+                    }
+
+                    return Q.all(copies);
+                })
+                .then(function(){
+                    return ResourcesLoader.appendFileContents(cordovaFile, dataToAppend);
+                });
+            }
+        });
+    }]);
+})();

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/e80bb1dc/www/js/CrxPackageHandler.js
----------------------------------------------------------------------
diff --git a/www/js/CrxPackageHandler.js b/www/js/CrxPackageHandler.js
deleted file mode 100644
index 2627fd7..0000000
--- a/www/js/CrxPackageHandler.js
+++ /dev/null
@@ -1,54 +0,0 @@
-(function(){
-    "use strict";
-    /* global myApp */
-    myApp.run(["AppsService", "ResourcesLoader", function(AppsService, ResourcesLoader){
-
-        function copyFile(startUrl, targetLocation){
-            /************ Begin Work around for File system bug ************/
-            if(targetLocation.indexOf("file://") === 0) {
-                targetLocation = targetLocation.substring("file://".length);
-            }
-            /************ End Work around for File system bug **************/
-            return ResourcesLoader.xhrGet(startUrl)
-            .then(function(xhr){
-                return ResourcesLoader.ensureDirectoryExists(targetLocation)
-                .then(function(){
-                    return ResourcesLoader.writeFileContents(targetLocation, xhr.responseText);
-                });
-            });
-        }
-
-        AppsService.registerPackageHandler("crx", {
-            extractPackageToDirectory : function (fileName, outputDirectory){
-                return ResourcesLoader.ensureDirectoryExists(outputDirectory + "/www")
-                .then(function(){
-                    return ResourcesLoader.extractZipFile(fileName, outputDirectory + "/www");
-                })
-                .then(function(){
-                    return Q.all([
-                        copyFile("cdv-app-harness:///direct/cordova.js", outputDirectory + "/www/cordova.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/config.android.xml", outputDirectory + "/config.android.xml"),
-                        copyFile("cdv-app-harness:///direct/crx_files/config.ios.xml", outputDirectory + "/config.ios.xml"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/cordova_plugins.json", outputDirectory + "/www/cordova_plugins.json"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/chromeapp.html", outputDirectory + "/www/chromeapp.html"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/chromeappstyles.css", outputDirectory + "/www/chromeappstyles.css"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/chromebgpage.html", outputDirectory + "/www/chromebgpage.html"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/app/runtime.js", outputDirectory + "/www/plugins/chrome/api/app/runtime.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/app/window.js", outputDirectory + "/www/plugins/chrome/api/app/window.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/bootstrap.js", outputDirectory + "/www/plugins/chrome/api/bootstrap.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/helpers/stubs.js", outputDirectory + "/www/plugins/chrome/api/helpers/stubs.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/mobile.js", outputDirectory + "/www/plugins/chrome/api/mobile.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome/api/runtime.js", outputDirectory + "/www/plugins/chrome/api/runtime.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.common/events.js", outputDirectory + "/www/plugins/chrome.common/events.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.fileSystem/fileSystem.js", outputDirectory + "/www/plugins/chrome.fileSystem/fileSystem.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.i18n/i18n.js", outputDirectory + "/www/plugins/chrome.i18n/i18n.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.identity/identity.js", outputDirectory + "/www/plugins/chrome.identity/identity.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.socket/socket.js", outputDirectory + "/www/plugins/chrome.socket/socket.js"),
-                        copyFile("cdv-app-harness:///direct/crx_files/www/plugins/chrome.storage/storage.js", outputDirectory + "/www/plugins/chrome.storage/storage.js")
-                    ]);
-                });
-            }
-        });
-
-    }]);
-})();
\ No newline at end of file