diff options
author | jamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-20 19:06:26 +0000 |
---|---|---|
committer | jamiewalch@google.com <jamiewalch@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-20 19:06:26 +0000 |
commit | de794ebc37fdefdb61f340b8e91f1ac80b1b8678 (patch) | |
tree | b7cb1404d6ddf71a4c2164edbccb98d094a03a6c /remoting | |
parent | 43526ac0e6f164add015dbc79584125486ffd671 (diff) | |
download | chromium_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
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/remoting.gyp | 1 | ||||
-rw-r--r-- | remoting/webapp/host_list.js | 50 | ||||
-rw-r--r-- | remoting/webapp/jscompiler_hacks.js | 7 | ||||
-rw-r--r-- | remoting/webapp/main.html | 1 | ||||
-rw-r--r-- | remoting/webapp/remoting.js | 34 | ||||
-rw-r--r-- | remoting/webapp/storage.js | 134 | ||||
-rw-r--r-- | remoting/webapp/ui_mode.js | 47 |
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]); } |