summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-20 19:06:26 +0000
committerjamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-20 19:06:26 +0000
commitde794ebc37fdefdb61f340b8e91f1ac80b1b8678 (patch)
treeb7cb1404d6ddf71a4c2164edbccb98d094a03a6c
parent43526ac0e6f164add015dbc79584125486ffd671 (diff)
downloadchromium_src-de794ebc37fdefdb61f340b8e91f1ac80b1b8678.zip
chromium_src-de794ebc37fdefdb61f340b8e91f1ac80b1b8678.tar.gz
chromium_src-de794ebc37fdefdb61f340b8e91f1ac80b1b8678.tar.bz2
Mock chrome.storage (https://developer.chrome.com/extensions/storage.html) API in preparation for Apps v2 migration.
I haven't changed oauth2.js, since that's going to need to be completely rewritten to make it Apps-v2-compatible. BUG=134213 Review URL: https://codereview.chromium.org/11638031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174195 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/remoting.gyp1
-rw-r--r--remoting/webapp/host_list.js50
-rw-r--r--remoting/webapp/jscompiler_hacks.js7
-rw-r--r--remoting/webapp/main.html1
-rw-r--r--remoting/webapp/remoting.js34
-rw-r--r--remoting/webapp/storage.js134
-rw-r--r--remoting/webapp/ui_mode.js47
7 files changed, 230 insertions, 44 deletions
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 8fadc68..bd514a2 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -176,6 +176,7 @@
'webapp/server_log_entry.js',
'webapp/spinner.gif',
'webapp/stats_accumulator.js',
+ 'webapp/storage.js',
'webapp/suspend_monitor.js',
'webapp/toolbar.css',
'webapp/toolbar.js',
diff --git a/remoting/webapp/host_list.js b/remoting/webapp/host_list.js
index 9cc007c..9d8353f 100644
--- a/remoting/webapp/host_list.js
+++ b/remoting/webapp/host_list.js
@@ -76,18 +76,30 @@ remoting.HostList = function(table, noHosts, errorMsg, errorButton) {
this.errorButton_.addEventListener('click',
this.onErrorClick_.bind(this),
false);
+};
+/**
+ * Load the host-list asynchronously from local storage.
+ *
+ * @param {function():void} onDone Completion callback.
+ */
+remoting.HostList.prototype.load = function(onDone) {
// Load the cache of the last host-list, if present.
- var cachedStr = /** @type {string} */
- (window.localStorage.getItem(remoting.HostList.HOSTS_KEY));
- if (cachedStr) {
- var cached = jsonParseSafe(cachedStr);
- if (cached) {
- this.hosts_ = /** @type {Array} */ cached;
- } else {
- console.error('Invalid value for ' + remoting.HostList.HOSTS_KEY);
+ /** @type {remoting.HostList} */
+ var that = this;
+ /** @param {Object.<string>} items */
+ var storeHostList = function(items) {
+ if (items[remoting.HostList.HOSTS_KEY]) {
+ var cached = jsonParseSafe(items[remoting.HostList.HOSTS_KEY]);
+ if (cached) {
+ that.hosts_ = /** @type {Array} */ cached;
+ } else {
+ console.error('Invalid value for ' + remoting.HostList.HOSTS_KEY);
+ }
}
- }
+ onDone();
+ };
+ chrome.storage.local.get(remoting.HostList.HOSTS_KEY, storeHostList);
};
/**
@@ -189,8 +201,7 @@ remoting.HostList.prototype.parseHostListResponse_ = function(onDone, xhr) {
console.error('Error processing response: ', xhr, typed_er);
this.lastError_ = remoting.Error.UNEXPECTED;
}
- window.localStorage.setItem(remoting.HostList.HOSTS_KEY,
- JSON.stringify(this.hosts_));
+ this.save_();
onDone(this.lastError_ == '');
};
@@ -277,8 +288,7 @@ remoting.HostList.prototype.renameHost_ = function(hostTableEntry) {
break;
}
}
- window.localStorage.setItem(remoting.HostList.HOSTS_KEY,
- JSON.stringify(this.hosts_));
+ this.save_();
/** @param {string?} token */
var renameHost = function(token) {
@@ -412,8 +422,7 @@ remoting.HostList.prototype.onLocalHostStarted = function(
localHost.publicKey = publicKey;
localHost.status = 'ONLINE';
this.hosts_.push(localHost);
- window.localStorage.setItem(remoting.HostList.HOSTS_KEY,
- JSON.stringify(this.hosts_));
+ this.save_();
this.setLocalHost_(localHost);
};
@@ -431,7 +440,16 @@ remoting.HostList.prototype.onErrorClick_ = function() {
this.display();
this.refresh(remoting.updateLocalHostState);
}
-}
+};
+
+/**
+ * Save the host list to local storage.
+ */
+remoting.HostList.prototype.save_ = function() {
+ var items = {};
+ items[remoting.HostList.HOSTS_KEY] = JSON.stringify(this.hosts_);
+ chrome.storage.local.set(items);
+};
/**
* Key name under which Me2Me hosts are cached.
diff --git a/remoting/webapp/jscompiler_hacks.js b/remoting/webapp/jscompiler_hacks.js
index a377b7f..28551e2 100644
--- a/remoting/webapp/jscompiler_hacks.js
+++ b/remoting/webapp/jscompiler_hacks.js
@@ -63,3 +63,10 @@ var WebKitMutationObserver = function(callback) {};
/** @param {Element} element
@param {Object} options */
WebKitMutationObserver.prototype.observe = function(element, options) {};
+
+/** @type {Object} */
+chrome.storage = {};
+
+// TODO(jamiewalch): Flesh this out with the correct type when we're a v2 app.
+/** @type {remoting.MockStorage} */
+chrome.storage.local = null; \ No newline at end of file
diff --git a/remoting/webapp/main.html b/remoting/webapp/main.html
index 7d92ac6..3936e79 100644
--- a/remoting/webapp/main.html
+++ b/remoting/webapp/main.html
@@ -39,6 +39,7 @@ found in the LICENSE file.
<script src="remoting.js"></script>
<script src="server_log_entry.js"></script>
<script src="stats_accumulator.js"></script>
+ <script src="storage.js"></script>
<script src="suspend_monitor.js"></script>
<script src="toolbar.js"></script>
<script src="ui_mode.js"></script>
diff --git a/remoting/webapp/remoting.js b/remoting/webapp/remoting.js
index 8d6513f..83ce05d 100644
--- a/remoting/webapp/remoting.js
+++ b/remoting/webapp/remoting.js
@@ -32,6 +32,9 @@ remoting.Error = {
* Entry point for app initialization.
*/
remoting.init = function() {
+ // TODO(jamiewalch): Remove this when we migrate to apps v2.
+ remoting.initMockStorage();
+
remoting.logExtensionInfoAsync_();
l10n.localize();
// Create global objects.
@@ -75,18 +78,20 @@ remoting.init = function() {
button.disabled = true;
}
- // Parse URL parameters.
- var urlParams = getUrlParameters_();
- if ('mode' in urlParams) {
- if (urlParams['mode'] == 'me2me') {
- var hostId = urlParams['hostId'];
- remoting.connectMe2Me(hostId, true);
- return;
+ var onLoad = function() {
+ // Parse URL parameters.
+ var urlParams = getUrlParameters_();
+ if ('mode' in urlParams) {
+ if (urlParams['mode'] == 'me2me') {
+ var hostId = urlParams['hostId'];
+ remoting.connectMe2Me(hostId, true);
+ return;
+ }
}
+ // No valid URL parameters, start up normally.
+ remoting.initDaemonUi();
}
-
- // No valid URL parameters, start up normally.
- remoting.initDaemonUi();
+ remoting.hostList.load(onLoad);
};
/**
@@ -127,7 +132,7 @@ remoting.updateLocalHostState = function() {
remoting.hostList.display();
};
remoting.hostController.getLocalHostStateAndId(onHostState);
-}
+};
/**
* Log information about the current extension.
@@ -175,13 +180,14 @@ remoting.promptClose = function() {
};
/**
- * Sign the user out of Chromoting by clearing the OAuth refresh token.
+ * Sign the user out of Chromoting by clearing (and revoking, if possible) the
+ * OAuth refresh token.
*
- * Also clear all localStorage, to avoid leaking information.
+ * Also clear all local storage, to avoid leaking information.
*/
remoting.signOut = function() {
remoting.oauth2.clear();
- window.localStorage.clear();
+ chrome.storage.local.clear();
remoting.setMode(remoting.AppMode.UNAUTHENTICATED);
};
diff --git a/remoting/webapp/storage.js b/remoting/webapp/storage.js
new file mode 100644
index 0000000..7296984
--- /dev/null
+++ b/remoting/webapp/storage.js
@@ -0,0 +1,134 @@
+// 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.
+
+/**
+ * @fileoverview
+ * Mock class for Chrome's storage API to aid with the transition to Apps v2.
+ *
+ * The local storage API is not supported in Apps v2, so we'll have to use
+ * the new storage API instead. This doesn't require Apps v2, but it turns
+ * out that migrating our OAuth2 code to the new API is non-trivial; since
+ * that code will need to be rewritten to be Apps-v2-compatible anyway, a
+ * mock seems like a good temporary solution.
+ */
+
+'use strict';
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+remoting.initMockStorage = function() {
+ if (typeof(chrome.storage) != 'undefined') {
+ console.warn('Congratulations! You already have access to chrome.storage.',
+ 'You should probably remove the call to initMockStorage.');
+ } else {
+ /** @type {Object} */
+ chrome.storage = {};
+ chrome.storage.local = new remoting.MockStorage();
+ }
+};
+
+/**
+ * @constructor
+ */
+remoting.MockStorage = function() {
+};
+
+/** @type {number} Delay for |get|, in ms, to simulate slow local storage
+ * and test correct asynchronous behavior. A value of 0 results in
+ * synchronous behavior.
+ */
+remoting.MockStorage.GET_DELAY = 0;
+
+/**
+ * @param {string|Array.<string>|Object.<string>} items
+ * @param {function(Object.<string>):void} callback
+ * @return {void}
+ */
+remoting.MockStorage.prototype.get = function(items, callback) {
+ var result = {};
+ if (items == null) {
+ // Return all items for null input.
+ result = window.localStorage;
+
+ } else if (typeof(items) == 'string') {
+ // If the input is a string, return one or zero items, depending on
+ // whether or not the value is stored in localStorage.
+ if (items in window.localStorage) {
+ result[items] = window.localStorage.getItem(items);
+ }
+
+ } else if (items.constructor == Array) {
+ // If the input is an array, return those items that have an entry
+ // in localStorage.
+ for (var index in items) {
+ /** @type {string} */
+ var item = items[index];
+ if (item in window.localStorage) {
+ result[item] = window.localStorage.getItem(item);
+ }
+ }
+
+ } else {
+ // If the input is a dictionary, return the localStorage value for
+ // items that are stored, and the dictionary value otherwise.
+ for (var item in items) {
+ if (item in window.localStorage) {
+ result[item] = window.localStorage.getItem(item);
+ } else {
+ result[item] = items[item];
+ }
+ }
+ }
+
+ if (remoting.MockStorage.GET_DELAY == 0) {
+ callback(result);
+ } else {
+ window.setTimeout(callback.bind(null, result),
+ remoting.MockStorage.GET_DELAY);
+ }
+};
+
+/**
+ * @param {Object.<string>} items
+ * @param {function():void=} opt_callback
+ * @return {void}
+ */
+remoting.MockStorage.prototype.set = function(items, opt_callback) {
+ for (var item in items) {
+ window.localStorage.setItem(item, items[item]);
+ }
+ if (opt_callback) {
+ opt_callback();
+ }
+};
+
+/**
+ * @param {string|Array.<string>} items
+ * @param {function():void=} opt_callback
+ * @return {void}
+ */
+remoting.MockStorage.prototype.remove = function(items, opt_callback) {
+ if (typeof(items) == 'string') {
+ window.localStorage.removeItem(items);
+ } else if (items.constructor == Array) {
+ for (var index in items) {
+ window.localStorage.removeItem(items[index]);
+ }
+ }
+ if (opt_callback) {
+ opt_callback();
+ }
+};
+
+/**
+ * @param {function():void=} opt_callback
+ * @return {void}
+ */
+remoting.MockStorage.prototype.clear = function(opt_callback) {
+ window.localStorage.clear();
+ if (opt_callback) {
+ opt_callback();
+ }
+}; \ No newline at end of file
diff --git a/remoting/webapp/ui_mode.js b/remoting/webapp/ui_mode.js
index e800e4a..77fb468 100644
--- a/remoting/webapp/ui_mode.js
+++ b/remoting/webapp/ui_mode.js
@@ -133,33 +133,52 @@ remoting.getMajorMode = function() {
return remoting.currentMode.split('.')[0];
};
+/**
+ * Helper function for showing or hiding the infographic UI based on
+ * whether or not the user has already dismissed it.
+ *
+ * @param {string} mode
+ * @param {!Object} items
+ */
+remoting.showOrHideCallback = function(mode, items) {
+ // Get the first element of a dictionary or array, without needing to know
+ // the key.
+ /** @type {string} */
+ var key = Object.keys(items)[0];
+ var visited = !!items[key];
+ document.getElementById(mode + '-first-run').hidden = visited;
+ document.getElementById(mode + '-content').hidden = !visited;
+};
+
remoting.showOrHideIt2MeUi = function() {
- var visited = !!window.localStorage.getItem('it2me-visited');
- document.getElementById('it2me-first-run').hidden = visited;
- document.getElementById('it2me-content').hidden = !visited;
+ chrome.storage.local.get('it2me-visited',
+ remoting.showOrHideCallback.bind(null, 'it2me'));
};
remoting.showOrHideMe2MeUi = function() {
- var visited = !!window.localStorage.getItem('me2me-visited');
- document.getElementById('me2me-first-run').hidden = visited;
- document.getElementById('me2me-content').hidden = !visited;
+ chrome.storage.local.get('me2me-visited',
+ remoting.showOrHideCallback.bind(null, 'me2me'));
};
remoting.showIt2MeUiAndSave = function() {
- window.localStorage.setItem('it2me-visited', true);
- remoting.showOrHideIt2MeUi();
+ var items = {};
+ items['it2me-visited'] = true;
+ chrome.storage.local.set(items);
+ remoting.showOrHideCallback('it2me', [true]);
};
remoting.showMe2MeUiAndSave = function() {
- window.localStorage.setItem('me2me-visited', true);
- remoting.showOrHideMe2MeUi();
+ var items = {};
+ items['me2me-visited'] = true;
+ chrome.storage.local.set(items);
+ remoting.showOrHideCallback('me2me', [true]);
};
remoting.resetInfographics = function() {
- window.localStorage.removeItem('it2me-visited');
- window.localStorage.removeItem('me2me-visited');
- remoting.showOrHideIt2MeUi();
- remoting.showOrHideMe2MeUi();
+ chrome.storage.local.remove('it2me-visited');
+ chrome.storage.local.remove('me2me-visited');
+ remoting.showOrHideCallback('it2me', [false]);
+ remoting.showOrHideCallback('me2me', [false]);
}