Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / chrome_apps / webstore_widget / cws_widget / cws_webview_client.js
blob0cafeab61a005886489ff10946c9469f78a1cbef
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.
5 /**
6  * @param {WebView} webView Web View tag.
7  * @param {number} width Width of the CWS widget.
8  * @param {number} height Height of the CWS widget.
9  * @param {string} url Share Url for an entry.
10  * @param {string} target Target (scheme + host + port) of the widget.
11  * @param {Object<*>} options Options to be sent to the dialog host.
12  * @param {!CWSWidgetContainer.PlatformDelegate} delegate Delegate for accessing
13  *     Chrome platform APIs.
14  * @constructor
15  * @extends {cr.EventTarget}
16  */
17 function CWSContainerClient(webView, width, height, url, target, options,
18                             delegate) {
19   /** @private {!CWSWidgetContainer.PlatformDelegate} */
20   this.delegate_ = delegate;
21   this.webView_ = webView;
22   this.width_ = width;
23   this.height_ = height;
24   this.url_ = url;
25   this.target_ = target;
26   this.options_ = options;
28   this.loaded_ = false;
29   this.loading_ = false;
31   this.onMessageBound_ = this.onMessage_.bind(this);
32   this.onLoadStopBound_ = this.onLoadStop_.bind(this);
33   this.onLoadAbortBound_ = this.onLoadAbort_.bind(this);
36 CWSContainerClient.prototype = {
37   __proto__: cr.EventTarget.prototype
40 /**
41  * Events CWSContainerClient fires
42  *
43  * @enum {string}
44  * @const
45  */
46 CWSContainerClient.Events = {
47   LOADED: 'CWSContainerClient.Events.LOADED',
48   LOAD_FAILED: 'CWSContainerClient.Events.LOAD_FAILED',
49   REQUEST_INSTALL: 'CWSContainerClient.Events.REQUEST_INSTALL',
50   INSTALL_DONE: 'CWSContainerClient.Events.INSTALL_DONE'
52 Object.freeze(CWSContainerClient.Events);
54 /**
55  * Handles messages from the widget
56  * @param {Event} event Message event.
57  * @private
58  */
59 CWSContainerClient.prototype.onMessage_ = function(event) {
60   if (event.origin != this.target_)
61     return;
63   var data = event.data;
64   switch (data['message']) {
65     case 'widget_loaded':
66       this.onWidgetLoaded_();
67       break;
68     case 'widget_load_failed':
69       this.onWidgetLoadFailed_();
70       break;
71     case 'before_install':
72       this.sendInstallRequest_(data['item_id']);
73       break;
74     case 'after_install':
75       this.sendInstallDone_(data['item_id']);
76       break;
77     default:
78       console.error('Unexpected message: ' + data['message'], data);
79   }
82 /**
83  * Called when receiving 'loadstop' event from the <webview>.
84  * @param {Event} event Message event.
85  * @private
86  */
87 CWSContainerClient.prototype.onLoadStop_ = function(event) {
88   if (this.url_ == this.webView_.src && !this.loaded_) {
89     this.loaded_ = true;
90     this.postInitializeMessage_();
91   }
94 /**
95  * Called when the widget is loaded successfully.
96  * @private
97  */
98 CWSContainerClient.prototype.onWidgetLoaded_ = function() {
99   cr.dispatchSimpleEvent(this, CWSContainerClient.Events.LOADED);
103  * Called when the widget is failed to load.
104  * @private
105  */
106 CWSContainerClient.prototype.onWidgetLoadFailed_ = function() {
107   this.sendWidgetLoadFailed_();
111  * Called when receiving the 'loadabort' event from <webview>.
112  * @param {Event} event Message event.
113  * @private
114  */
115 CWSContainerClient.prototype.onLoadAbort_ = function(event) {
116   this.sendWidgetLoadFailed_();
120  * Called when the installation is completed from the suggest-app dialog.
122  * @param {boolean} result True if the installation is success, false if failed.
123  * @param {string} itemId Item id to be installed.
124  */
125 CWSContainerClient.prototype.onInstallCompleted = function(result, itemId) {
126   if (result)
127     this.postInstallSuccessMessage_(itemId);
128   else
129     this.postInstallFailureMessage_(itemId);
133  * Send the fail message to the suggest-app dialog.
134  * @private
135  */
136 CWSContainerClient.prototype.sendWidgetLoadFailed_ = function() {
137   cr.dispatchSimpleEvent(this, CWSContainerClient.Events.LOAD_FAILED);
141  * Send the install request to the suggest-app dialog.
143  * @param {string} itemId Item id to be installed.
144  * @private
145  */
146 CWSContainerClient.prototype.sendInstallRequest_ = function(itemId) {
147   var event = new Event(CWSContainerClient.Events.REQUEST_INSTALL);
148   event.itemId = itemId;
149   this.dispatchEvent(event);
153  * Notifies the suggest-app dialog that the item installation is completed.
155  * @param {string} itemId The installed item ID.
156  * @private
157  */
158 CWSContainerClient.prototype.sendInstallDone_ = function(itemId) {
159   var event = new Event(CWSContainerClient.Events.INSTALL_DONE);
160   event.itemId = itemId;
161   this.dispatchEvent(event);
165  * Send the 'install_failure' message to the widget.
167  * @param {string} itemId Item id to be installed.
168  * @private
169  */
170 CWSContainerClient.prototype.postInstallFailureMessage_ = function(itemId) {
171   var message = {
172     message: 'install_failure',
173     item_id: itemId,
174     v: 1
175   };
177   this.postMessage_(message);
181  * Send the 'install_success' message to the widget.
183  * @param {string} itemId Item id to be installed.
184  * @private
185  */
186 CWSContainerClient.prototype.postInstallSuccessMessage_ = function(itemId) {
187   var message = {
188     message: 'install_success',
189     item_id: itemId,
190     v: 1
191   };
193   this.postMessage_(message);
197  * Send the 'initialize' message to the widget.
198  * @private
199  */
200 CWSContainerClient.prototype.postInitializeMessage_ = function() {
201   new Promise(function(fulfill, reject) {
202     this.delegate_.getInstalledItems(
203         /**
204          * @param {?Array<!string>} items Installed items.
205          *     Null on error.
206          */
207         function(items) {
208           if (!items) {
209             reject('Failed to retrive installed items.');
210             return;
211           }
212           fulfill(items);
213     })
214   }.bind(this)).then(
215       /**
216        * @param {!Array<string>} preinstalledExtensionIDs
217        */
218       function(preinstalledExtensionIDs) {
219         var message = {
220           message: 'initialize',
221           hl: this.delegate_.strings.UI_LOCALE,
222           width: this.width_,
223           height: this.height_,
224           preinstalled_items: preinstalledExtensionIDs,
225           v: 1
226         };
228         if (this.options_) {
229           Object.keys(this.options_).forEach(function(key) {
230             message[key] = this.options_[key];
231           }.bind(this));
232         }
234         this.postMessage_(message);
235       }.bind(this));
239  * Send a message to the widget. This method shouldn't be called directly,
240  * should from more specified posting function (eg. postXyzMessage_()).
242  * @param {Object} message Message object to be posted.
243  * @private
244  */
245 CWSContainerClient.prototype.postMessage_ = function(message) {
246   if (!this.webView_.contentWindow)
247     return;
249   this.webView_.contentWindow.postMessage(message, this.target_);
253  * Loads the page to <webview>. Can be called only once.
254  */
255 CWSContainerClient.prototype.load = function() {
256   if (this.loading_ || this.loaded_)
257     throw new Error('Already loaded.');
258   this.loading_ = true;
259   this.loaded_ = false;
261   window.addEventListener('message', this.onMessageBound_);
262   this.webView_.addEventListener('loadstop', this.onLoadStopBound_);
263   this.webView_.addEventListener('loadabort', this.onLoadAbortBound_);
264   this.webView_.setAttribute('src', this.url_);
268  * Aborts loading of the embedded dialog and performs cleanup.
269  */
270 CWSContainerClient.prototype.abort = function() {
271   window.removeEventListener('message', this.onMessageBound_);
272   this.webView_.removeEventListener('loadstop', this.onLoadStopBound_);
273   this.webView_.removeEventListener(
274       'loadabort', this.onLoadAbortBound_);
275   this.webView_.stop();
279  * Cleans the dialog by removing all handlers.
280  */
281 CWSContainerClient.prototype.dispose = function() {
282   this.abort();