OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_UI_INTENTS_WEB_INTENT_PICKER_CONTROLLER_H_ | |
6 #define CHROME_BROWSER_UI_INTENTS_WEB_INTENT_PICKER_CONTROLLER_H_ | |
7 | |
8 #include <vector> | |
9 | |
10 #include "base/compiler_specific.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/memory/weak_ptr.h" | |
14 #include "base/string16.h" | |
15 #include "chrome/browser/extensions/webstore_installer.h" | |
16 #include "chrome/browser/intents/cws_intents_registry.h" | |
17 #include "chrome/browser/intents/web_intents_registry.h" | |
18 #include "chrome/browser/intents/web_intents_reporting.h" | |
19 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" | |
20 #include "content/public/browser/download_id.h" | |
21 #include "content/public/browser/web_contents_user_data.h" | |
22 #include "webkit/glue/web_intent_data.h" | |
23 #include "webkit/glue/web_intent_reply_data.h" | |
24 #include "webkit/glue/web_intent_service_data.h" | |
25 | |
26 class Browser; | |
27 struct DefaultWebIntentService; | |
28 class GURL; | |
29 class Profile; | |
30 class WebIntentPicker; | |
31 class WebIntentPickerModel; | |
32 | |
33 namespace content { | |
34 class WebContents; | |
35 class WebIntentsDispatcher; | |
36 } | |
37 | |
38 namespace web_intents { | |
39 class NativeServiceFactory; | |
40 class IconLoader; | |
41 } | |
42 | |
43 namespace webkit_glue { | |
44 struct WebIntentServiceData; | |
45 } | |
46 | |
47 // Controls the creation of the WebIntentPicker UI and forwards the user's | |
48 // intent handler choice back to the WebContents object. | |
49 class WebIntentPickerController | |
50 : public WebIntentPickerDelegate, | |
51 public extensions::WebstoreInstaller::Delegate, | |
52 public content::WebContentsUserData<WebIntentPickerController> { | |
53 public: | |
54 | |
55 // The various states that the UI may be in. Public for testing. | |
56 enum WebIntentPickerState { | |
57 kPickerHidden, // Picker not displayed at all. | |
58 kPickerSetup, // Initial setup. Acquires data, keeps picker hidden. | |
59 kPickerWaiting, // Displaying "waiting for CWS". | |
60 kPickerWaitLong, // "waiting" has displayed for longer than min. time. | |
61 kPickerMain, // Displaying main picker dialog. | |
62 kPickerInline, // Displaying inline intent handler. | |
63 }; | |
64 | |
65 // Events that happen during picker life time. Drive state machine. | |
66 enum WebIntentPickerEvent { | |
67 kPickerEventHiddenSetupTimeout, // Time for hidden setup exired. | |
68 kPickerEventMaxWaitTimeExceeded, // Exceeded max wait time for CWS results. | |
69 kPickerEventRegistryDataComplete, // Data from the registry has arrived. | |
70 kPickerEventAsyncDataComplete, // Data from registry and CWS has arrived. | |
71 }; | |
72 | |
73 virtual ~WebIntentPickerController(); | |
74 | |
75 // Sets the intent data and return pathway handler object for which | |
76 // this picker was created. The picker takes ownership of | |
77 // |intents_dispatcher|. |intents_dispatcher| must not be NULL. | |
78 void SetIntentsDispatcher(content::WebIntentsDispatcher* intents_dispatcher); | |
79 | |
80 // Shows the web intent picker given the intent |action| and MIME-type |type|. | |
81 void ShowDialog(const string16& action, | |
82 const string16& type); | |
83 | |
84 // Called directly after SetIntentsDispatcher to handle the dispatch of the | |
85 // intent to the indicated service. The picker model may still be unloaded. | |
86 void InvokeServiceWithSelection( | |
87 const webkit_glue::WebIntentServiceData& service); | |
88 | |
89 // Called by the location bar to see whether the web intents picker button | |
90 // should be shown. | |
91 bool ShowLocationBarPickerButton(); | |
92 | |
93 // Record that the location bar button has been animated. | |
94 void SetLocationBarPickerButtonIndicated() { | |
95 location_bar_button_indicated_ = true; | |
96 } | |
97 | |
98 // Check whether the location bar button has been animated. | |
99 bool location_bar_picker_button_indicated() const { | |
100 return location_bar_button_indicated_; | |
101 } | |
102 | |
103 // Called by the location bar to notify picker that the button was clicked. | |
104 // Called in the controller of the tab which is displaying the service. | |
105 void LocationBarPickerButtonClicked(); | |
106 | |
107 // Called to notify a controller for a page hosting a web intents service | |
108 // that the source WebContents has been destroyed. | |
109 void SourceWebContentsDestroyed(content::WebContents* source); | |
110 | |
111 protected: | |
112 // WebIntentPickerDelegate implementation. | |
113 virtual void OnServiceChosen( | |
114 const GURL& url, | |
115 webkit_glue::WebIntentServiceData::Disposition disposition, | |
116 DefaultsUsage suppress_defaults) OVERRIDE; | |
117 virtual content::WebContents* CreateWebContentsForInlineDisposition( | |
118 Profile* profile, const GURL& url) OVERRIDE; | |
119 virtual void OnExtensionInstallRequested(const std::string& id) OVERRIDE; | |
120 virtual void OnExtensionLinkClicked( | |
121 const std::string& id, | |
122 WindowOpenDisposition disposition) OVERRIDE; | |
123 virtual void OnSuggestionsLinkClicked( | |
124 WindowOpenDisposition disposition) OVERRIDE; | |
125 virtual void OnUserCancelledPickerDialog() OVERRIDE; | |
126 virtual void OnChooseAnotherService() OVERRIDE; | |
127 virtual void OnClosing() OVERRIDE; | |
128 | |
129 // extensions::WebstoreInstaller::Delegate implementation. | |
130 virtual void OnExtensionDownloadStarted(const std::string& id, | |
131 content::DownloadItem* item) OVERRIDE; | |
132 virtual void OnExtensionDownloadProgress( | |
133 const std::string& id, | |
134 content::DownloadItem* item) OVERRIDE; | |
135 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; | |
136 virtual void OnExtensionInstallFailure( | |
137 const std::string& id, | |
138 const std::string& error, | |
139 extensions::WebstoreInstaller::FailureReason reason) OVERRIDE; | |
140 | |
141 private: | |
142 explicit WebIntentPickerController(content::WebContents* web_contents); | |
143 friend class content::WebContentsUserData<WebIntentPickerController>; | |
144 | |
145 friend class WebIntentPickerControllerTest; | |
146 friend class WebIntentPickerControllerBrowserTest; | |
147 friend class WebIntentPickerControllerIncognitoBrowserTest; | |
148 friend class WebIntentsButtonDecorationTest; | |
149 | |
150 // Forward declaraton of the internal implementation class. | |
151 class UMAReporter; | |
152 | |
153 // Dispatches intent to a just-installed extension with ID |extension_id|. | |
154 void DispatchToInstalledExtension(const std::string& extension_id); | |
155 | |
156 // Adds a service to the data model. | |
157 void AddServiceToModel(const webkit_glue::WebIntentServiceData& service); | |
158 | |
159 // Register the user-selected service (indicated by the passed |url|) as | |
160 // the default for the combination of action/type/options in the picker. | |
161 void SetDefaultServiceForSelection(const GURL& url); | |
162 | |
163 // Calculate a digest value for the services in the picker. | |
164 int64 DigestServices(); | |
165 | |
166 // Gets a notification when the return message is sent to the source tab, | |
167 // so we can close the picker dialog or service tab. | |
168 void OnSendReturnMessage(webkit_glue::WebIntentReplyType reply_type); | |
169 | |
170 // Exposed for tests only. | |
171 void set_picker(WebIntentPicker* picker) { picker_ = picker; } | |
172 | |
173 // Exposed for tests only. | |
174 void set_model_observer(WebIntentPickerModelObserver* observer) { | |
175 picker_model_->set_observer(observer); | |
176 } | |
177 | |
178 // Notify the controller that its WebContents is hosting a web intents | |
179 // service. Sets the source and dispatcher for the invoking client. | |
180 void SetWindowDispositionSource(content::WebContents* source, | |
181 content::WebIntentsDispatcher* dispatcher); | |
182 | |
183 // Called to notify a controller for a page hosting a web intents service | |
184 // that the source dispatcher has been replied on. | |
185 void SourceDispatcherReplied(webkit_glue::WebIntentReplyType reply_type); | |
186 | |
187 // Called by the WebIntentsRegistry, returning |services|, which is | |
188 // a list of WebIntentServiceData matching the query. | |
189 void OnWebIntentServicesAvailable( | |
190 const std::vector<webkit_glue::WebIntentServiceData>& services); | |
191 | |
192 // Called when a default service is returned from the WebIntentsRegistry. | |
193 // (Still called with default_service.service_url empty if there are no | |
194 // defaults.) | |
195 void OnWebIntentDefaultsAvailable( | |
196 const DefaultWebIntentService& default_service); | |
197 | |
198 // Coordination method which is delegated to by the registry calls to get | |
199 // services and defaults. Checks whether the picker should be shown or if | |
200 // default choices allow it to be skipped. | |
201 void RegistryCallsCompleted(); | |
202 | |
203 // Called when WebIntentServiceData is ready for checking extensions | |
204 // when dispatching explicit intents. Gets |services| | |
205 // from the WebIntentsRegistry to check for known urls/extensions and find | |
206 // disposition data. | |
207 void OnWebIntentServicesAvailableForExplicitIntent( | |
208 const std::vector<webkit_glue::WebIntentServiceData>& services); | |
209 | |
210 // Called when IntentExtensionInfo is returned from the CWSIntentsRegistry. | |
211 void OnCWSIntentServicesAvailable( | |
212 const CWSIntentsRegistry::IntentExtensionList& extensions); | |
213 | |
214 void OnIntentDataArrived(); | |
215 | |
216 // Reset internal state to default values. | |
217 void Reset(); | |
218 | |
219 // Called to show a custom extension install dialog. | |
220 void OnShowExtensionInstallDialog( | |
221 const ExtensionInstallPrompt::ShowParams& show_params, | |
222 ExtensionInstallPrompt::Delegate* delegate, | |
223 const ExtensionInstallPrompt::Prompt& prompt); | |
224 | |
225 // Signals that a picker event has occurred. | |
226 void OnPickerEvent(WebIntentPickerEvent event); | |
227 | |
228 // Decrements the |pending_async_count_| and notifies the picker if it | |
229 // reaches zero. | |
230 void AsyncOperationFinished(); | |
231 | |
232 // Invoke the specified service at |service_url| with chosen |disposition|. | |
233 void InvokeService(const WebIntentPickerModel::InstalledService& service); | |
234 | |
235 // Sets current dialog state. | |
236 void SetDialogState(WebIntentPickerState state); | |
237 | |
238 // Helper to create picker dialog UI. | |
239 void CreatePicker(); | |
240 | |
241 // Closes the currently active picker. | |
242 void ClosePicker(); | |
243 | |
244 // Re-starts the process of showing the dialog, suppressing any default | |
245 // queries. Called on the user clicking Use-Another-Service. | |
246 void ReshowDialog(); | |
247 | |
248 // Delegate for ShowDialog and ReshowDialog. Starts all the data queries for | |
249 // loading the picker model and showing the dialog. | |
250 void ShowDialog(DefaultsUsage suppress_defaults); | |
251 | |
252 // Cancel a pending download if any. | |
253 void CancelDownload(); | |
254 | |
255 WebIntentPickerState dialog_state_; // Current state of the dialog. | |
256 | |
257 // A weak pointer to the web contents that the picker is displayed on. | |
258 content::WebContents* web_contents_; | |
259 | |
260 // A weak pointer to the profile for the web contents. | |
261 Profile* profile_; | |
262 | |
263 // A weak pointer to the picker this controller controls. | |
264 WebIntentPicker* picker_; | |
265 | |
266 // The model for the picker. Owned by this controller. It should not be NULL | |
267 // while this controller exists, even if the picker is not shown. | |
268 scoped_ptr<WebIntentPickerModel> picker_model_; | |
269 | |
270 // UMA reporting manager. | |
271 scoped_ptr<UMAReporter> uma_reporter_; | |
272 | |
273 // A count of the outstanding asynchronous calls. | |
274 int pending_async_count_; | |
275 | |
276 // A count of outstanding WebIntentsRegistry calls. | |
277 int pending_registry_calls_count_; | |
278 | |
279 // Indicator that there is a pending request for cws data. | |
280 bool pending_cws_request_; | |
281 | |
282 // Is true if the picker is currently visible. | |
283 // This bool is not equivalent to picker != NULL in a unit test. In that | |
284 // case, a picker may be non-NULL before it is shown. | |
285 bool picker_shown_; | |
286 | |
287 #if defined(TOOLKIT_VIEWS) | |
288 // Set to true if user cancelled the picker dialog. Set to false if the picker | |
289 // dialog is closing for any other reason. | |
290 // TODO(rouslan): We need to fix DialogDelegate in Views to notify us when the | |
291 // user closes the picker dialog. This boolean is a mediocre workaround for | |
292 // lack of that information. | |
293 bool cancelled_; | |
294 #endif | |
295 | |
296 // Weak pointer to the source WebContents for the intent if it is associated | |
297 // with this controller and hosting a web intents window disposition service. | |
298 content::WebContents* window_disposition_source_; | |
299 | |
300 // If this tab is hosting a web intents service, a weak pointer to dispatcher | |
301 // that invoked us. Weak pointer. | |
302 content::WebIntentsDispatcher* source_intents_dispatcher_; | |
303 | |
304 // Weak pointer to the routing object for the renderer which launched the | |
305 // intent. Contains the intent data and a way to signal back to the | |
306 // client page. | |
307 content::WebIntentsDispatcher* intents_dispatcher_; | |
308 | |
309 // Saves whether the use-another-service button has been | |
310 // animated on the location bar. | |
311 bool location_bar_button_indicated_; | |
312 | |
313 // Weak pointer to the tab servicing the intent. Remembered in order to | |
314 // close it when a reply is sent. | |
315 content::WebContents* service_tab_; | |
316 | |
317 // Object managing the details of icon loading. | |
318 scoped_ptr<web_intents::IconLoader> icon_loader_; | |
319 | |
320 // Factory for weak pointers used in callbacks for async calls to load the | |
321 // picker model. | |
322 base::WeakPtrFactory<WebIntentPickerController> weak_ptr_factory_; | |
323 | |
324 // Timer factory for minimum display time of "waiting" dialog. | |
325 base::WeakPtrFactory<WebIntentPickerController> timer_factory_; | |
326 | |
327 // Weak pointers for the dispatcher OnSendReturnMessage will not be | |
328 // cancelled on picker close. | |
329 base::WeakPtrFactory<WebIntentPickerController> dispatcher_factory_; | |
330 | |
331 // Bucket identifier for UMA reporting. Saved off in a field | |
332 // to avoid repeated calculation of the bucket across | |
333 // multiple UMA calls. Should be recalculated each time | |
334 // |intents_dispatcher_| is set. | |
335 web_intents::UMABucket uma_bucket_; | |
336 | |
337 // Factory used to obtain instance of native services. | |
338 scoped_ptr<web_intents::NativeServiceFactory> native_services_; | |
339 | |
340 // The ID of a pending extension download. | |
341 content::DownloadId download_id_; | |
342 | |
343 // Manager for a pending extension download and installation. | |
344 scoped_refptr<extensions::WebstoreInstaller> webstore_installer_; | |
345 | |
346 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerController); | |
347 }; | |
348 | |
349 #endif // CHROME_BROWSER_UI_INTENTS_WEB_INTENT_PICKER_CONTROLLER_H_ | |
OLD | NEW |