1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
// 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.
#ifndef CHROME_BROWSER_UI_INTENTS_WEB_INTENT_PICKER_CONTROLLER_H_
#define CHROME_BROWSER_UI_INTENTS_WEB_INTENT_PICKER_CONTROLLER_H_
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/string16.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/favicon/favicon_service.h"
#include "chrome/browser/intents/cws_intents_registry.h"
#include "chrome/browser/intents/web_intents_registry.h"
#include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "webkit/glue/web_intent_data.h"
#include "webkit/glue/web_intent_reply_data.h"
#include "webkit/glue/web_intent_service_data.h"
class Browser;
struct DefaultWebIntentService;
class GURL;
class TabContents;
class WebIntentPicker;
class WebIntentPickerModel;
namespace content {
class WebContents;
class WebIntentsDispatcher;
}
namespace webkit_glue {
struct WebIntentServiceData;
}
// Controls the creation of the WebIntentPicker UI and forwards the user's
// intent handler choice back to the WebContents object.
class WebIntentPickerController
: public content::NotificationObserver,
public WebIntentPickerDelegate,
public extensions::WebstoreInstaller::Delegate {
public:
// The various states that the UI may be in. Public for testing.
enum WebIntentPickerState {
kPickerHidden, // Picker not displayed at all.
kPickerSetup, // Initial setup. Acquires data, keeps picker hidden.
kPickerWaiting, // Displaying "waiting for CWS".
kPickerWaitLong, // "waiting" has displayed for longer than min. time.
kPickerMain, // Displaying main picker dialog.
};
// Events that happen during picker life time. Drive state machine.
enum WebIntentPickerEvent {
kPickerEventHiddenSetupTimeout, // Time for hidden setup exired.
kPickerEventMaxWaitTimeExceeded, // Exceeded max wait time for CWS results.
kPickerEventRegistryDataComplete, // Data from the registry has arrived.
kPickerEventAsyncDataComplete, // Data from registry and CWS has arrived.
};
explicit WebIntentPickerController(TabContents* tab_contents);
virtual ~WebIntentPickerController();
// Sets the intent data and return pathway handler object for which
// this picker was created. The picker takes ownership of
// |intents_dispatcher|. |intents_dispatcher| must not be NULL.
void SetIntentsDispatcher(content::WebIntentsDispatcher* intents_dispatcher);
// Shows the web intent picker given the intent |action| and MIME-type |type|.
void ShowDialog(const string16& action,
const string16& type);
// Called by the location bar to see whether the web intents picker button
// should be shown.
bool ShowLocationBarPickerTool();
// Called by the location bar to notify picker that the button was clicked.
// Called in the controller of the tab which is displaying the service.
void LocationBarPickerToolClicked();
// Called to notify a controller for a page hosting a web intents service
// that the source WebContents has been destroyed.
void SourceWebContentsDestroyed(content::WebContents* source);
protected:
// content::NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// WebIntentPickerDelegate implementation.
virtual void OnServiceChosen(
const GURL& url,
webkit_glue::WebIntentServiceData::Disposition disposition) OVERRIDE;
virtual void OnInlineDispositionWebContentsCreated(
content::WebContents* web_contents) OVERRIDE;
virtual void OnExtensionInstallRequested(const std::string& id) OVERRIDE;
virtual void OnExtensionLinkClicked(const std::string& id) OVERRIDE;
virtual void OnSuggestionsLinkClicked() OVERRIDE;
virtual void OnPickerClosed() OVERRIDE;
virtual void OnChooseAnotherService() OVERRIDE;
virtual void OnClosing() OVERRIDE;
// extensions::WebstoreInstaller::Delegate implementation.
virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
virtual void OnExtensionInstallFailure(const std::string& id,
const std::string& error) OVERRIDE;
private:
friend class WebIntentPickerControllerTest;
friend class WebIntentPickerControllerBrowserTest;
friend class WebIntentPickerControllerIncognitoBrowserTest;
// Dispatches intent to a just-installed extension with ID |extension_id|.
void DispatchToInstalledExtension(const std::string& extension_id);
// Adds a service to the data model.
void AddServiceToModel(const webkit_glue::WebIntentServiceData& service);
// Gets a notification when the return message is sent to the source tab,
// so we can close the picker dialog or service tab.
void OnSendReturnMessage(webkit_glue::WebIntentReplyType reply_type);
// Exposed for tests only.
void set_picker(WebIntentPicker* picker) { picker_ = picker; }
// Exposed for tests only.
void set_model_observer(WebIntentPickerModelObserver* observer) {
picker_model_->set_observer(observer);
}
// Notify the controller that its TabContents is hosting a web intents
// service. Sets the source and dispatcher for the invoking client.
void SetWindowDispositionSource(content::WebContents* source,
content::WebIntentsDispatcher* dispatcher);
// Called to notify a controller for a page hosting a web intents service
// that the source dispatcher has been replied on.
void SourceDispatcherReplied(webkit_glue::WebIntentReplyType reply_type);
// Called by the WebIntentsRegistry, returning |services|, which is
// a list of WebIntentServiceData matching the query.
void OnWebIntentServicesAvailable(
const std::vector<webkit_glue::WebIntentServiceData>& services);
// Called when a default service is returned from the WebIntentsRegistry.
// (Still called with default_service.service_url empty if there are no
// defaults.)
void OnWebIntentDefaultsAvailable(
const DefaultWebIntentService& default_service);
// Coordination method which is delegated to by the registry calls to get
// services and defaults. Checks whether the picker should be shown or if
// default choices allow it to be skipped.
void RegistryCallsCompleted();
// Called when WebIntentServiceData is ready for checking extensions
// when dispatching explicit intents. Gets |services|
// from the WebIntentsRegistry to check for known urls/extensions and find
// disposition data.
void WebIntentServicesForExplicitIntent(
const std::vector<webkit_glue::WebIntentServiceData>& services);
// Called when a favicon is returned from the FaviconService.
void OnFaviconDataAvailable(
FaviconService::Handle handle,
const history::FaviconImageResult& image_result);
// Called when IntentExtensionInfo is returned from the CWSIntentsRegistry.
void OnCWSIntentServicesAvailable(
const CWSIntentsRegistry::IntentExtensionList& extensions);
// Called when a suggested extension's icon is fetched.
void OnExtensionIconURLFetchComplete(const string16& extension_id,
const net::URLFetcher* source);
// Called whenever intent data (both from registry and CWS) arrives.
void OnIntentDataArrived();
// Reset internal state to default values.
void Reset();
typedef base::Callback<void(const gfx::Image&)>
ExtensionIconAvailableCallback;
// Called on a worker thread to decode and resize the extension's icon.
static void DecodeExtensionIconAndResize(
scoped_ptr<std::string> icon_response,
const ExtensionIconAvailableCallback& callback,
const base::Closure& unavailable_callback);
// Called when an extension's icon is successfully decoded and resized.
void OnExtensionIconAvailable(const string16& extension_id,
const gfx::Image& icon_image);
// Called when an extension's icon failed to be decoded or resized.
void OnExtensionIconUnavailable(const string16& extension_id);
// Signals that a picker event has occurred.
void OnPickerEvent(WebIntentPickerEvent event);
// Decrements the |pending_async_count_| and notifies the picker if it
// reaches zero.
void AsyncOperationFinished();
// Invoke the specified service at |service_url| with chosen |disposition|.
void InvokeService(const WebIntentPickerModel::InstalledService& service);
// Sets current dialog state.
void SetDialogState(WebIntentPickerState state);
// Helper to create picker dialog UI.
void CreatePicker();
// Closes the currently active picker.
void ClosePicker();
WebIntentPickerState dialog_state_; // Current state of the dialog.
// A weak pointer to the tab contents that the picker is displayed on.
TabContents* tab_contents_;
// A notification registrar, listening for notifications when the tab closes
// to close the picker ui.
content::NotificationRegistrar registrar_;
// A weak pointer to the picker this controller controls.
WebIntentPicker* picker_;
// The model for the picker. Owned by this controller. It should not be NULL
// while this controller exists, even if the picker is not shown.
scoped_ptr<WebIntentPickerModel> picker_model_;
// A count of the outstanding asynchronous calls.
int pending_async_count_;
// A count of outstanding WebIntentsRegistry calls.
int pending_registry_calls_count_;
// Indicator that there is a pending request for cws data.
bool pending_cws_request_;
// Is true if the picker is currently visible.
// This bool is not equivalent to picker != NULL in a unit test. In that
// case, a picker may be non-NULL before it is shown.
bool picker_shown_;
// Weak pointer to the source WebContents for the intent if the TabContents
// with which this controller is associated is hosting a web intents window
// disposition service.
content::WebContents* window_disposition_source_;
// If this tab is hosting a web intents service, a weak pointer to dispatcher
// that invoked us. Weak pointer.
content::WebIntentsDispatcher* source_intents_dispatcher_;
// Weak pointer to the routing object for the renderer which launched the
// intent. Contains the intent data and a way to signal back to the
// client page.
content::WebIntentsDispatcher* intents_dispatcher_;
// Weak pointer to the tab servicing the intent. Remembered in order to
// close it when a reply is sent.
content::WebContents* service_tab_;
// Request consumer used when asynchronously loading favicons.
CancelableRequestConsumerTSimple<size_t> favicon_consumer_;
base::WeakPtrFactory<WebIntentPickerController> weak_ptr_factory_;
// Timer factory for minimum display time of "waiting" dialog.
base::WeakPtrFactory<WebIntentPickerController> timer_factory_;
DISALLOW_COPY_AND_ASSIGN(WebIntentPickerController);
};
#endif // CHROME_BROWSER_UI_INTENTS_WEB_INTENT_PICKER_CONTROLLER_H_
|