• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {WebView} webView Web View tag.
9 * @param {string} url Share Url for an entry.
10 * @param {ShareClient.Observer} observer Observer instance.
11 * @constructor
12 */
13function ShareClient(webView, url, observer) {
14  this.webView_ = webView;
15  this.url_ = url;
16  this.observer_ = observer;
17  this.loaded_ = false;
18  this.loading_ = false;
19  this.onMessageBound_ = this.onMessage_.bind(this);
20  this.onLoadStopBound_ = this.onLoadStop_.bind(this);
21  this.onLoadAbortBound_ = this.onLoadAbort_.bind(this);
22}
23
24/**
25 * Source origin of the client.
26 * @type {string}
27 * @const
28 */
29ShareClient.SHARE_ORIGIN =
30    'chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj';
31
32/**
33 * Target origin of the embedded dialog.
34 * @type {string}
35 * @const
36 */
37ShareClient.SHARE_TARGET = 'https://drive.google.com';
38
39/**
40 * Observes for state changes of the embedded dialog.
41 * @interface
42 */
43ShareClient.Observer = function() {
44};
45
46/**
47 * Notifies about the embedded dialog being loaded.
48 */
49ShareClient.Observer.prototype.onLoaded = function() {
50};
51
52/**
53 * Notifies when the the embedded dialog failed to load.
54 */
55ShareClient.Observer.prototype.onLoadingFailed = function() {
56};
57
58/**
59 * Notifies about changed dimensions of the embedded dialog.
60 * @param {number} width Width in pixels.
61 * @param {number} height Height in pixels.
62 * @param {function()} callback Completion callback. Call when finished
63 *     handling the resize.
64 */
65ShareClient.Observer.prototype.onResized = function(width, height, callback) {
66};
67
68/**
69 * Notifies about the embedded dialog being closed.
70 */
71ShareClient.Observer.prototype.onClosed = function() {
72};
73
74/**
75 * Handles messages from the embedded dialog.
76 * @param {Event} e Message event.
77 * @private
78 */
79ShareClient.prototype.onMessage_ = function(e) {
80  if (e.origin != ShareClient.SHARE_TARGET && !window.IN_TEST) {
81    // Logs added temporarily to track crbug.com/288783.
82    console.debug('Received a message from an illegal origin: ' + e.origin);
83    return;
84  }
85
86  var data = JSON.parse(e.data);
87  // Logs added temporarily to track crbug.com/288783.
88  console.debug('Received message: ' + data.type);
89
90  switch (data.type) {
91    case 'resize':
92      this.observer_.onResized(data.args.width,
93                               data.args.height,
94                               this.postMessage_.bind(this, 'resizeComplete'));
95      break;
96    case 'prepareForVisible':
97      this.postMessage_('prepareComplete');
98      if (!this.loaded_) {
99        this.loading_ = false;
100        this.loaded_ = true;
101        this.observer_.onLoaded();
102      }
103      break;
104    case 'setVisible':
105      if (!data.args.visible)
106        this.observer_.onClosed();
107      break;
108  }
109};
110
111/**
112 * Handles completion of the web view request.
113 * @param {Event} e Message event.
114 * @private
115 */
116ShareClient.prototype.onLoadStop_ = function(e) {
117  // Logs added temporarily to track crbug.com/288783.
118  console.debug('Web View loaded.');
119
120  this.postMessage_('makeBodyVisible');
121};
122
123/**
124 * Handles termination of the web view request.
125 * @param {Event} e Message event.
126 * @private
127 */
128ShareClient.prototype.onLoadAbort_ = function(e) {
129  // Logs added temporarily to track crbug.com/288783.
130  console.debug('Web View failed to load with error: ' + e.reason + ', url: ' +
131      e.url + ' while requested: ' + this.url_);
132
133  this.observer_.onLoadFailed();
134};
135
136/**
137 * Sends a message to the embedded dialog.
138 * @param {string} type Message type.
139 * @param {Object=} opt_args Optional arguments.
140 * @private
141 */
142ShareClient.prototype.postMessage_ = function(type, opt_args) {
143  // Logs added temporarily to track crbug.com/288783.
144  console.debug('Sending message: ' + type);
145
146  var message = {
147    type: type,
148    args: opt_args
149  };
150  this.webView_.contentWindow.postMessage(
151      JSON.stringify(message),
152      !window.IN_TEST ? ShareClient.SHARE_TARGET : '*');
153};
154
155/**
156 * Loads the embedded dialog. Can be called only one.
157 */
158ShareClient.prototype.load = function() {
159  if (this.loading_ || this.loaded_)
160    throw new Error('Already loaded.');
161  this.loading_ = true;
162
163  // Logs added temporarily to track crbug.com/288783.
164  console.debug('Loading.');
165
166  window.addEventListener('message', this.onMessageBound_);
167  this.webView_.addEventListener('loadstop', this.onLoadStopBound_);
168  this.webView_.addEventListener('loadabort', this.onLoadAbortBound_);
169  this.webView_.setAttribute('src', this.url_);
170};
171
172/**
173 * Aborts loading of the embedded dialog and performs cleanup.
174 */
175ShareClient.prototype.abort = function() {
176  window.removeEventListener('message', this.onMessageBound_);
177  this.webView_.removeEventListener('loadstop', this.onLoadStopBound_);
178  this.webView_.removeEventListener(
179      'loadabort', this.onLoadAbortBound_);
180  this.webView_.stop();
181};
182
183/**
184 * Cleans the dialog by removing all handlers.
185 */
186ShareClient.prototype.dispose = function() {
187  this.abort();
188};
189