Chromium Code Reviews| 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 <algorithm> | 5 #include <algorithm> |
| 6 #include <iterator> | 6 #include <iterator> |
| 7 | 7 |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "base/string_util.h" | |
| 12 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/favicon/favicon_service.h" | 14 #include "chrome/browser/favicon/favicon_service.h" |
| 14 #include "chrome/browser/intents/web_intents_registry.h" | 15 #include "chrome/browser/intents/web_intents_registry.h" |
| 15 #include "chrome/browser/intents/web_intents_registry_factory.h" | 16 #include "chrome/browser/intents/web_intents_registry_factory.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 18 #include "chrome/browser/ui/intents/web_intent_picker.h" | 19 #include "chrome/browser/ui/intents/web_intent_picker.h" |
| 19 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 20 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
| 20 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | 21 #include "chrome/browser/ui/intents/web_intent_picker_model.h" |
| 21 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" | 22 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 content::URLFetcherDelegate* d) OVERRIDE { | 88 content::URLFetcherDelegate* d) OVERRIDE { |
| 88 return new TestURLFetcher(id, url, d); | 89 return new TestURLFetcher(id, url, d); |
| 89 } | 90 } |
| 90 }; | 91 }; |
| 91 | 92 |
| 92 } // namespace | 93 } // namespace |
| 93 | 94 |
| 94 class WebIntentPickerMock : public WebIntentPicker, | 95 class WebIntentPickerMock : public WebIntentPicker, |
| 95 public WebIntentPickerModelObserver { | 96 public WebIntentPickerModelObserver { |
| 96 public: | 97 public: |
| 97 WebIntentPickerMock() | 98 WebIntentPickerMock() { |
| 98 : num_installed_services_(0), | 99 reset(); |
| 99 num_icons_changed_(0), | 100 } |
| 100 num_extension_icons_changed_(0), | 101 |
| 101 num_extensions_installed_(0), | 102 void reset() { |
|
groby-ooo-7-16
2012/04/24 21:36:51
Why separate this out? Nobody calls reset?
Greg Billock
2012/04/25 16:04:32
I was using this but found a better way and forgot
| |
| 102 message_loop_started_(false), | 103 num_installed_services_ = 0; |
| 103 pending_async_completed_(false) { | 104 num_icons_changed_ = 0; |
| 105 num_extension_icons_changed_ = 0; | |
| 106 num_extensions_installed_ = 0; | |
| 107 message_loop_started_ = false; | |
| 108 pending_async_completed_ = false; | |
| 109 num_inline_disposition_ = 0; | |
| 110 delegate_ = NULL; | |
| 111 } | |
| 112 | |
| 113 void MockClose() { | |
| 114 delegate_->OnClosing(); | |
| 104 } | 115 } |
| 105 | 116 |
| 106 // WebIntentPicker implementation. | 117 // WebIntentPicker implementation. |
| 107 virtual void Close() OVERRIDE {} | 118 virtual void Close() OVERRIDE {} |
| 108 virtual void SetActionString(const string16& action) OVERRIDE {} | 119 virtual void SetActionString(const string16& action) OVERRIDE {} |
| 109 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE { | 120 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE { |
| 110 num_extensions_installed_++; | 121 num_extensions_installed_++; |
| 111 } | 122 } |
| 112 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE {} | 123 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE {} |
| 113 virtual void OnPendingAsyncCompleted() OVERRIDE { | 124 virtual void OnPendingAsyncCompleted() OVERRIDE { |
| 114 StopWaiting(); | 125 StopWaiting(); |
| 115 } | 126 } |
| 116 | 127 |
| 117 // WebIntentPickerModelObserver implementation. | 128 // WebIntentPickerModelObserver implementation. |
| 118 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE { | 129 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE { |
| 119 num_installed_services_ = | 130 num_installed_services_ = |
| 120 static_cast<int>(model->GetInstalledServiceCount()); | 131 static_cast<int>(model->GetInstalledServiceCount()); |
| 121 } | 132 } |
| 122 virtual void OnFaviconChanged( | 133 virtual void OnFaviconChanged( |
| 123 WebIntentPickerModel* model, size_t index) OVERRIDE { | 134 WebIntentPickerModel* model, size_t index) OVERRIDE { |
| 124 num_icons_changed_++; | 135 num_icons_changed_++; |
| 125 } | 136 } |
| 126 virtual void OnExtensionIconChanged( | 137 virtual void OnExtensionIconChanged( |
| 127 WebIntentPickerModel* model, const string16& extension_id) OVERRIDE { | 138 WebIntentPickerModel* model, const string16& extension_id) OVERRIDE { |
| 128 num_extension_icons_changed_++; | 139 num_extension_icons_changed_++; |
| 129 } | 140 } |
| 130 virtual void OnInlineDisposition( | 141 virtual void OnInlineDisposition( |
| 131 WebIntentPickerModel* model, const GURL& url) OVERRIDE {} | 142 WebIntentPickerModel* model, const GURL& url) OVERRIDE { |
| 143 num_inline_disposition_++; | |
| 144 } | |
| 132 | 145 |
| 133 void Wait() { | 146 void Wait() { |
| 134 if (!pending_async_completed_) { | 147 if (!pending_async_completed_) { |
| 135 message_loop_started_ = true; | 148 message_loop_started_ = true; |
| 136 ui_test_utils::RunMessageLoop(); | 149 ui_test_utils::RunMessageLoop(); |
| 137 pending_async_completed_ = false; | 150 pending_async_completed_ = false; |
| 138 } | 151 } |
| 139 } | 152 } |
| 140 | 153 |
| 141 void StopWaiting() { | 154 void StopWaiting() { |
| 142 pending_async_completed_ = true; | 155 pending_async_completed_ = true; |
| 143 if (message_loop_started_) | 156 if (message_loop_started_) |
| 144 MessageLoop::current()->Quit(); | 157 MessageLoop::current()->Quit(); |
| 145 } | 158 } |
| 146 | 159 |
| 147 int num_installed_services_; | 160 int num_installed_services_; |
| 148 int num_icons_changed_; | 161 int num_icons_changed_; |
| 149 int num_extension_icons_changed_; | 162 int num_extension_icons_changed_; |
| 150 int num_extensions_installed_; | 163 int num_extensions_installed_; |
| 151 bool message_loop_started_; | 164 bool message_loop_started_; |
| 152 bool pending_async_completed_; | 165 bool pending_async_completed_; |
| 166 int num_inline_disposition_; | |
| 167 WebIntentPickerDelegate* delegate_; | |
| 153 }; | 168 }; |
| 154 | 169 |
| 155 class IntentsDispatcherMock : public content::WebIntentsDispatcher { | 170 class IntentsDispatcherMock : public content::WebIntentsDispatcher { |
| 156 public: | 171 public: |
| 157 explicit IntentsDispatcherMock(const webkit_glue::WebIntentData& intent) | 172 explicit IntentsDispatcherMock(const webkit_glue::WebIntentData& intent) |
| 158 : intent_(intent), | 173 : intent_(intent), |
| 159 dispatched_(false) {} | 174 dispatched_(false), |
| 175 replied_(false) {} | |
| 160 | 176 |
| 161 virtual const webkit_glue::WebIntentData& GetIntent() OVERRIDE { | 177 virtual const webkit_glue::WebIntentData& GetIntent() OVERRIDE { |
| 162 return intent_; | 178 return intent_; |
| 163 } | 179 } |
| 164 | 180 |
| 165 virtual void DispatchIntent(content::WebContents* web_contents) OVERRIDE { | 181 virtual void DispatchIntent(content::WebContents* web_contents) OVERRIDE { |
| 166 dispatched_ = true; | 182 dispatched_ = true; |
| 167 } | 183 } |
| 168 | 184 |
| 169 virtual void SendReplyMessage(webkit_glue::WebIntentReplyType reply_type, | 185 virtual void SendReplyMessage(webkit_glue::WebIntentReplyType reply_type, |
| 170 const string16& data) OVERRIDE { | 186 const string16& data) OVERRIDE { |
| 187 replied_ = true; | |
| 188 LOG(INFO) << "Intent Reply: " << UTF16ToASCII(data); | |
| 171 } | 189 } |
| 172 | 190 |
| 173 virtual void RegisterReplyNotification( | 191 virtual void RegisterReplyNotification( |
| 174 const base::Callback<void(webkit_glue::WebIntentReplyType)>&) OVERRIDE { | 192 const base::Callback<void(webkit_glue::WebIntentReplyType)>&) OVERRIDE { |
| 175 } | 193 } |
| 176 | 194 |
| 177 webkit_glue::WebIntentData intent_; | 195 webkit_glue::WebIntentData intent_; |
| 178 bool dispatched_; | 196 bool dispatched_; |
| 197 bool replied_; | |
| 179 }; | 198 }; |
| 180 | 199 |
| 181 class WebIntentPickerControllerBrowserTest : public InProcessBrowserTest { | 200 class WebIntentPickerControllerBrowserTest : public InProcessBrowserTest { |
| 182 protected: | 201 protected: |
| 183 typedef WebIntentPickerModel::Disposition Disposition; | 202 typedef WebIntentPickerModel::Disposition Disposition; |
| 184 | 203 |
| 185 WebIntentPickerControllerBrowserTest() {} | 204 WebIntentPickerControllerBrowserTest() {} |
| 186 | 205 |
| 187 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 206 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 188 // We start the test server now instead of in | 207 // We start the test server now instead of in |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 213 fake_url_fetcher_factory_.reset( | 232 fake_url_fetcher_factory_.reset( |
| 214 new FakeURLFetcherFactory(default_url_fetcher_factory_.get())); | 233 new FakeURLFetcherFactory(default_url_fetcher_factory_.get())); |
| 215 | 234 |
| 216 web_data_service_ = | 235 web_data_service_ = |
| 217 GetBrowser()->profile()->GetWebDataService(Profile::EXPLICIT_ACCESS); | 236 GetBrowser()->profile()->GetWebDataService(Profile::EXPLICIT_ACCESS); |
| 218 favicon_service_ = | 237 favicon_service_ = |
| 219 GetBrowser()->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); | 238 GetBrowser()->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); |
| 220 controller_ = GetBrowser()-> | 239 controller_ = GetBrowser()-> |
| 221 GetSelectedTabContentsWrapper()->web_intent_picker_controller(); | 240 GetSelectedTabContentsWrapper()->web_intent_picker_controller(); |
| 222 | 241 |
| 223 controller_->set_picker(&picker_); | 242 SetupMockPicker(); |
| 224 controller_->set_model_observer(&picker_); | 243 controller_->set_model_observer(&picker_); |
| 244 picker_.delegate_ = controller_; | |
| 225 | 245 |
| 226 CreateFakeIcon(); | 246 CreateFakeIcon(); |
| 227 } | 247 } |
| 228 | 248 |
| 249 virtual void SetupMockPicker() { | |
| 250 controller_->set_picker(&picker_); | |
| 251 } | |
| 252 | |
| 229 virtual Browser* GetBrowser() { return browser(); } | 253 virtual Browser* GetBrowser() { return browser(); } |
| 230 | 254 |
| 231 void AddWebIntentService(const string16& action, const GURL& service_url) { | 255 void AddWebIntentService(const string16& action, const GURL& service_url) { |
| 232 webkit_glue::WebIntentServiceData service; | 256 webkit_glue::WebIntentServiceData service; |
| 233 service.action = action; | 257 service.action = action; |
| 234 service.type = kType1; | 258 service.type = kType1; |
| 235 service.service_url = service_url; | 259 service.service_url = service_url; |
| 236 web_data_service_->AddWebIntentService(service); | 260 web_data_service_->AddWebIntentService(service); |
| 237 } | 261 } |
| 238 | 262 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 picker_.Wait(); | 455 picker_.Wait(); |
| 432 EXPECT_EQ(1, picker_.num_extensions_installed_); | 456 EXPECT_EQ(1, picker_.num_extensions_installed_); |
| 433 const Extension* extension = browser()->profile()->GetExtensionService()-> | 457 const Extension* extension = browser()->profile()->GetExtensionService()-> |
| 434 GetExtensionById(extension_id, false); | 458 GetExtensionById(extension_id, false); |
| 435 EXPECT_TRUE(extension); | 459 EXPECT_TRUE(extension); |
| 436 | 460 |
| 437 // Installing an extension should also choose it. Since this extension uses | 461 // Installing an extension should also choose it. Since this extension uses |
| 438 // window disposition, it will create a new tab. | 462 // window disposition, it will create a new tab. |
| 439 ASSERT_EQ(2, browser()->tab_count()); | 463 ASSERT_EQ(2, browser()->tab_count()); |
| 440 } | 464 } |
| 465 | |
| 466 // Test that an explicit intent does not trigger loading intents from the | |
| 467 // registry (skips the picker), and creates the intent service handler | |
| 468 // immediately. | |
| 469 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
| 470 ExplicitIntentTest) { | |
| 471 // Install a target service for the explicit intent. | |
| 472 const char extension_id[] = "ooodacpbmglpoagccnepcbfhfhpdgddn"; | |
| 473 AddCWSExtensionServiceWithResult(extension_id, kAction1, kType2); | |
| 474 controller_->ShowDialog(browser(), kAction1, kType2); | |
| 475 picker_.Wait(); | |
| 476 | |
| 477 webkit_glue::WebIntentData intent; | |
| 478 intent.action = kAction1; | |
| 479 intent.type = kType2; | |
| 480 IntentsDispatcherMock dispatcher(intent); | |
| 481 controller_->SetIntentsDispatcher(&dispatcher); | |
|
groby-ooo-7-16
2012/04/24 21:36:51
Why do we set up a dispatcher when we install a ta
Greg Billock
2012/04/25 16:04:32
Needed for smooth operation of the controller. I l
| |
| 482 | |
| 483 OnExtensionInstallRequested(extension_id); | |
| 484 picker_.Wait(); | |
| 485 ASSERT_EQ(1, picker_.num_extensions_installed_); | |
| 486 // The intent launches a new tab. | |
| 487 ASSERT_EQ(2, browser()->tab_count()); | |
| 488 | |
| 489 // Make the controller think nothing is being shown. | |
| 490 picker_.MockClose(); | |
| 491 SetupMockPicker(); | |
| 492 | |
| 493 // Now call the explicit intent. | |
| 494 webkit_glue::WebIntentData explicitIntent; | |
| 495 explicitIntent.action = kAction1; | |
| 496 explicitIntent.type = kType2; | |
| 497 explicitIntent.service = GURL(StringPrintf("%s://%s/%s", | |
| 498 chrome::kExtensionScheme, | |
| 499 extension_id, | |
| 500 "share.html")); | |
| 501 LOG(INFO) << "Calling " << explicitIntent.service.spec(); | |
| 502 IntentsDispatcherMock dispatcher2(explicitIntent); | |
| 503 controller_->SetIntentsDispatcher(&dispatcher2); | |
| 504 controller_->ShowDialog(browser(), kAction1, kType2); | |
| 505 | |
| 506 EXPECT_EQ(2, browser()->tab_count()); | |
| 507 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
| 508 EXPECT_FALSE(dispatcher2.replied_); | |
| 509 | |
| 510 // num_installed_services_ would be 2 if the intent wasn't explicit. | |
| 511 EXPECT_EQ(0, picker_.num_installed_services_); | |
| 512 } | |
| 513 | |
| 514 // Test that an explicit intent for non-installed extension won't | |
| 515 // complete. | |
| 516 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
| 517 ExplicitIntentNoExtensionTest) { | |
| 518 AddWebIntentService(kAction1, kServiceURL1); | |
| 519 AddWebIntentService(kAction1, kServiceURL2); | |
| 520 AddCWSExtensionServiceWithResult(kDummyExtensionId, kAction1, kType1); | |
| 521 | |
| 522 webkit_glue::WebIntentData intent; | |
| 523 intent.action = kAction1; | |
| 524 intent.type = kType1; | |
| 525 intent.service = GURL(StringPrintf("%s://%s/%s", | |
| 526 chrome::kExtensionScheme, | |
| 527 kDummyExtensionId, | |
| 528 UTF16ToASCII(kAction1).c_str())); | |
| 529 LOG(INFO) << "Calling " << intent.service.spec(); | |
| 530 IntentsDispatcherMock dispatcher(intent); | |
| 531 controller_->SetIntentsDispatcher(&dispatcher); | |
| 532 controller_->ShowDialog(browser(), kAction1, kType1); | |
| 533 picker_.Wait(); | |
| 534 | |
| 535 EXPECT_EQ(1, browser()->tab_count()); | |
| 536 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
| 537 EXPECT_TRUE(dispatcher.replied_); | |
| 538 | |
| 539 // num_installed_services_ would be 2 if the intent wasn't explicit. | |
| 540 EXPECT_EQ(0, picker_.num_installed_services_); | |
| 541 } | |
| 542 | |
| 543 // Test that explicit intents won't load non-extensions. | |
| 544 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
| 545 ExplicitIntentNonExtensionTest) { | |
| 546 AddWebIntentService(kAction1, kServiceURL1); | |
| 547 AddWebIntentService(kAction1, kServiceURL2); | |
| 548 AddCWSExtensionServiceWithResult(kDummyExtensionId, kAction1, kType1); | |
| 549 | |
| 550 webkit_glue::WebIntentData intent; | |
| 551 intent.action = kAction1; | |
| 552 intent.type = kType1; | |
| 553 intent.service = GURL("http://www.google.com/"); | |
| 554 IntentsDispatcherMock dispatcher(intent); | |
| 555 controller_->SetIntentsDispatcher(&dispatcher); | |
| 556 controller_->ShowDialog(browser(), kAction1, kType1); | |
| 557 | |
| 558 EXPECT_EQ(1, browser()->tab_count()); | |
| 559 EXPECT_EQ(0, picker_.num_inline_disposition_); | |
| 560 | |
| 561 // num_installed_services_ would be 2 if the intent wasn't explicit. | |
| 562 EXPECT_EQ(0, picker_.num_installed_services_); | |
| 563 EXPECT_TRUE(dispatcher.replied_); | |
| 564 } | |
| OLD | NEW |