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

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

Issue 39123003: [Files.app] Split the JavaScript files into subdirectories: common, background, and foreground (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed test failure. Created 7 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8 * @param {HTMLElement} parentNode Node to be parent for this dialog.
9 * @constructor
10 * @extends {FileManagerDialogBase}
11 * @implements {ShareClient.Observer}
12 */
13 function ShareDialog(parentNode) {
14 this.queue_ = new AsyncUtil.Queue();
15 this.onQueueTaskFinished_ = null;
16 this.shareClient_ = null;
17 this.spinner_ = null;
18 this.spinnerWrapper_ = null;
19 this.webViewWrapper_ = null;
20 this.webView_ = null;
21 this.failureTimeout_ = null;
22 this.callback_ = null;
23
24 FileManagerDialogBase.call(this, parentNode);
25 }
26
27 /**
28 * Timeout for loading the share dialog before giving up.
29 * @type {number}
30 * @const
31 */
32 ShareDialog.FAILURE_TIMEOUT = 10000;
33
34 /**
35 * The result of opening the dialog.
36 * @enum {string}
37 * @const
38 */
39 ShareDialog.Result = Object.freeze({
40 // The dialog is closed normally. This includes user cancel.
41 SUCCESS: 'success',
42 // The dialog is closed by network error.
43 NETWORK_ERROR: 'networkError',
44 // The dialog is not opened because it is already showing.
45 ALREADY_SHOWING: 'alreadyShowing'
46 });
47
48 /**
49 * Wraps a Web View element and adds authorization headers to it.
50 * @param {string} urlPattern Pattern of urls to be authorized.
51 * @param {WebView} webView Web View element to be wrapped.
52 * @constructor
53 */
54 ShareDialog.WebViewAuthorizer = function(urlPattern, webView) {
55 this.urlPattern_ = urlPattern;
56 this.webView_ = webView;
57 this.initialized_ = false;
58 this.accessToken_ = null;
59 };
60
61 /**
62 * Initializes the web view by installing hooks injecting the authorization
63 * headers.
64 * @param {function()} callback Completion callback.
65 */
66 ShareDialog.WebViewAuthorizer.prototype.initialize = function(callback) {
67 if (this.initialized_) {
68 callback();
69 return;
70 }
71
72 var registerInjectionHooks = function() {
73 this.webView_.removeEventListener('loadstop', registerInjectionHooks);
74 this.webView_.request.onBeforeSendHeaders.addListener(
75 this.authorizeRequest_.bind(this),
76 {urls: [this.urlPattern_]},
77 ['blocking', 'requestHeaders']);
78 this.initialized_ = true;
79 callback();
80 }.bind(this);
81
82 this.webView_.addEventListener('loadstop', registerInjectionHooks);
83 this.webView_.setAttribute('src', 'data:text/html,');
84 };
85
86 /**
87 * Authorizes the web view by fetching the freshest access tokens.
88 * @param {function()} callback Completion callback.
89 */
90 ShareDialog.WebViewAuthorizer.prototype.authorize = function(callback) {
91 // Fetch or update the access token.
92 chrome.fileBrowserPrivate.requestAccessToken(false, // force_refresh
93 function(inAccessToken) {
94 this.accessToken_ = inAccessToken;
95 callback();
96 }.bind(this));
97 };
98
99 /**
100 * Injects headers into the passed request.
101 * @param {Event} e Request event.
102 * @return {{requestHeaders: HttpHeaders}} Modified headers.
103 * @private
104 */
105 ShareDialog.WebViewAuthorizer.prototype.authorizeRequest_ = function(e) {
106 e.requestHeaders.push({
107 name: 'Authorization',
108 value: 'Bearer ' + this.accessToken_
109 });
110 return {requestHeaders: e.requestHeaders};
111 };
112
113 ShareDialog.prototype = {
114 __proto__: FileManagerDialogBase.prototype
115 };
116
117 /**
118 * One-time initialization of DOM.
119 * @private
120 */
121 ShareDialog.prototype.initDom_ = function() {
122 FileManagerDialogBase.prototype.initDom_.call(this);
123 this.frame_.classList.add('share-dialog-frame');
124
125 this.spinnerWrapper_ = this.document_.createElement('div');
126 this.spinnerWrapper_.className = 'spinner-container';
127 this.frame_.appendChild(this.spinnerWrapper_);
128
129 this.spinner_ = this.document_.createElement('div');
130 this.spinner_.className = 'spinner';
131 this.spinnerWrapper_.appendChild(this.spinner_);
132
133 this.webViewWrapper_ = this.document_.createElement('div');
134 this.webViewWrapper_.className = 'share-dialog-webview-wrapper';
135 this.cancelButton_.hidden = true;
136 this.okButton_.hidden = true;
137 this.frame_.insertBefore(this.webViewWrapper_,
138 this.frame_.querySelector('.cr-dialog-buttons'));
139 };
140
141 /**
142 * @override
143 */
144 ShareDialog.prototype.onResized = function(width, height, callback) {
145 if (width && height) {
146 this.webViewWrapper_.style.width = width + 'px';
147 this.webViewWrapper_.style.height = height + 'px';
148 this.webView_.style.width = width + 'px';
149 this.webView_.style.height = height + 'px';
150 }
151 setTimeout(callback, 0);
152 };
153
154 /**
155 * @override
156 */
157 ShareDialog.prototype.onClosed = function() {
158 this.hide();
159 };
160
161 /**
162 * @override
163 */
164 ShareDialog.prototype.onLoaded = function() {
165 if (this.failureTimeout_) {
166 clearTimeout(this.failureTimeout_);
167 this.failureTimeout_ = null;
168 }
169
170 // Logs added temporarily to track crbug.com/288783.
171 console.debug('Loaded.');
172
173 this.okButton_.hidden = false;
174 this.spinnerWrapper_.hidden = true;
175 this.webViewWrapper_.classList.add('loaded');
176 this.webView_.focus();
177 };
178
179 /**
180 * @override
181 */
182 ShareDialog.prototype.onLoadFailed = function() {
183 this.hideWithResult(ShareDialog.Result.NETWORK_ERROR);
184 };
185
186 /**
187 * @override
188 */
189 ShareDialog.prototype.hide = function(opt_onHide) {
190 this.hideWithResult(ShareDialog.Result.SUCCESS, opt_onHide);
191 };
192
193 /**
194 * Hide the dialog with the result and the callback.
195 * @param {ShareDialog.Result} result Result passed to the closing callback.
196 * @param {function()=} opt_onHide Callback called at the end of hiding.
197 */
198 ShareDialog.prototype.hideWithResult = function(result, opt_onHide) {
199 if (!this.isShowing())
200 return;
201
202 if (this.shareClient_) {
203 this.shareClient_.dispose();
204 this.shareClient_ = null;
205 }
206
207 this.webViewWrapper_.textContent = '';
208 if (this.failureTimeout_) {
209 clearTimeout(this.failureTimeout_);
210 this.failureTimeout_ = null;
211 }
212
213 FileManagerDialogBase.prototype.hide.call(
214 this,
215 function() {
216 if (opt_onHide)
217 opt_onHide();
218 this.callback_(result);
219 this.callback_ = null;
220 }.bind(this));
221 };
222
223 /**
224 * Shows the dialog.
225 * @param {FileEntry} entry Entry to share.
226 * @param {function(boolean)} callback Callback to be called when the showing
227 * task is completed. The argument is whether to succeed or not. Note that
228 * cancel is regarded as success.
229 */
230 ShareDialog.prototype.show = function(entry, callback) {
231 // If the dialog is already showing, return the error.
232 if (this.isShowing()) {
233 callback(ShareDialog.Result.ALREADY_SHOWING);
234 return;
235 }
236
237 // Initialize the variables.
238 this.callback_ = callback;
239 this.spinnerWrapper_.hidden = false;
240 this.webViewWrapper_.style.width = '';
241 this.webViewWrapper_.style.height = '';
242
243 // If the embedded share dialog is not started within some time, then
244 // give up and show an error message.
245 this.failureTimeout_ = setTimeout(function() {
246 this.hideWithResult(ShareDialog.Result.NETWORK_ERROR);
247
248 // Logs added temporarily to track crbug.com/288783.
249 console.debug('Timeout. Web View points at: ' + this.webView_.src);
250 }.bind(this), ShareDialog.FAILURE_TIMEOUT);
251
252 // TODO(mtomasz): Move to initDom_() once and reuse <webview> once it gets
253 // fixed. See: crbug.com/260622.
254 this.webView_ = util.createChild(
255 this.webViewWrapper_, 'share-dialog-webview', 'webview');
256 this.webView_.setAttribute('tabIndex', '-1');
257 this.webViewAuthorizer_ = new ShareDialog.WebViewAuthorizer(
258 !window.IN_TEST ? (ShareClient.SHARE_TARGET + '/*') : '<all_urls>',
259 this.webView_);
260 this.webView_.addEventListener('newwindow', function(e) {
261 // Discard the window object and reopen in an external window.
262 e.window.discard();
263 util.visitURL(e.targetUrl);
264 e.preventDefault();
265 });
266 var show = FileManagerDialogBase.prototype.showBlankDialog.call(this);
267 if (!show) {
268 // The code shoundn't get here, since already-showing was handled before.
269 console.error('ShareDialog can\'t be shown.');
270 return;
271 }
272
273 // Initialize and authorize the Web View tag asynchronously.
274 var group = new AsyncUtil.Group();
275
276 // Fetches an url to the sharing dialog.
277 var shareUrl;
278 group.add(function(inCallback) {
279 chrome.fileBrowserPrivate.getShareUrl(
280 entry.toURL(),
281 function(inShareUrl) {
282 if (!chrome.runtime.lastError)
283 shareUrl = inShareUrl;
284 inCallback();
285 });
286 });
287 group.add(this.webViewAuthorizer_.initialize.bind(this.webViewAuthorizer_));
288 group.add(this.webViewAuthorizer_.authorize.bind(this.webViewAuthorizer_));
289
290 // Loads the share widget once all the previous async calls are finished.
291 group.run(function() {
292 // If the url is not obtained, return the network error.
293 if (!shareUrl) {
294 // Logs added temporarily to track crbug.com/288783.
295 console.debug('URL not available.');
296
297 this.hideWithResult(ShareDialog.Result.NETWORK_ERROR);
298 return;
299 }
300 // Already inactive, therefore ignore.
301 if (!this.isShowing())
302 return;
303 this.shareClient_ = new ShareClient(this.webView_,
304 shareUrl,
305 this);
306 this.shareClient_.load();
307 }.bind(this));
308 };
309
310 /**
311 * Tells whether the share dialog is showing or not.
312 *
313 * @return {boolean} True since the show method is called and until the closing
314 * callback is invoked.
315 */
316 ShareDialog.prototype.isShowing = function() {
317 return !!this.callback_;
318 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698