| 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 |