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> | |
| 6 | |
| 5 #include "base/bind.h" | 7 #include "base/bind.h" |
| 6 #include "base/callback.h" | 8 #include "base/callback.h" |
| 7 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 9 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/favicon/favicon_service.h" | 12 #include "chrome/browser/favicon/favicon_service.h" |
| 11 #include "chrome/browser/intents/web_intents_registry.h" | 13 #include "chrome/browser/intents/web_intents_registry.h" |
| 12 #include "chrome/browser/intents/web_intents_registry_factory.h" | 14 #include "chrome/browser/intents/web_intents_registry_factory.h" |
| 13 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
| 15 #include "chrome/browser/ui/intents/web_intent_picker.h" | 17 #include "chrome/browser/ui/intents/web_intent_picker.h" |
| 16 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 18 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
| 17 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | 19 #include "chrome/browser/ui/intents/web_intent_picker_model.h" |
| 18 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" | 20 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" |
| 19 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 20 #include "chrome/browser/webdata/web_data_service.h" | 22 #include "chrome/browser/webdata/web_data_service.h" |
| 21 #include "chrome/common/url_constants.h" | 23 #include "chrome/common/url_constants.h" |
| 22 #include "chrome/test/base/in_process_browser_test.h" | 24 #include "chrome/test/base/in_process_browser_test.h" |
| 23 #include "chrome/test/base/ui_test_utils.h" | 25 #include "chrome/test/base/ui_test_utils.h" |
| 24 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
| 25 #include "content/public/browser/web_intents_dispatcher.h" | 27 #include "content/public/browser/web_intents_dispatcher.h" |
| 26 #include "content/test/test_url_fetcher_factory.h" | 28 #include "content/test/test_url_fetcher_factory.h" |
| 29 #include "net/base/escape.h" | |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
| 31 #include "ui/gfx/image/image_unittest_util.h" | |
| 32 #include "ui/gfx/image/image_util.h" | |
| 28 #include "webkit/glue/web_intent_service_data.h" | 33 #include "webkit/glue/web_intent_service_data.h" |
| 29 | 34 |
| 30 namespace { | 35 namespace { |
| 31 | 36 |
| 32 const string16 kAction1(ASCIIToUTF16("http://www.example.com/share")); | 37 const string16 kAction1(ASCIIToUTF16("http://www.example.com/share")); |
| 33 const string16 kAction2(ASCIIToUTF16("http://www.example.com/foobar")); | 38 const string16 kAction2(ASCIIToUTF16("http://www.example.com/foobar")); |
| 34 const string16 kType(ASCIIToUTF16("image/png")); | 39 const string16 kType(ASCIIToUTF16("image/png")); |
| 35 const GURL kServiceURL1("http://www.google.com"); | 40 const GURL kServiceURL1("http://www.google.com"); |
| 36 const GURL kServiceURL2("http://www.chromium.org"); | 41 const GURL kServiceURL2("http://www.chromium.org"); |
| 37 const char kCWSResponseEmpty[] = | 42 const char kCWSResponseEmpty[] = |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 68 " \\\"intents\\\": {\\n " | 73 " \\\"intents\\\": {\\n " |
| 69 "\\\"%s\\\" : {\\n " | 74 "\\\"%s\\\" : {\\n " |
| 70 "\\\"type\\\" : [\\\"%s\\\"],\\n " | 75 "\\\"type\\\" : [\\\"%s\\\"],\\n " |
| 71 "\\\"path\\\" : \\\"//services/edit\\\",\\n " | 76 "\\\"path\\\" : \\\"//services/edit\\\",\\n " |
| 72 "\\\"title\\\" : \\\"Sample Editing Intent\\\",\\n " | 77 "\\\"title\\\" : \\\"Sample Editing Intent\\\",\\n " |
| 73 "\\\"disposition\\\" : \\\"inline\\\"\\n " | 78 "\\\"disposition\\\" : \\\"inline\\\"\\n " |
| 74 "}\\n " | 79 "}\\n " |
| 75 "}\\n" | 80 "}\\n" |
| 76 "}\\n\"," | 81 "}\\n\"," |
| 77 "\"family_safe\":true," | 82 "\"family_safe\":true," |
| 78 "\"icon_url\":" "\"http://qa-lighthouse.sandbox.google.com/image/" | 83 "\"icon_url\": \"%s\"}]}"; |
| 79 "QzPnRCYCBbBGI99ZkGxkp-NNJ488IkkiTyCgynFEeDTJHcw4tHl3csmjTQ\"}]}"; | 84 |
| 85 const char kCWSFakeIconURLFormat[] = "http://example.com/%s/icon.png"; | |
| 86 | |
| 87 class DummyURLFetcherFactory : public content::URLFetcherFactory { | |
|
Greg Billock
2012/02/23 18:38:34
Would this factory be worth putting in the TestURL
binji
2012/02/23 19:06:13
Maybe. The only reason I need it is because I use
| |
| 88 public: | |
| 89 DummyURLFetcherFactory() {} | |
| 90 virtual ~DummyURLFetcherFactory() {} | |
| 91 | |
| 92 virtual content::URLFetcher* CreateURLFetcher( | |
| 93 int id, | |
| 94 const GURL& url, | |
| 95 content::URLFetcher::RequestType request_type, | |
| 96 content::URLFetcherDelegate* d) OVERRIDE { | |
| 97 return new TestURLFetcher(id, url, d); | |
| 98 } | |
| 99 }; | |
| 80 | 100 |
| 81 } // namespace | 101 } // namespace |
| 82 | 102 |
| 83 class WebIntentPickerMock : public WebIntentPicker, | 103 class WebIntentPickerMock : public WebIntentPicker, |
| 84 public WebIntentPickerModelObserver { | 104 public WebIntentPickerModelObserver { |
| 85 public: | 105 public: |
| 86 WebIntentPickerMock() | 106 WebIntentPickerMock() |
| 87 : num_installed_services_(0), | 107 : num_installed_services_(0), |
| 88 num_icons_changed_(0), | 108 num_icons_changed_(0), |
| 109 num_extension_icons_changed_(0), | |
| 89 message_loop_started_(false), | 110 message_loop_started_(false), |
| 90 pending_async_completed_(false) { | 111 pending_async_completed_(false) { |
| 91 } | 112 } |
| 92 | 113 |
| 93 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE { | 114 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE { |
| 94 num_installed_services_ = | 115 num_installed_services_ = |
| 95 static_cast<int>(model->GetInstalledServiceCount()); | 116 static_cast<int>(model->GetInstalledServiceCount()); |
| 96 } | 117 } |
| 97 | 118 |
| 98 virtual void OnFaviconChanged( | 119 virtual void OnFaviconChanged( |
| 99 WebIntentPickerModel* model, size_t index) OVERRIDE { | 120 WebIntentPickerModel* model, size_t index) OVERRIDE { |
| 100 num_icons_changed_++; | 121 num_icons_changed_++; |
| 101 } | 122 } |
| 102 | 123 |
| 124 virtual void OnExtensionIconChanged( | |
| 125 WebIntentPickerModel* model, const string16& extension_id) OVERRIDE { | |
| 126 num_extension_icons_changed_++; | |
| 127 } | |
| 128 | |
| 103 virtual void OnInlineDisposition(WebIntentPickerModel* model) OVERRIDE {} | 129 virtual void OnInlineDisposition(WebIntentPickerModel* model) OVERRIDE {} |
| 104 virtual void Close() OVERRIDE {} | 130 virtual void Close() OVERRIDE {} |
| 105 | 131 |
| 106 virtual void OnPendingAsyncCompleted() OVERRIDE { | 132 virtual void OnPendingAsyncCompleted() OVERRIDE { |
| 107 pending_async_completed_ = true; | 133 pending_async_completed_ = true; |
| 108 | 134 |
| 109 if (message_loop_started_) | 135 if (message_loop_started_) |
| 110 MessageLoop::current()->Quit(); | 136 MessageLoop::current()->Quit(); |
| 111 } | 137 } |
| 112 | 138 |
| 113 void WaitForPendingAsync() { | 139 void WaitForPendingAsync() { |
| 114 if (!pending_async_completed_) { | 140 if (!pending_async_completed_) { |
| 115 message_loop_started_ = true; | 141 message_loop_started_ = true; |
| 116 ui_test_utils::RunMessageLoop(); | 142 ui_test_utils::RunMessageLoop(); |
| 117 } | 143 } |
| 118 } | 144 } |
| 119 | 145 |
| 120 int num_installed_services_; | 146 int num_installed_services_; |
| 121 int num_icons_changed_; | 147 int num_icons_changed_; |
| 148 int num_extension_icons_changed_; | |
| 122 bool message_loop_started_; | 149 bool message_loop_started_; |
| 123 bool pending_async_completed_; | 150 bool pending_async_completed_; |
| 124 }; | 151 }; |
| 125 | 152 |
| 126 class IntentsDispatcherMock : public content::WebIntentsDispatcher { | 153 class IntentsDispatcherMock : public content::WebIntentsDispatcher { |
| 127 public: | 154 public: |
| 128 explicit IntentsDispatcherMock(const webkit_glue::WebIntentData& intent) | 155 explicit IntentsDispatcherMock(const webkit_glue::WebIntentData& intent) |
| 129 : intent_(intent), | 156 : intent_(intent), |
| 130 dispatched_(false) {} | 157 dispatched_(false) {} |
| 131 | 158 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 149 bool dispatched_; | 176 bool dispatched_; |
| 150 }; | 177 }; |
| 151 | 178 |
| 152 class WebIntentPickerControllerBrowserTest : public InProcessBrowserTest { | 179 class WebIntentPickerControllerBrowserTest : public InProcessBrowserTest { |
| 153 protected: | 180 protected: |
| 154 typedef WebIntentPickerModel::Disposition Disposition; | 181 typedef WebIntentPickerModel::Disposition Disposition; |
| 155 | 182 |
| 156 WebIntentPickerControllerBrowserTest() {} | 183 WebIntentPickerControllerBrowserTest() {} |
| 157 | 184 |
| 158 virtual void SetUpOnMainThread() OVERRIDE { | 185 virtual void SetUpOnMainThread() OVERRIDE { |
| 186 // The FakeURLFetcherFactory will return a NULL URLFetcher if a request is | |
|
Greg Billock
2012/02/23 18:38:34
I don't understand this. Aren't the only urls you
binji
2012/02/23 19:06:13
I thought so too, but it turns out some other syst
Greg Billock
2012/02/23 22:15:49
So where are the requests getting delayed? Does th
| |
| 187 // created for a URL it doesn't know and there is no default factory. | |
| 188 // Instead, use this dummy factory to infinitely delay the request. | |
| 189 default_url_fetcher_factory_.reset(new DummyURLFetcherFactory); | |
| 190 fake_url_fetcher_factory_.reset( | |
| 191 new FakeURLFetcherFactory(default_url_fetcher_factory_.get())); | |
| 192 | |
| 159 web_data_service_ = | 193 web_data_service_ = |
| 160 browser()->profile()->GetWebDataService(Profile::EXPLICIT_ACCESS); | 194 browser()->profile()->GetWebDataService(Profile::EXPLICIT_ACCESS); |
| 161 favicon_service_ = | 195 favicon_service_ = |
| 162 browser()->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); | 196 browser()->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); |
| 163 controller_ = browser()-> | 197 controller_ = browser()-> |
| 164 GetSelectedTabContentsWrapper()->web_intent_picker_controller(); | 198 GetSelectedTabContentsWrapper()->web_intent_picker_controller(); |
| 165 | 199 |
| 166 controller_->set_picker(&picker_); | 200 controller_->set_picker(&picker_); |
| 167 controller_->set_model_observer(&picker_); | 201 controller_->set_model_observer(&picker_); |
| 202 | |
| 203 CreateFakeIcon(); | |
| 168 } | 204 } |
| 169 | 205 |
| 170 void AddWebIntentService(const string16& action, const GURL& service_url) { | 206 void AddWebIntentService(const string16& action, const GURL& service_url) { |
| 171 webkit_glue::WebIntentServiceData service; | 207 webkit_glue::WebIntentServiceData service; |
| 172 service.action = action; | 208 service.action = action; |
| 173 service.type = kType; | 209 service.type = kType; |
| 174 service.service_url = service_url; | 210 service.service_url = service_url; |
| 175 web_data_service_->AddWebIntentService(service); | 211 web_data_service_->AddWebIntentService(service); |
| 176 } | 212 } |
| 177 | 213 |
| 178 void AddCWSExtensionServiceEmpty(const string16& action) { | 214 void AddCWSExtensionServiceEmpty(const string16& action) { |
| 179 GURL cws_query_url = CWSIntentsRegistry::BuildQueryURL(action, kType); | 215 GURL cws_query_url = CWSIntentsRegistry::BuildQueryURL(action, kType); |
| 180 fake_url_fetcher_factory_.SetFakeResponse(cws_query_url.spec(), | 216 fake_url_fetcher_factory_->SetFakeResponse(cws_query_url.spec(), |
| 181 kCWSResponseEmpty, true); | 217 kCWSResponseEmpty, true); |
| 182 } | 218 } |
| 183 | 219 |
| 184 void AddCWSExtensionServiceWithResult(const string16& action) { | 220 void AddCWSExtensionServiceWithResult(const string16& action) { |
| 185 GURL cws_query_url = CWSIntentsRegistry::BuildQueryURL(action, kType); | 221 GURL cws_query_url = CWSIntentsRegistry::BuildQueryURL(action, kType); |
| 222 std::string icon_url; | |
| 223 std::string escaped_action = net::EscapePath(UTF16ToUTF8(action)); | |
| 224 base::SStringPrintf(&icon_url, kCWSFakeIconURLFormat, | |
| 225 escaped_action.c_str()); | |
| 226 | |
| 186 std::string response; | 227 std::string response; |
| 187 base::SStringPrintf(&response, kCWSResponseResultFormat, | 228 base::SStringPrintf(&response, kCWSResponseResultFormat, |
| 188 UTF16ToUTF8(action).c_str(), UTF16ToUTF8(kType).c_str()); | 229 UTF16ToUTF8(action).c_str(), UTF16ToUTF8(kType).c_str(), |
| 189 fake_url_fetcher_factory_.SetFakeResponse(cws_query_url.spec(), response, | 230 icon_url.c_str()); |
| 231 fake_url_fetcher_factory_->SetFakeResponse(cws_query_url.spec(), response, | |
| 232 true); | |
| 233 | |
| 234 fake_url_fetcher_factory_->SetFakeResponse(icon_url, icon_response_, | |
| 190 true); | 235 true); |
| 191 } | 236 } |
| 192 | 237 |
| 193 void OnSendReturnMessage( | 238 void OnSendReturnMessage( |
| 194 webkit_glue::WebIntentReplyType reply_type) { | 239 webkit_glue::WebIntentReplyType reply_type) { |
| 195 controller_->OnSendReturnMessage(reply_type); | 240 controller_->OnSendReturnMessage(reply_type); |
| 196 } | 241 } |
| 197 | 242 |
| 198 void OnServiceChosen(size_t index, Disposition disposition) { | 243 void OnServiceChosen(size_t index, Disposition disposition) { |
| 199 controller_->OnServiceChosen(index, disposition); | 244 controller_->OnServiceChosen(index, disposition); |
| 200 } | 245 } |
| 201 | 246 |
| 202 void OnCancelled() { | 247 void OnCancelled() { |
| 203 controller_->OnCancelled(); | 248 controller_->OnCancelled(); |
| 204 } | 249 } |
| 205 | 250 |
| 251 void CreateFakeIcon() { | |
| 252 gfx::Image image(gfx::test::CreateImage()); | |
| 253 std::vector<unsigned char> image_data; | |
| 254 bool result = gfx::PNGEncodedDataFromImage(image, &image_data); | |
| 255 DCHECK(result); | |
| 256 | |
| 257 std::copy(image_data.begin(), image_data.end(), | |
| 258 std::back_inserter(icon_response_)); | |
| 259 } | |
| 260 | |
| 206 WebIntentPickerMock picker_; | 261 WebIntentPickerMock picker_; |
| 207 WebDataService* web_data_service_; | 262 WebDataService* web_data_service_; |
| 208 FaviconService* favicon_service_; | 263 FaviconService* favicon_service_; |
| 209 WebIntentPickerController* controller_; | 264 WebIntentPickerController* controller_; |
| 210 FakeURLFetcherFactory fake_url_fetcher_factory_; | 265 scoped_ptr<DummyURLFetcherFactory> default_url_fetcher_factory_; |
| 266 scoped_ptr<FakeURLFetcherFactory> fake_url_fetcher_factory_; | |
| 267 std::string icon_response_; | |
| 211 }; | 268 }; |
| 212 | 269 |
| 213 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, ChooseService) { | 270 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, ChooseService) { |
| 214 AddWebIntentService(kAction1, kServiceURL1); | 271 AddWebIntentService(kAction1, kServiceURL1); |
| 215 AddWebIntentService(kAction1, kServiceURL2); | 272 AddWebIntentService(kAction1, kServiceURL2); |
| 216 AddCWSExtensionServiceEmpty(kAction1); | 273 AddCWSExtensionServiceEmpty(kAction1); |
| 217 | 274 |
| 218 controller_->ShowDialog(browser(), kAction1, kType); | 275 controller_->ShowDialog(browser(), kAction1, kType); |
| 219 picker_.WaitForPendingAsync(); | 276 picker_.WaitForPendingAsync(); |
| 220 EXPECT_EQ(2, picker_.num_installed_services_); | 277 EXPECT_EQ(2, picker_.num_installed_services_); |
| 221 EXPECT_EQ(0, picker_.num_icons_changed_); | 278 EXPECT_EQ(0, picker_.num_icons_changed_); |
| 222 | 279 |
| 223 webkit_glue::WebIntentData intent; | 280 webkit_glue::WebIntentData intent; |
| 224 intent.action = ASCIIToUTF16("a"); | 281 intent.action = ASCIIToUTF16("a"); |
| 225 intent.type = ASCIIToUTF16("b"); | 282 intent.type = ASCIIToUTF16("b"); |
| 226 IntentsDispatcherMock dispatcher(intent); | 283 IntentsDispatcherMock dispatcher(intent); |
| 227 controller_->SetIntentsDispatcher(&dispatcher); | 284 controller_->SetIntentsDispatcher(&dispatcher); |
| 228 | 285 |
| 229 OnServiceChosen(1, WebIntentPickerModel::DISPOSITION_WINDOW); | 286 OnServiceChosen(1, WebIntentPickerModel::DISPOSITION_WINDOW); |
| 230 ASSERT_EQ(2, browser()->tab_count()); | 287 ASSERT_EQ(2, browser()->tab_count()); |
| 231 EXPECT_EQ(GURL(kServiceURL2), | 288 EXPECT_EQ(GURL(kServiceURL2), |
| 232 browser()->GetSelectedWebContents()->GetURL()); | 289 browser()->GetSelectedWebContents()->GetURL()); |
| 233 | 290 |
| 234 EXPECT_TRUE(dispatcher.dispatched_); | 291 EXPECT_TRUE(dispatcher.dispatched_); |
| 235 | 292 |
| 236 OnSendReturnMessage(webkit_glue::WEB_INTENT_REPLY_SUCCESS); | 293 OnSendReturnMessage(webkit_glue::WEB_INTENT_REPLY_SUCCESS); |
| 237 ASSERT_EQ(1, browser()->tab_count()); | 294 ASSERT_EQ(1, browser()->tab_count()); |
| 238 } | 295 } |
| 239 | 296 |
| 297 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, | |
| 298 FetchExtensionIcon) { | |
| 299 AddWebIntentService(kAction1, kServiceURL1); | |
| 300 AddWebIntentService(kAction1, kServiceURL2); | |
| 301 AddCWSExtensionServiceWithResult(kAction1); | |
| 302 | |
| 303 controller_->ShowDialog(browser(), kAction1, kType); | |
| 304 picker_.WaitForPendingAsync(); | |
| 305 EXPECT_EQ(2, picker_.num_installed_services_); | |
| 306 EXPECT_EQ(0, picker_.num_icons_changed_); | |
| 307 EXPECT_EQ(1, picker_.num_extension_icons_changed_); | |
| 308 } | |
| 309 | |
| 240 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, OpenCancelOpen) { | 310 IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, OpenCancelOpen) { |
| 241 AddWebIntentService(kAction1, kServiceURL1); | 311 AddWebIntentService(kAction1, kServiceURL1); |
| 242 AddWebIntentService(kAction1, kServiceURL2); | 312 AddWebIntentService(kAction1, kServiceURL2); |
| 243 AddCWSExtensionServiceEmpty(kAction1); | 313 AddCWSExtensionServiceEmpty(kAction1); |
| 244 | 314 |
| 245 controller_->ShowDialog(browser(), kAction1, kType); | 315 controller_->ShowDialog(browser(), kAction1, kType); |
| 246 picker_.WaitForPendingAsync(); | 316 picker_.WaitForPendingAsync(); |
| 247 OnCancelled(); | 317 OnCancelled(); |
| 248 | 318 |
| 249 controller_->ShowDialog(browser(), kAction1, kType); | 319 controller_->ShowDialog(browser(), kAction1, kType); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 278 ASSERT_EQ(3, browser()->tab_count()); | 348 ASSERT_EQ(3, browser()->tab_count()); |
| 279 EXPECT_EQ(GURL(kServiceURL1), | 349 EXPECT_EQ(GURL(kServiceURL1), |
| 280 browser()->GetSelectedWebContents()->GetURL()); | 350 browser()->GetSelectedWebContents()->GetURL()); |
| 281 | 351 |
| 282 EXPECT_TRUE(dispatcher.dispatched_); | 352 EXPECT_TRUE(dispatcher.dispatched_); |
| 283 | 353 |
| 284 OnSendReturnMessage(webkit_glue::WEB_INTENT_REPLY_SUCCESS); | 354 OnSendReturnMessage(webkit_glue::WEB_INTENT_REPLY_SUCCESS); |
| 285 ASSERT_EQ(2, browser()->tab_count()); | 355 ASSERT_EQ(2, browser()->tab_count()); |
| 286 EXPECT_EQ(original, browser()->GetSelectedWebContents()->GetURL()); | 356 EXPECT_EQ(original, browser()->GetSelectedWebContents()->GetURL()); |
| 287 } | 357 } |
| OLD | NEW |