OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/extensions/extension_service.h" | 13 #include "chrome/browser/extensions/extension_service.h" |
14 #include "chrome/browser/extensions/platform_app_launcher.h" | 14 #include "chrome/browser/extensions/platform_app_launcher.h" |
15 #include "chrome/browser/extensions/webstore_installer.h" | 15 #include "chrome/browser/extensions/webstore_installer.h" |
16 #include "chrome/browser/favicon/favicon_service.h" | 16 #include "chrome/browser/favicon/favicon_service.h" |
17 #include "chrome/browser/intents/cws_intents_registry_factory.h" | 17 #include "chrome/browser/intents/cws_intents_registry_factory.h" |
18 #include "chrome/browser/intents/default_web_intent_service.h" | 18 #include "chrome/browser/intents/default_web_intent_service.h" |
19 #include "chrome/browser/intents/web_intents_registry_factory.h" | 19 #include "chrome/browser/intents/web_intents_registry_factory.h" |
20 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
21 #include "chrome/browser/tab_contents/tab_util.h" | 21 #include "chrome/browser/tab_contents/tab_util.h" |
22 #include "chrome/browser/ui/browser.h" | 22 #include "chrome/browser/ui/browser.h" |
23 #include "chrome/browser/ui/browser_finder.h" | 23 #include "chrome/browser/ui/browser_finder.h" |
24 #include "chrome/browser/ui/browser_list.h" | 24 #include "chrome/browser/ui/browser_list.h" |
25 #include "chrome/browser/ui/browser_navigator.h" | 25 #include "chrome/browser/ui/browser_navigator.h" |
26 #include "chrome/browser/ui/browser_tabstrip.h" | 26 #include "chrome/browser/ui/browser_tabstrip.h" |
| 27 #include "chrome/browser/ui/constrained_window_tab_helper.h" |
27 #include "chrome/browser/ui/intents/web_intent_picker.h" | 28 #include "chrome/browser/ui/intents/web_intent_picker.h" |
28 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | 29 #include "chrome/browser/ui/intents/web_intent_picker_model.h" |
29 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 30 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
30 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 31 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
31 #include "chrome/browser/webdata/web_data_service.h" | 32 #include "chrome/browser/webdata/web_data_service.h" |
32 #include "chrome/common/chrome_notification_types.h" | 33 #include "chrome/common/chrome_notification_types.h" |
33 #include "chrome/common/url_constants.h" | 34 #include "chrome/common/url_constants.h" |
34 #include "content/public/browser/browser_thread.h" | 35 #include "content/public/browser/browser_thread.h" |
35 #include "content/public/browser/navigation_controller.h" | 36 #include "content/public/browser/navigation_controller.h" |
36 #include "content/public/browser/notification_source.h" | 37 #include "content/public/browser/notification_source.h" |
(...skipping 16 matching lines...) Expand all Loading... |
53 | 54 |
54 namespace { | 55 namespace { |
55 | 56 |
56 const char kShareActionURL[] = "http://webintents.org/share"; | 57 const char kShareActionURL[] = "http://webintents.org/share"; |
57 const char kEditActionURL[] = "http://webintents.org/edit"; | 58 const char kEditActionURL[] = "http://webintents.org/edit"; |
58 const char kViewActionURL[] = "http://webintents.org/view"; | 59 const char kViewActionURL[] = "http://webintents.org/view"; |
59 const char kPickActionURL[] = "http://webintents.org/pick"; | 60 const char kPickActionURL[] = "http://webintents.org/pick"; |
60 const char kSubscribeActionURL[] = "http://webintents.org/subscribe"; | 61 const char kSubscribeActionURL[] = "http://webintents.org/subscribe"; |
61 const char kSaveActionURL[] = "http://webintents.org/save"; | 62 const char kSaveActionURL[] = "http://webintents.org/save"; |
62 | 63 |
| 64 // Maximum amount of time to delay displaying dialog while waiting for data. |
| 65 const int kMaxHiddenSetupTimeMs = 200; |
| 66 |
| 67 // Minimum amount of time to show waiting dialog, if it is shown. |
| 68 const int kMinThrobberDisplayTimeMs = 2000; |
| 69 |
| 70 |
63 // Gets the favicon service for the profile in |tab_contents|. | 71 // Gets the favicon service for the profile in |tab_contents|. |
64 FaviconService* GetFaviconService(TabContents* tab_contents) { | 72 FaviconService* GetFaviconService(TabContents* tab_contents) { |
65 return tab_contents->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); | 73 return tab_contents->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); |
66 } | 74 } |
67 | 75 |
68 // Gets the web intents registry for the profile in |tab_contents|. | 76 // Gets the web intents registry for the profile in |tab_contents|. |
69 WebIntentsRegistry* GetWebIntentsRegistry(TabContents* tab_contents) { | 77 WebIntentsRegistry* GetWebIntentsRegistry(TabContents* tab_contents) { |
70 return WebIntentsRegistryFactory::GetForProfile(tab_contents->profile()); | 78 return WebIntentsRegistryFactory::GetForProfile(tab_contents->profile()); |
71 } | 79 } |
72 | 80 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 } | 162 } |
155 | 163 |
156 private: | 164 private: |
157 base::WeakPtr<WebIntentPickerController> controller_; | 165 base::WeakPtr<WebIntentPickerController> controller_; |
158 }; | 166 }; |
159 | 167 |
160 } // namespace | 168 } // namespace |
161 | 169 |
162 WebIntentPickerController::WebIntentPickerController( | 170 WebIntentPickerController::WebIntentPickerController( |
163 TabContents* tab_contents) | 171 TabContents* tab_contents) |
164 : tab_contents_(tab_contents), | 172 : dialog_state_(kPickerHidden), |
| 173 tab_contents_(tab_contents), |
165 picker_(NULL), | 174 picker_(NULL), |
166 picker_model_(new WebIntentPickerModel()), | 175 picker_model_(new WebIntentPickerModel()), |
167 pending_async_count_(0), | 176 pending_async_count_(0), |
168 pending_registry_calls_count_(0), | 177 pending_registry_calls_count_(0), |
| 178 pending_cws_request_(false), |
169 picker_shown_(false), | 179 picker_shown_(false), |
170 window_disposition_source_(NULL), | 180 window_disposition_source_(NULL), |
171 source_intents_dispatcher_(NULL), | 181 source_intents_dispatcher_(NULL), |
172 intents_dispatcher_(NULL), | 182 intents_dispatcher_(NULL), |
173 service_tab_(NULL), | 183 service_tab_(NULL), |
174 weak_ptr_factory_(this) { | 184 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| 185 ALLOW_THIS_IN_INITIALIZER_LIST(timer_factory_(this)) { |
175 content::NavigationController* controller = | 186 content::NavigationController* controller = |
176 &tab_contents->web_contents()->GetController(); | 187 &tab_contents->web_contents()->GetController(); |
177 registrar_.Add(this, content::NOTIFICATION_LOAD_START, | 188 registrar_.Add(this, content::NOTIFICATION_LOAD_START, |
178 content::Source<content::NavigationController>(controller)); | 189 content::Source<content::NavigationController>(controller)); |
179 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING, | 190 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING, |
180 content::Source<content::NavigationController>(controller)); | 191 content::Source<content::NavigationController>(controller)); |
181 } | 192 } |
182 | 193 |
183 WebIntentPickerController::~WebIntentPickerController() { | 194 WebIntentPickerController::~WebIntentPickerController() { |
184 } | 195 } |
185 | 196 |
186 // TODO(gbillock): combine this with ShowDialog. | 197 // TODO(gbillock): combine this with ShowDialog. |
187 void WebIntentPickerController::SetIntentsDispatcher( | 198 void WebIntentPickerController::SetIntentsDispatcher( |
188 content::WebIntentsDispatcher* intents_dispatcher) { | 199 content::WebIntentsDispatcher* intents_dispatcher) { |
189 intents_dispatcher_ = intents_dispatcher; | 200 intents_dispatcher_ = intents_dispatcher; |
190 intents_dispatcher_->RegisterReplyNotification( | 201 intents_dispatcher_->RegisterReplyNotification( |
191 base::Bind(&WebIntentPickerController::OnSendReturnMessage, | 202 base::Bind(&WebIntentPickerController::OnSendReturnMessage, |
192 weak_ptr_factory_.GetWeakPtr())); | 203 weak_ptr_factory_.GetWeakPtr())); |
193 } | 204 } |
194 | |
195 void WebIntentPickerController::ShowDialog(const string16& action, | 205 void WebIntentPickerController::ShowDialog(const string16& action, |
196 const string16& type) { | 206 const string16& type) { |
| 207 |
| 208 // As soon as the dialog is requested, block all input events |
| 209 // on the original tab. |
| 210 tab_contents_->constrained_window_tab_helper()->BlockTabContent(true); |
| 211 |
197 // Only show a picker once. | 212 // Only show a picker once. |
198 // TODO(gbillock): There's a hole potentially admitting multiple | 213 // TODO(gbillock): There's a hole potentially admitting multiple |
199 // in-flight dispatches since we don't create the picker | 214 // in-flight dispatches since we don't create the picker |
200 // in this method, but only after calling the registry. | 215 // in this method, but only after calling the registry. |
201 if (picker_shown_) { | 216 if (picker_shown_) { |
202 if (intents_dispatcher_) { | 217 if (intents_dispatcher_) { |
203 intents_dispatcher_->SendReplyMessage( | 218 intents_dispatcher_->SendReplyMessage( |
204 webkit_glue::WEB_INTENT_REPLY_FAILURE, | 219 webkit_glue::WEB_INTENT_REPLY_FAILURE, |
205 ASCIIToUTF16("Simultaneous intent invocation.")); | 220 ASCIIToUTF16("Simultaneous intent invocation.")); |
206 } | 221 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 // required to find disposition set by service.) | 255 // required to find disposition set by service.) |
241 pending_async_count_++; | 256 pending_async_count_++; |
242 GetWebIntentsRegistry(tab_contents_)->GetIntentServices( | 257 GetWebIntentsRegistry(tab_contents_)->GetIntentServices( |
243 action, type, base::Bind( | 258 action, type, base::Bind( |
244 &WebIntentPickerController::WebIntentServicesForExplicitIntent, | 259 &WebIntentPickerController::WebIntentServicesForExplicitIntent, |
245 weak_ptr_factory_.GetWeakPtr())); | 260 weak_ptr_factory_.GetWeakPtr())); |
246 return; | 261 return; |
247 } | 262 } |
248 } | 263 } |
249 | 264 |
250 pending_async_count_ += 2; | 265 SetDialogState(kPickerSetup); |
251 pending_registry_calls_count_ += 1; | |
252 | 266 |
| 267 pending_async_count_++; |
| 268 pending_registry_calls_count_++; |
253 GetWebIntentsRegistry(tab_contents_)->GetIntentServices( | 269 GetWebIntentsRegistry(tab_contents_)->GetIntentServices( |
254 action, type, | 270 action, type, |
255 base::Bind(&WebIntentPickerController::OnWebIntentServicesAvailable, | 271 base::Bind(&WebIntentPickerController::OnWebIntentServicesAvailable, |
256 weak_ptr_factory_.GetWeakPtr())); | 272 weak_ptr_factory_.GetWeakPtr())); |
257 | 273 |
258 GURL invoking_url = tab_contents_->web_contents()->GetURL(); | 274 GURL invoking_url = tab_contents_->web_contents()->GetURL(); |
259 if (invoking_url.is_valid()) { | 275 if (invoking_url.is_valid()) { |
260 pending_async_count_++; | 276 pending_async_count_++; |
261 pending_registry_calls_count_++; | 277 pending_registry_calls_count_++; |
262 GetWebIntentsRegistry(tab_contents_)->GetDefaultIntentService( | 278 GetWebIntentsRegistry(tab_contents_)->GetDefaultIntentService( |
263 action, type, invoking_url, | 279 action, type, invoking_url, |
264 base::Bind(&WebIntentPickerController::OnWebIntentDefaultsAvailable, | 280 base::Bind(&WebIntentPickerController::OnWebIntentDefaultsAvailable, |
265 weak_ptr_factory_.GetWeakPtr())); | 281 weak_ptr_factory_.GetWeakPtr())); |
266 } | 282 } |
267 | 283 |
268 GetCWSIntentsRegistry(tab_contents_)->GetIntentServices( | 284 pending_cws_request_ = true; |
269 action, type, | 285 pending_async_count_++; |
270 base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable, | 286 GetCWSIntentsRegistry(tab_contents_)->GetIntentServices( |
271 weak_ptr_factory_.GetWeakPtr())); | 287 picker_model_->action(), picker_model_->type(), |
| 288 base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable, |
| 289 weak_ptr_factory_.GetWeakPtr())); |
272 } | 290 } |
273 | 291 |
274 void WebIntentPickerController::Observe( | 292 void WebIntentPickerController::Observe( |
275 int type, | 293 int type, |
276 const content::NotificationSource& source, | 294 const content::NotificationSource& source, |
277 const content::NotificationDetails& details) { | 295 const content::NotificationDetails& details) { |
278 DCHECK(type == content::NOTIFICATION_LOAD_START || | 296 DCHECK(type == content::NOTIFICATION_LOAD_START || |
279 type == chrome::NOTIFICATION_TAB_CLOSING); | 297 type == chrome::NOTIFICATION_TAB_CLOSING); |
280 ClosePicker(); | 298 ClosePicker(); |
281 } | 299 } |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 void WebIntentPickerController::WebIntentServicesForExplicitIntent( | 541 void WebIntentPickerController::WebIntentServicesForExplicitIntent( |
524 const std::vector<webkit_glue::WebIntentServiceData>& services) { | 542 const std::vector<webkit_glue::WebIntentServiceData>& services) { |
525 DCHECK(intents_dispatcher_); | 543 DCHECK(intents_dispatcher_); |
526 DCHECK(intents_dispatcher_->GetIntent().service.is_valid()); | 544 DCHECK(intents_dispatcher_->GetIntent().service.is_valid()); |
527 for (size_t i = 0; i < services.size(); ++i) { | 545 for (size_t i = 0; i < services.size(); ++i) { |
528 if (services[i].service_url != intents_dispatcher_->GetIntent().service) | 546 if (services[i].service_url != intents_dispatcher_->GetIntent().service) |
529 continue; | 547 continue; |
530 | 548 |
531 AddServiceToModel(services[i]); | 549 AddServiceToModel(services[i]); |
532 | 550 |
533 if (services[i].disposition == | 551 InvokeService(picker_model_->GetInstalledServiceAt(i)); |
534 webkit_glue::WebIntentServiceData::DISPOSITION_INLINE) | |
535 CreatePicker(); | |
536 OnServiceChosen(services[i].service_url, | |
537 ConvertDisposition(services[i].disposition)); | |
538 AsyncOperationFinished(); | 552 AsyncOperationFinished(); |
539 return; | 553 return; |
540 } | 554 } |
541 | 555 |
542 // No acceptable extension. The intent cannot be dispatched. | 556 // No acceptable extension. The intent cannot be dispatched. |
543 intents_dispatcher_->SendReplyMessage( | 557 intents_dispatcher_->SendReplyMessage( |
544 webkit_glue::WEB_INTENT_REPLY_FAILURE, ASCIIToUTF16( | 558 webkit_glue::WEB_INTENT_REPLY_FAILURE, ASCIIToUTF16( |
545 "Explicit extension URL is not available.")); | 559 "Explicit extension URL is not available.")); |
546 | 560 |
547 AsyncOperationFinished(); | 561 AsyncOperationFinished(); |
(...skipping 15 matching lines...) Expand all Loading... |
563 if (pending_registry_calls_count_ != 0) return; | 577 if (pending_registry_calls_count_ != 0) return; |
564 | 578 |
565 if (picker_model_->default_service_url().is_valid()) { | 579 if (picker_model_->default_service_url().is_valid()) { |
566 // If there's a default service, dispatch to it immediately | 580 // If there's a default service, dispatch to it immediately |
567 // without showing the picker. | 581 // without showing the picker. |
568 const WebIntentPickerModel::InstalledService* default_service = | 582 const WebIntentPickerModel::InstalledService* default_service = |
569 picker_model_->GetInstalledServiceWithURL( | 583 picker_model_->GetInstalledServiceWithURL( |
570 GURL(picker_model_->default_service_url())); | 584 GURL(picker_model_->default_service_url())); |
571 | 585 |
572 if (default_service != NULL) { | 586 if (default_service != NULL) { |
573 if (default_service->disposition == | 587 InvokeService(*default_service); |
574 WebIntentPickerModel::DISPOSITION_INLINE) | |
575 CreatePicker(); | |
576 | |
577 OnServiceChosen(default_service->url, default_service->disposition); | |
578 return; | 588 return; |
579 } | 589 } |
580 } | 590 } |
581 | 591 |
582 CreatePicker(); | 592 OnPickerEvent(kPickerEventRegistryDataComplete); |
583 picker_->SetActionString(GetIntentActionString( | 593 OnIntentDataArrived(); |
584 UTF16ToUTF8(picker_model_->action()))); | |
585 } | 594 } |
586 | 595 |
587 void WebIntentPickerController::OnFaviconDataAvailable( | 596 void WebIntentPickerController::OnFaviconDataAvailable( |
588 FaviconService::Handle handle, history::FaviconData favicon_data) { | 597 FaviconService::Handle handle, history::FaviconData favicon_data) { |
589 size_t index = favicon_consumer_.GetClientDataForCurrentRequest(); | 598 size_t index = favicon_consumer_.GetClientDataForCurrentRequest(); |
590 if (favicon_data.is_valid()) { | 599 if (favicon_data.is_valid()) { |
591 SkBitmap icon_bitmap; | 600 SkBitmap icon_bitmap; |
592 | 601 |
593 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), | 602 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), |
594 favicon_data.image_data->size(), | 603 favicon_data.image_data->size(), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 weak_ptr_factory_.GetWeakPtr(), info.id))); | 638 weak_ptr_factory_.GetWeakPtr(), info.id))); |
630 | 639 |
631 icon_url_fetcher->SetLoadFlags( | 640 icon_url_fetcher->SetLoadFlags( |
632 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); | 641 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); |
633 icon_url_fetcher->SetRequestContext( | 642 icon_url_fetcher->SetRequestContext( |
634 tab_contents_->profile()->GetRequestContext()); | 643 tab_contents_->profile()->GetRequestContext()); |
635 icon_url_fetcher->Start(); | 644 icon_url_fetcher->Start(); |
636 } | 645 } |
637 | 646 |
638 AsyncOperationFinished(); | 647 AsyncOperationFinished(); |
| 648 pending_cws_request_ = false; |
| 649 OnIntentDataArrived(); |
639 } | 650 } |
640 | 651 |
641 void WebIntentPickerController::OnExtensionIconURLFetchComplete( | 652 void WebIntentPickerController::OnExtensionIconURLFetchComplete( |
642 const string16& extension_id, const net::URLFetcher* source) { | 653 const string16& extension_id, const net::URLFetcher* source) { |
643 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 654 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
644 if (source->GetResponseCode() != 200) { | 655 if (source->GetResponseCode() != 200) { |
645 AsyncOperationFinished(); | 656 AsyncOperationFinished(); |
646 return; | 657 return; |
647 } | 658 } |
648 | 659 |
(...skipping 27 matching lines...) Expand all Loading... |
676 | 687 |
677 // Decode PNG and resize on worker thread. | 688 // Decode PNG and resize on worker thread. |
678 content::BrowserThread::PostBlockingPoolTask( | 689 content::BrowserThread::PostBlockingPoolTask( |
679 FROM_HERE, | 690 FROM_HERE, |
680 base::Bind(&DecodeExtensionIconAndResize, | 691 base::Bind(&DecodeExtensionIconAndResize, |
681 base::Passed(&response), | 692 base::Passed(&response), |
682 available_callback, | 693 available_callback, |
683 unavailable_callback)); | 694 unavailable_callback)); |
684 } | 695 } |
685 | 696 |
| 697 void WebIntentPickerController::OnIntentDataArrived() { |
| 698 DCHECK(picker_model_.get()); |
| 699 |
| 700 if (!pending_cws_request_ && |
| 701 pending_registry_calls_count_ == 0) |
| 702 OnPickerEvent(kPickerEventAsyncDataComplete); |
| 703 } |
| 704 |
686 // static | 705 // static |
687 void WebIntentPickerController::DecodeExtensionIconAndResize( | 706 void WebIntentPickerController::DecodeExtensionIconAndResize( |
688 scoped_ptr<std::string> icon_response, | 707 scoped_ptr<std::string> icon_response, |
689 const ExtensionIconAvailableCallback& callback, | 708 const ExtensionIconAvailableCallback& callback, |
690 const base::Closure& unavailable_callback) { | 709 const base::Closure& unavailable_callback) { |
691 SkBitmap icon_bitmap; | 710 SkBitmap icon_bitmap; |
692 if (gfx::PNGCodec::Decode( | 711 if (gfx::PNGCodec::Decode( |
693 reinterpret_cast<const unsigned char*>(icon_response->data()), | 712 reinterpret_cast<const unsigned char*>(icon_response->data()), |
694 icon_response->length(), | 713 icon_response->length(), |
695 &icon_bitmap)) { | 714 &icon_bitmap)) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 | 767 |
749 void WebIntentPickerController::SourceDispatcherReplied( | 768 void WebIntentPickerController::SourceDispatcherReplied( |
750 webkit_glue::WebIntentReplyType reply_type) { | 769 webkit_glue::WebIntentReplyType reply_type) { |
751 source_intents_dispatcher_ = NULL; | 770 source_intents_dispatcher_ = NULL; |
752 } | 771 } |
753 | 772 |
754 bool WebIntentPickerController::ShowLocationBarPickerTool() { | 773 bool WebIntentPickerController::ShowLocationBarPickerTool() { |
755 return window_disposition_source_ || source_intents_dispatcher_; | 774 return window_disposition_source_ || source_intents_dispatcher_; |
756 } | 775 } |
757 | 776 |
| 777 void WebIntentPickerController::OnPickerEvent(WebIntentPickerEvent event) { |
| 778 switch (event) { |
| 779 case kPickerEventHiddenSetupTimeout: |
| 780 DCHECK(dialog_state_ == kPickerSetup); |
| 781 SetDialogState(kPickerWaiting); |
| 782 break; |
| 783 |
| 784 case kPickerEventMaxWaitTimeExceeded: |
| 785 DCHECK(dialog_state_ == kPickerWaiting); |
| 786 |
| 787 // If registry data is complete, go to main dialog. Otherwise, wait. |
| 788 if (pending_registry_calls_count_ == 0) |
| 789 SetDialogState(kPickerMain); |
| 790 else |
| 791 SetDialogState(kPickerWaitLong); |
| 792 break; |
| 793 |
| 794 case kPickerEventRegistryDataComplete: |
| 795 DCHECK(dialog_state_ == kPickerSetup || |
| 796 dialog_state_ == kPickerWaiting || |
| 797 dialog_state_ == kPickerWaitLong); |
| 798 |
| 799 // If minimum wait dialog time is exceeded, display main dialog. |
| 800 // Either way, we don't do a thing. |
| 801 break; |
| 802 |
| 803 case kPickerEventAsyncDataComplete: |
| 804 DCHECK(dialog_state_ == kPickerSetup || |
| 805 dialog_state_ == kPickerWaiting); |
| 806 |
| 807 // In setup state, transition to main dialog. In waiting state, let |
| 808 // timer expire. |
| 809 if (dialog_state_ == kPickerSetup) |
| 810 SetDialogState(kPickerMain); |
| 811 break; |
| 812 |
| 813 default: |
| 814 NOTREACHED(); |
| 815 break; |
| 816 } |
| 817 } |
| 818 |
758 void WebIntentPickerController::AsyncOperationFinished() { | 819 void WebIntentPickerController::AsyncOperationFinished() { |
759 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 820 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
760 if (--pending_async_count_ == 0) { | 821 if (--pending_async_count_ == 0) { |
761 if (picker_) | 822 if (picker_) |
762 picker_->OnPendingAsyncCompleted(); | 823 picker_->OnPendingAsyncCompleted(); |
763 } | 824 } |
764 } | 825 } |
765 | 826 |
| 827 void WebIntentPickerController::InvokeService( |
| 828 const WebIntentPickerModel::InstalledService& service) { |
| 829 if (service.disposition == WebIntentPickerModel::DISPOSITION_INLINE) { |
| 830 SetDialogState(kPickerMain); |
| 831 } |
| 832 OnServiceChosen(service.url, service.disposition); |
| 833 } |
| 834 |
| 835 void WebIntentPickerController::SetDialogState(WebIntentPickerState state) { |
| 836 // Ignore events that don't change state. |
| 837 if (state == dialog_state_) |
| 838 return; |
| 839 |
| 840 // Any pending timers are abandoned on state changes. |
| 841 timer_factory_.InvalidateWeakPtrs(); |
| 842 |
| 843 switch (state) { |
| 844 case kPickerSetup: |
| 845 DCHECK(dialog_state_ == kPickerHidden); |
| 846 |
| 847 // Post timer CWS pending |
| 848 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 849 base::Bind(&WebIntentPickerController::OnPickerEvent, |
| 850 timer_factory_.GetWeakPtr(), |
| 851 kPickerEventHiddenSetupTimeout), |
| 852 base::TimeDelta::FromMilliseconds(kMaxHiddenSetupTimeMs)); |
| 853 break; |
| 854 |
| 855 case kPickerWaiting: |
| 856 DCHECK(dialog_state_ == kPickerSetup); |
| 857 // Waiting dialog can be dismissed after minimum wait time. |
| 858 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 859 base::Bind(&WebIntentPickerController::OnPickerEvent, |
| 860 timer_factory_.GetWeakPtr(), |
| 861 kPickerEventMaxWaitTimeExceeded), |
| 862 base::TimeDelta::FromMilliseconds(kMinThrobberDisplayTimeMs)); |
| 863 break; |
| 864 |
| 865 case kPickerWaitLong: |
| 866 DCHECK(dialog_state_ == kPickerWaiting); |
| 867 break; |
| 868 |
| 869 case kPickerMain: |
| 870 // No DCHECK - main state can be reached from any state. |
| 871 // Ready to display data. |
| 872 picker_model_->SetWaitingForSuggestions(false); |
| 873 break; |
| 874 |
| 875 case kPickerHidden: |
| 876 break; |
| 877 |
| 878 default: |
| 879 NOTREACHED(); |
| 880 break; |
| 881 |
| 882 } |
| 883 |
| 884 dialog_state_ = state; |
| 885 |
| 886 // Create picker dialog when changing away from hidden state. |
| 887 if (dialog_state_ != kPickerHidden && dialog_state_ != kPickerSetup) |
| 888 CreatePicker(); |
| 889 } |
| 890 |
| 891 |
766 void WebIntentPickerController::CreatePicker() { | 892 void WebIntentPickerController::CreatePicker() { |
767 // If picker is non-NULL, it was set by a test. | 893 // If picker is non-NULL, it was set by a test. |
768 if (picker_ == NULL) | 894 if (picker_ == NULL) |
769 picker_ = WebIntentPicker::Create(tab_contents_, this, picker_model_.get()); | 895 picker_ = WebIntentPicker::Create(tab_contents_, this, picker_model_.get()); |
| 896 picker_->SetActionString(GetIntentActionString( |
| 897 UTF16ToUTF8(picker_model_->action()))); |
770 picker_shown_ = true; | 898 picker_shown_ = true; |
771 } | 899 } |
772 | 900 |
773 void WebIntentPickerController::ClosePicker() { | 901 void WebIntentPickerController::ClosePicker() { |
| 902 SetDialogState(kPickerHidden); |
774 if (picker_) | 903 if (picker_) |
775 picker_->Close(); | 904 picker_->Close(); |
776 } | 905 } |
OLD | NEW |