Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(686)

Side by Side Diff: chrome/browser/resources/file_manager/js/suggest_apps_dialog.js

Issue 23717007: [Files.app] Refinement events of suggest app dialog (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comment Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/resources/file_manager/js/file_manager.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 'use strict'; 5 'use strict';
6 6
7 /** 7 /**
8 * SuggestAppsDialog contains a list box to select an app to be opened the file 8 * SuggestAppsDialog contains a list box to select an app to be opened the file
9 * with. This dialog should be used as action picker for file operations. 9 * with. This dialog should be used as action picker for file operations.
10 */ 10 */
11 11
12 /** 12 /**
13 * The width of the widget (in pixel). 13 * The width of the widget (in pixel).
14 * @type {number} 14 * @type {number}
15 * @const 15 * @const
16 */ 16 */
17 var WEBVIEW_WIDTH = 400; 17 var WEBVIEW_WIDTH = 400;
18 /** 18 /**
19 * The height of the widget (in pixel). 19 * The height of the widget (in pixel).
20 * @type {number} 20 * @type {number}
21 * @const 21 * @const
22 */ 22 */
23 var WEBVIEW_HEIGHT = 480; 23 var WEBVIEW_HEIGHT = 480;
24 24
25 /** 25 /**
26 * The widget of the spinner box (in pixel).
27 * @type {number}
28 * @const
29 */
30 var SPINNER_WIDTH = 300;
31 /**
32 * The height of the spinner box (in pixel).
33 * @type {number}
34 * @const
35 */
36 var SPINNER_HEIGHT = 300;
37
38 /**
26 * The URL of the widget. 39 * The URL of the widget.
27 * @type {string} 40 * @type {string}
28 * @const 41 * @const
29 */ 42 */
30 var CWS_WIDGET_URL = 43 var CWS_WIDGET_URL =
31 'https://clients5.google.com/webstore/wall/cros-widget-container'; 44 'https://clients5.google.com/webstore/wall/cros-widget-container';
32 /** 45 /**
33 * The origin of the widget. 46 * The origin of the widget.
34 * @type {string} 47 * @type {string}
35 * @const 48 * @const
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 * 82 *
70 * @param {HTMLElement} parentNode Node to be parent for this dialog. 83 * @param {HTMLElement} parentNode Node to be parent for this dialog.
71 * @constructor 84 * @constructor
72 * @extends {cr.ui.dialogs.BaseDialog} 85 * @extends {cr.ui.dialogs.BaseDialog}
73 */ 86 */
74 function SuggestAppsDialog(parentNode) { 87 function SuggestAppsDialog(parentNode) {
75 cr.ui.dialogs.BaseDialog.call(this, parentNode); 88 cr.ui.dialogs.BaseDialog.call(this, parentNode);
76 89
77 this.frame_.id = 'suggest-app-dialog'; 90 this.frame_.id = 'suggest-app-dialog';
78 91
92 this.spinnerWrapper_ = this.document_.createElement('div');
93 this.spinnerWrapper_.className = 'spinner-container';
94 this.spinnerWrapper_.style.width = SPINNER_WIDTH + 'px';
95 this.spinnerWrapper_.style.height = SPINNER_HEIGHT + 'px';
96 this.spinnerWrapper_.hidden = true;
97 this.frame_.appendChild(this.spinnerWrapper_);
98
99 this.spinner_ = this.document_.createElement('div');
100 this.spinner_.className = 'spinner';
101 this.spinnerWrapper_.appendChild(this.spinner_);
102
79 this.webviewContainer_ = this.document_.createElement('div'); 103 this.webviewContainer_ = this.document_.createElement('div');
80 this.webviewContainer_.id = 'webview-container'; 104 this.webviewContainer_.id = 'webview-container';
105 this.webviewContainer_.style.width = SPINNER_WIDTH + 'px';
106 this.webviewContainer_.style.height = SPINNER_HEIGHT + 'px';
81 this.frame_.insertBefore(this.webviewContainer_, this.text_.nextSibling); 107 this.frame_.insertBefore(this.webviewContainer_, this.text_.nextSibling);
82 108
83 this.buttons_ = this.document_.createElement('div'); 109 this.buttons_ = this.document_.createElement('div');
84 this.buttons_.id = 'buttons'; 110 this.buttons_.id = 'buttons';
85 this.frame_.appendChild(this.buttons_); 111 this.frame_.appendChild(this.buttons_);
86 112
87 this.webstoreButton_ = this.document_.createElement('div'); 113 this.webstoreButton_ = this.document_.createElement('div');
88 this.webstoreButton_.id = 'webstore-button'; 114 this.webstoreButton_.id = 'webstore-button';
89 this.webstoreButton_.innerHTML = str('SUGGEST_DIALOG_LINK_TO_WEBSTORE'); 115 this.webstoreButton_.innerHTML = str('SUGGEST_DIALOG_LINK_TO_WEBSTORE');
90 this.webstoreButton_.addEventListener( 116 this.webstoreButton_.addEventListener(
91 'click', this.onWebstoreLinkClicked_.bind(this)); 117 'click', this.onWebstoreLinkClicked_.bind(this));
92 this.buttons_.appendChild(this.webstoreButton_); 118 this.buttons_.appendChild(this.webstoreButton_);
93 119
94 this.initialFocusElement_ = this.webviewContainer_; 120 this.initialFocusElement_ = this.webviewContainer_;
95 121
122 this.webview_ = null;
96 this.accessToken_ = null; 123 this.accessToken_ = null;
97 this.widgetUrl_ = CWS_WIDGET_URL; 124 this.widgetUrl_ = CWS_WIDGET_URL;
98 this.widgetOrigin_ = CWS_WIDGET_ORIGIN; 125 this.widgetOrigin_ = CWS_WIDGET_ORIGIN;
99 126
100 // For development, we provide the feature to override the URL of the widget. 127 // For development, we provide the feature to override the URL of the widget.
101 // TODO(yoshiki): Remove this before ShareDialog launches or M31 branch cut. 128 // TODO(yoshiki): Remove this before ShareDialog launches or M31 branch cut.
102 this.urlOverrided_ = false; 129 this.urlOverrided_ = false;
103 chrome.storage.local.get( 130 chrome.storage.local.get(
104 ['widgetUrlOverride'], 131 ['widgetUrlOverride'],
105 function(items) { 132 function(items) {
(...skipping 18 matching lines...) Expand all
124 this.initializationTask_ = new AsyncUtil.Group(); 151 this.initializationTask_ = new AsyncUtil.Group();
125 this.initializationTask_.add(this.retrieveAuthorizeToken_.bind(this)); 152 this.initializationTask_.add(this.retrieveAuthorizeToken_.bind(this));
126 this.initializationTask_.run(); 153 this.initializationTask_.run();
127 } 154 }
128 155
129 SuggestAppsDialog.prototype = { 156 SuggestAppsDialog.prototype = {
130 __proto__: cr.ui.dialogs.BaseDialog.prototype 157 __proto__: cr.ui.dialogs.BaseDialog.prototype
131 }; 158 };
132 159
133 /** 160 /**
134 * @enum {number} 161 * @enum {string}
135 * @const 162 * @const
136 */ 163 */
137 SuggestAppsDialog.State = { 164 SuggestAppsDialog.State = {
138 UNINITIALIZED: 0, 165 UNINITIALIZED: 'SuggestAppsDialog.State.UNINITIALIZED',
139 INITIALIZED: 1, 166 INITIALIZING: 'SuggestAppsDialog.State.INITIALIZING',
140 INSTALLING: 2, 167 INITIALIZE_FAILED_CLOSING:
141 INSTALLED: 3, 168 'SuggestAppsDialog.State.INITIALIZE_FAILED_CLOSING',
142 INSTALL_FAILED: 4, 169 INITIALIZED: 'SuggestAppsDialog.State.INITIALIZED',
170 INSTALLING: 'SuggestAppsDialog.State.INSTALLING',
171 INSTALLED_CLOSING: 'SuggestAppsDialog.State.INSTALLED_CLOSING',
172 CANCELED_CLOSING: 'SuggestAppsDialog.State.CANCELED_CLOSING'
143 }; 173 };
174 Object.freeze(SuggestAppsDialog.State);
175
176 /**
177 * @enum {string}
178 * @const
179 */
180 SuggestAppsDialog.Result = {
181 // Install is done. The install app should be opened.
182 INSTALL_SUCCESSFUL: 'SuggestAppsDialog.Result.INSTALL_SUCCESSFUL',
183 // User cancelled the suggest app dialog. No message should be shown.
184 USER_CANCELL: 'SuggestAppsDialog.Result.USER_CANCELL',
185 // Failed to load the widget. Error message should be shown.
186 FAILED: 'SuggestAppsDialog.Result.FAILED'
187 };
188 Object.freeze(SuggestAppsDialog.Result);
144 189
145 /** 190 /**
146 * @override 191 * @override
147 */ 192 */
148 SuggestAppsDialog.prototype.onInputFocus = function() { 193 SuggestAppsDialog.prototype.onInputFocus = function() {
149 this.webviewContainer_.select(); 194 this.webviewContainer_.select();
150 }; 195 };
151 196
152 /** 197 /**
153 * Injects headers into the passed request. 198 * Injects headers into the passed request.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 /** 235 /**
191 * Shows dialog. 236 * Shows dialog.
192 * 237 *
193 * @param {string} extension Extension of the file. 238 * @param {string} extension Extension of the file.
194 * @param {string} mime Mime of the file. 239 * @param {string} mime Mime of the file.
195 * @param {function(boolean)} onDialogClosed Called when the dialog is closed. 240 * @param {function(boolean)} onDialogClosed Called when the dialog is closed.
196 * The argument is the result of installation: true if an app is installed, 241 * The argument is the result of installation: true if an app is installed,
197 * false otherwise. 242 * false otherwise.
198 */ 243 */
199 SuggestAppsDialog.prototype.show = function(extension, mime, onDialogClosed) { 244 SuggestAppsDialog.prototype.show = function(extension, mime, onDialogClosed) {
245 if (this.state_ != SuggestAppsDialog.State.UNINITIALIZED) {
246 console.error('Invalid state.');
247 return;
248 }
249
200 this.extension_ = extension; 250 this.extension_ = extension;
201 this.mimeType_ = mime; 251 this.mimeType_ = mime;
252 this.onDialogClosed_ = onDialogClosed;
253 this.state_ = SuggestAppsDialog.State.INITIALIZING;
202 254
203 // Makes it sure that the initialization is completed. 255 // Makes it sure that the initialization is completed.
204 this.initializationTask_.run(function() { 256 this.initializationTask_.run(function() {
205 var title = str('SUGGEST_DIALOG_TITLE'); 257 var title = str('SUGGEST_DIALOG_TITLE');
206 258
207 // TODO(yoshiki): Remove this before ShareDialog launches. 259 // TODO(yoshiki): Remove this before ShareDialog launches.
208 if (this.urlOverrided_) 260 if (this.urlOverrided_)
209 title += ' [OVERRIDED]'; 261 title += ' [OVERRIDED]';
210 262
211 cr.ui.dialogs.BaseDialog.prototype.showWithTitle.apply( 263 cr.ui.dialogs.BaseDialog.prototype.showWithTitle.apply(
212 this, [title, '', function() {}, null, null]); 264 this, [title, '', function() {}, null, null]);
213 265
214 this.onDialogClosed_ = onDialogClosed;
215
216 this.webviewContainer_.innerHTML = 266 this.webviewContainer_.innerHTML =
217 '<webview id="cws-widget" partition="persist:cwswidgets"></webview>'; 267 '<webview id="cws-widget" partition="persist:cwswidgets"></webview>';
218 this.webviewContainer_.style.width = WEBVIEW_WIDTH + 'px'; 268 this.webviewContainer_.classList.remove('loaded');
219 this.webviewContainer_.style.height = WEBVIEW_HEIGHT + 'px'; 269 this.webviewContainer_.style.width = SPINNER_WIDTH + 'px';
270 this.webviewContainer_.style.height = SPINNER_HEIGHT + 'px';
220 271
221 var webview = this.container_.querySelector('#cws-widget'); 272 this.webview_ = this.container_.querySelector('#cws-widget');
222 webview.style.width = WEBVIEW_WIDTH + 'px'; 273 this.webview_.request.onBeforeSendHeaders.addListener(
223 webview.style.height = WEBVIEW_HEIGHT + 'px';
224 webview.request.onBeforeSendHeaders.addListener(
225 this.authorizeRequest_.bind(this), 274 this.authorizeRequest_.bind(this),
226 {urls: [this.widgetOrigin_ + '/*']}, 275 {urls: [this.widgetOrigin_ + '/*']},
227 ['blocking', 'requestHeaders']); 276 ['blocking', 'requestHeaders']);
228 webview.addEventListener('newwindow', function(event) { 277
229 // Discard the window object and reopen in an external window. 278 this.spinnerWrapper_.hidden = false;
230 event.window.discard();
231 util.visitURL(e.targetUrl);
232 event.preventDefault();
233 });
234 webview.focus();
235 279
236 this.webviewClient_ = new CWSContainerClient( 280 this.webviewClient_ = new CWSContainerClient(
237 webview, 281 this.webview_,
238 extension, mime, 282 extension, mime,
239 WEBVIEW_WIDTH, WEBVIEW_HEIGHT, 283 WEBVIEW_WIDTH, WEBVIEW_HEIGHT,
240 this.widgetUrl_, this.widgetOrigin_); 284 this.widgetUrl_, this.widgetOrigin_);
241 this.webviewClient_.addEventListener('install-request', 285 this.webviewClient_.addEventListener(CWSContainerClient.Events.LOADED,
242 this.onInstallRequest_.bind(this)); 286 this.onWidgetLoaded_.bind(this));
287 this.webviewClient_.addEventListener(CWSContainerClient.Events.LOAD_FAILED,
288 this.onWidgetLoadFailed_.bind(this));
289 this.webviewClient_.addEventListener(
290 CWSContainerClient.Events.REQUEST_INSTALL,
291 this.onInstallRequest_.bind(this));
243 this.webviewClient_.load(); 292 this.webviewClient_.load();
244
245 this.state_ = SuggestAppsDialog.State.INITIALIZED;
246 }.bind(this)); 293 }.bind(this));
247 }; 294 };
248 295
249 /** 296 /**
250 * Called when the 'See more...' link is clicked to be navigated to Webstore. 297 * Called when the 'See more...' link is clicked to be navigated to Webstore.
251 * @param {Event} e Evnet. 298 * @param {Event} e Evnet.
252 * @private 299 * @private
253 */ 300 */
254 SuggestAppsDialog.prototype.onWebstoreLinkClicked_ = function(e) { 301 SuggestAppsDialog.prototype.onWebstoreLinkClicked_ = function(e) {
255 var webStoreUrl = 302 var webStoreUrl =
256 FileTasks.createWebStoreLink(this.extension_, this.mimeType_); 303 FileTasks.createWebStoreLink(this.extension_, this.mimeType_);
257 chrome.windows.create({url: webStoreUrl}); 304 chrome.windows.create({url: webStoreUrl});
258 this.hide(); 305 this.hide();
259 }; 306 };
260 307
261 /** 308 /**
309 * Called when the widget is loaded successfuly.
310 * @param {Event} event Evnet.
311 * @private
312 */
313 SuggestAppsDialog.prototype.onWidgetLoaded_ = function(event) {
314 this.spinnerWrapper_.hidden = true;
315 this.webviewContainer_.classList.add('loaded');
316 this.state_ = SuggestAppsDialog.State.INITIALIZED;
317
318 this.webviewContainer_.style.width = WEBVIEW_WIDTH + 'px';
319 this.webviewContainer_.style.height = WEBVIEW_HEIGHT + 'px';
320
321 this.webview_.style.width = WEBVIEW_WIDTH + 'px';
322 this.webview_.style.height = WEBVIEW_HEIGHT + 'px';
323 this.webview_.focus();
324 };
325
326 /**
327 * Called when the widget is failed to load.
328 * @param {Event} event Evnet.
329 * @private
330 */
331 SuggestAppsDialog.prototype.onWidgetLoadFailed_ = function(event) {
332 this.spinnerWrapper_.hidden = true;
333 this.state_ = SuggestAppsDialog.State.INITIALIZE_FAILED_CLOSING;
334
335 this.hide();
336 };
337
338 /**
262 * Called when receiving the install request from the webview client. 339 * Called when receiving the install request from the webview client.
263 * @param {Event} e Evnet. 340 * @param {Event} e Evnet.
264 * @private 341 * @private
265 */ 342 */
266 SuggestAppsDialog.prototype.onInstallRequest_ = function(e) { 343 SuggestAppsDialog.prototype.onInstallRequest_ = function(e) {
267 var itemId = e.itemId; 344 var itemId = e.itemId;
268 this.installingItemId_ = itemId; 345 this.installingItemId_ = itemId;
269 346
270 this.appInstaller_ = new AppInstaller(itemId); 347 this.appInstaller_ = new AppInstaller(itemId);
271 this.appInstaller_.install(this.onInstallCompleted_.bind(this)); 348 this.appInstaller_.install(this.onInstallCompleted_.bind(this));
272 349
273 this.state_ = SuggestAppsDialog.State.INSTALLING; 350 this.state_ = SuggestAppsDialog.State.INSTALLING;
274 }; 351 };
275 352
276 /** 353 /**
277 * Called when the installation is completed from the app installer. 354 * Called when the installation is completed from the app installer.
278 * @param {AppInstaller.Result} result Result of the installation. 355 * @param {AppInstaller.Result} result Result of the installation.
279 * @param {string} error Detail of the error. 356 * @param {string} error Detail of the error.
280 * @private 357 * @private
281 */ 358 */
282 SuggestAppsDialog.prototype.onInstallCompleted_ = function(result, error) { 359 SuggestAppsDialog.prototype.onInstallCompleted_ = function(result, error) {
283 this.state_ = (result === AppInstaller.Result.SUCCESS) ?
284 SuggestAppsDialog.State.INSTALLED :
285 SuggestAppsDialog.State.INSTALL_FAILED;
286 var success = (result === AppInstaller.Result.SUCCESS); 360 var success = (result === AppInstaller.Result.SUCCESS);
361 this.state_ = success ?
362 SuggestAppsDialog.State.INSTALLED_CLOSING :
363 SuggestAppsDialog.State.INITIALIZED; // Back to normal state.
287 this.webviewClient_.onInstallCompleted(success, this.installingItemId_); 364 this.webviewClient_.onInstallCompleted(success, this.installingItemId_);
288 this.installingItemId_ = null; 365 this.installingItemId_ = null;
289 366
290 switch (result) { 367 switch (result) {
291 case AppInstaller.Result.SUCCESS: 368 case AppInstaller.Result.SUCCESS:
292 this.hide(); 369 this.hide();
293 break; 370 break;
294 case AppInstaller.Result.CANCELLED: 371 case AppInstaller.Result.CANCELLED:
295 // User cancelled the installation. Do nothing. 372 // User cancelled the installation. Do nothing.
296 break; 373 break;
297 case AppInstaller.Result.ERROR: 374 case AppInstaller.Result.ERROR:
298 fileManager.error.show(str('SUGGEST_DIALOG_INSTALLATION_FAILED')); 375 fileManager.error.show(str('SUGGEST_DIALOG_INSTALLATION_FAILED'));
299 break; 376 break;
300 } 377 }
301 }; 378 };
302 379
303 /** 380 /**
304 * @override 381 * @override
305 */ 382 */
306 SuggestAppsDialog.prototype.hide = function() { 383 SuggestAppsDialog.prototype.hide = function(opt_originalOnHide) {
307 // Install is being aborted. Send the failure result. 384 switch (this.state_) {
308 if (this.state_ == SuggestAppsDialog.State.INSTALLING) { 385 case SuggestAppsDialog.State.INSTALLING:
309 if (this.webviewClient_) 386 // Install is being aborted. Send the failure result.
310 this.webviewClient_.onInstallCompleted(false, this.installingItemId_); 387 // Cancels the install.
311 this.state_ = SuggestAppsDialog.State.INSTALL_FAILED; 388 if (this.webviewClient_)
312 this.installingItemId_ = null; 389 this.webviewClient_.onInstallCompleted(false, this.installingItemId_);
390 this.installingItemId_ = null;
391
392 // Assumes closing the dialog as canceling the install.
393 this.state_ = SuggestAppsDialog.State.CANCELED_CLOSING;
394 break;
395 case SuggestAppsDialog.State.INSTALLED_CLOSING:
396 case SuggestAppsDialog.State.INITIALIZE_FAILED_CLOSING:
397 // Do nothing.
398 break;
399 case SuggestAppsDialog.State.INITIALIZED:
400 this.state_ = SuggestAppsDialog.State.CANCELED_CLOSING;
401 break;
402 default:
403 this.state_ = SuggestAppsDialog.State.CANCELED_CLOSING;
404 console.error('Invalid state.');
313 } 405 }
314 406
315 if (this.webviewClient_) { 407 if (this.webviewClient_) {
316 this.webviewClient_.dispose(); 408 this.webviewClient_.dispose();
317 this.webviewClient_ = null; 409 this.webviewClient_ = null;
318 } 410 }
319 411
320 this.webviewContainer_.innerHTML = ''; 412 this.webviewContainer_.innerHTML = '';
321 this.extension_ = null; 413 this.extension_ = null;
322 this.mime_ = null; 414 this.mime_ = null;
323 415
324 cr.ui.dialogs.BaseDialog.prototype.hide.call(this); 416 cr.ui.dialogs.BaseDialog.prototype.hide.call(
417 this,
418 this.onHide_.bind(this, opt_originalOnHide));
419 };
325 420
421 /**
422 * @param {function()=} opt_originalOnHide Original onHide function passed to
423 * SuggestAppsDialog.hide().
424 * @private
425 */
426 SuggestAppsDialog.prototype.onHide_ = function(opt_originalOnHide) {
326 // Calls the callback after the dialog hides. 427 // Calls the callback after the dialog hides.
327 setTimeout(function() { 428 if (opt_originalOnHide)
328 var installed = this.state_ == SuggestAppsDialog.State.INSTALLED; 429 opt_originalOnHide();
329 this.onDialogClosed_(installed); 430
330 }.bind(this), 0); 431 this.webviewContainer_.style.width = SPINNER_WIDTH + 'px';
432 this.webviewContainer_.style.height = SPINNER_HEIGHT + 'px';
433
434 var result;
435 switch (this.state_) {
436 case SuggestAppsDialog.State.INSTALLED_CLOSING:
437 result = SuggestAppsDialog.Result.INSTALL_SUCCESSFUL;
438 break;
439 case SuggestAppsDialog.State.INITIALIZE_FAILED_CLOSING:
440 result = SuggestAppsDialog.Result.FAILED;
441 break;
442 case SuggestAppsDialog.State.CANCELED_CLOSING:
443 result = SuggestAppsDialog.Result.USER_CANCELL;
444 break;
445 default:
446 result = SuggestAppsDialog.Result.USER_CANCELL;
447 console.error('Invalid state.');
448 }
449 this.state_ = SuggestAppsDialog.State.UNINITIALIZED;
450
451 this.onDialogClosed_(result);
331 }; 452 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/file_manager.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698