diff options
author | gbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-28 20:46:07 +0000 |
---|---|---|
committer | gbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-28 20:46:07 +0000 |
commit | 3ac1eef774ee13be784f4c2211f9909da27ad4dd (patch) | |
tree | 9fb9fbe03b789c5c82ffac568a71896d44c721be | |
parent | 19425758a72d1048197e9138740f6301f3eff77d (diff) | |
download | chromium_src-3ac1eef774ee13be784f4c2211f9909da27ad4dd.zip chromium_src-3ac1eef774ee13be784f4c2211f9909da27ad4dd.tar.gz chromium_src-3ac1eef774ee13be784f4c2211f9909da27ad4dd.tar.bz2 |
Pass intent data through to the picker and launch a new tab
on service selection.
R=jhawkins@chromium.org
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/7978014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103171 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/ui/browser.cc | 4 | ||||
-rw-r--r-- | chrome/browser/ui/intents/web_intent_picker_controller.cc | 31 | ||||
-rw-r--r-- | chrome/browser/ui/intents/web_intent_picker_controller.h | 21 | ||||
-rw-r--r-- | chrome/browser/ui/intents/web_intent_picker_controller_browsertest.cc | 135 | ||||
-rw-r--r-- | chrome/browser/ui/intents/web_intent_picker_controller_unittest.cc | 24 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | content/browser/intents/intent_injector.cc | 14 | ||||
-rw-r--r-- | content/browser/intents/intent_injector.h | 6 |
8 files changed, 199 insertions, 37 deletions
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index d5d96fc..00baca8 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -3816,7 +3816,9 @@ void Browser::WebIntentDispatch(TabContents* tab, TabContentsWrapper* tcw = TabContentsWrapper::GetCurrentWrapperForContents(tab); - + tcw->web_intent_picker_controller()->SetIntent(routing_id, + intent, + intent_id); tcw->web_intent_picker_controller()->ShowDialog(window()->GetNativeHandle(), intent.action, intent.type); } diff --git a/chrome/browser/ui/intents/web_intent_picker_controller.cc b/chrome/browser/ui/intents/web_intent_picker_controller.cc index f076dc9..cbc02ce 100644 --- a/chrome/browser/ui/intents/web_intent_picker_controller.cc +++ b/chrome/browser/ui/intents/web_intent_picker_controller.cc @@ -10,10 +10,12 @@ #include "chrome/browser/intents/web_intents_registry.h" #include "chrome/browser/intents/web_intents_registry_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/intents/web_intent_picker.h" #include "chrome/browser/ui/intents/web_intent_picker_factory.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/browser/webdata/web_data_service.h" +#include "content/browser/intents/intent_injector.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/notification_source.h" #include "ui/gfx/codec/png_codec.h" @@ -107,7 +109,9 @@ WebIntentPickerController::WebIntentPickerController( favicon_fetcher_( new FaviconFetcher(this, GetFaviconService(wrapper))), picker_(NULL), - pending_async_count_(0) { + pending_async_count_(0), + routing_id_(0), + intent_id_(0) { NavigationController* controller = &wrapper->controller(); registrar_.Add(this, content::NOTIFICATION_LOAD_START, Source<NavigationController>(controller)); @@ -118,6 +122,15 @@ WebIntentPickerController::WebIntentPickerController( WebIntentPickerController::~WebIntentPickerController() { } +void WebIntentPickerController::SetIntent( + int routing_id, + const webkit_glue::WebIntentData& intent, + int intent_id) { + routing_id_ = routing_id; + intent_ = intent; + intent_id_ = intent_id; +} + void WebIntentPickerController::ShowDialog(gfx::NativeWindow parent, const string16& action, const string16& type) { @@ -145,8 +158,20 @@ void WebIntentPickerController::Observe(int type, void WebIntentPickerController::OnServiceChosen(size_t index) { DCHECK(index < urls_.size()); - // TODO(binji) Send the chosen service back to the renderer. - LOG(INFO) << "Chose index: " << index << " url: " << urls_[index]; + // TODO(gbillock): This really only handles the 'window' disposition in a + // quite prototype way. We need to flesh out what happens to the picker during + // the lifetime of the service url context, and that may mean we need to pass + // more information into the injector to find the picker again and close it. + browser::NavigateParams params(NULL, urls_[index], + PageTransition::AUTO_BOOKMARK); + params.disposition = NEW_FOREGROUND_TAB; + params.profile = wrapper_->profile(); + browser::Navigate(¶ms); + + IntentInjector* injector = new IntentInjector( + params.target_contents->tab_contents()); + injector->SetIntent(routing_id_, intent_, intent_id_); + ClosePicker(); } diff --git a/chrome/browser/ui/intents/web_intent_picker_controller.h b/chrome/browser/ui/intents/web_intent_picker_controller.h index 4c9b989..b356550 100644 --- a/chrome/browser/ui/intents/web_intent_picker_controller.h +++ b/chrome/browser/ui/intents/web_intent_picker_controller.h @@ -15,6 +15,7 @@ #include "content/common/notification_observer.h" #include "content/common/notification_registrar.h" #include "ui/gfx/native_widget_types.h" +#include "webkit/glue/web_intent_data.h" class FaviconService; class GURL; @@ -35,6 +36,15 @@ class WebIntentPickerController : public NotificationObserver, WebIntentPickerFactory* factory); virtual ~WebIntentPickerController(); + // Sets the intent data for which this picker was created. The picker will + // copy and hold this data until the user has made a service selection. + // |routing_id| is the IPC routing ID of the source renderer. + // |intent| is the intent data as created by the client content. + // |intent_id| is the ID assigned by the source renderer. + void SetIntent(int routing_id, + const webkit_glue::WebIntentData& intent, + int intent_id); + // Shows the web intent picker for the window |parent|, given the intent // |action| and MIME-type |type|. void ShowDialog(gfx::NativeWindow parent, @@ -53,6 +63,7 @@ class WebIntentPickerController : public NotificationObserver, private: friend class WebIntentPickerControllerTest; + friend class WebIntentPickerControllerBrowserTest; class WebIntentDataFetcher; class FaviconFetcher; @@ -96,6 +107,16 @@ class WebIntentPickerController : public NotificationObserver, // A count of the outstanding asynchronous calls. int pending_async_count_; + // The routing id of the renderer which launched the intent. Should be the + // renderer associated with the TabContents which owns this object. + int routing_id_; + + // The intent data from the client. + webkit_glue::WebIntentData intent_; + + // The intent ID assigned to this intent by the renderer. + int intent_id_; + DISALLOW_COPY_AND_ASSIGN(WebIntentPickerController); }; diff --git a/chrome/browser/ui/intents/web_intent_picker_controller_browsertest.cc b/chrome/browser/ui/intents/web_intent_picker_controller_browsertest.cc new file mode 100644 index 0000000..3ebbfda --- /dev/null +++ b/chrome/browser/ui/intents/web_intent_picker_controller_browsertest.cc @@ -0,0 +1,135 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/favicon/favicon_service.h" +#include "chrome/browser/intents/web_intents_registry.h" +#include "chrome/browser/intents/web_intents_registry_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/intents/web_intent_picker.h" +#include "chrome/browser/ui/intents/web_intent_picker_controller.h" +#include "chrome/browser/ui/intents/web_intent_picker_factory.h" +#include "chrome/browser/webdata/web_data_service.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/web_intent_service_data.h" + +using testing::_; +using testing::DoAll; +using testing::Return; +using testing::SaveArg; + +namespace { + +const string16 kAction1(ASCIIToUTF16("http://www.example.com/share")); +const string16 kAction2(ASCIIToUTF16("http://www.example.com/foobar")); +const string16 kType(ASCIIToUTF16("image/png")); +const GURL kServiceURL1("http://www.google.com"); +const GURL kServiceURL2("http://www.chromium.org"); + +MATCHER_P(VectorIsOfSize, n, "") { + return arg.size() == static_cast<size_t>(n); +} + +} // namespace + +class WebIntentPickerMock : public WebIntentPicker { + public: + MOCK_METHOD1(SetServiceURLs, void(const std::vector<GURL>& urls)); + MOCK_METHOD2(SetServiceIcon, void(size_t index, const SkBitmap& icon)); + MOCK_METHOD1(SetDefaultServiceIcon, void(size_t index)); + MOCK_METHOD0(Show, void(void)); + MOCK_METHOD0(Close, void(void)); +}; + +class WebIntentPickerFactoryMock : public WebIntentPickerFactory { + public: + MOCK_METHOD3(Create, + WebIntentPicker*(gfx::NativeWindow parent, + TabContentsWrapper* wrapper, + WebIntentPickerDelegate* delegate)); + MOCK_METHOD1(ClosePicker, void(WebIntentPicker* picker)); +}; + +class WebIntentPickerControllerBrowserTest : public InProcessBrowserTest { + protected: + void AddWebIntentService(const string16& action, + const GURL& service_url) { + WebIntentServiceData web_intent_service_data; + web_intent_service_data.action = action; + web_intent_service_data.type = kType; + web_intent_service_data.service_url = service_url; + web_data_service_->AddWebIntent(web_intent_service_data); + } + + void SetPickerExpectations(int expected_service_count, + int expected_default_favicons) { + EXPECT_CALL(*picker_factory_, Create(_, _, _)). + WillOnce(DoAll(SaveArg<2>(&delegate_), Return(&picker_))); + EXPECT_CALL(picker_, + SetServiceURLs(VectorIsOfSize(expected_service_count))). + Times(1); + EXPECT_CALL(picker_, SetDefaultServiceIcon(_)). + Times(expected_default_favicons); + EXPECT_CALL(*picker_factory_, ClosePicker(_)); + } + + void CheckPendingAsync() { + if (controller_->pending_async_count() > 0) { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&WebIntentPickerControllerBrowserTest::CheckPendingAsync, + base::Unretained(this))); + return; + } + + MessageLoop::current()->Quit(); + } + + void WaitForDialogToShow() { + CheckPendingAsync(); + MessageLoop::current()->Run(); + } + + WebIntentPickerMock picker_; + + // |controller_| takes ownership. + WebIntentPickerFactoryMock* picker_factory_; + + scoped_ptr<WebIntentPickerController> controller_; + WebIntentPickerDelegate* delegate_; + WebDataService* web_data_service_; + FaviconService* favicon_service_; +}; + +IN_PROC_BROWSER_TEST_F(WebIntentPickerControllerBrowserTest, ChooseService) { + web_data_service_ = + browser()->profile()->GetWebDataService(Profile::EXPLICIT_ACCESS); + AddWebIntentService(kAction1, kServiceURL1); + AddWebIntentService(kAction1, kServiceURL2); + + favicon_service_ = + browser()->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); + + picker_factory_ = new WebIntentPickerFactoryMock(); + controller_.reset(new WebIntentPickerController( + browser()->GetSelectedTabContentsWrapper(), picker_factory_)); + + SetPickerExpectations(2, 2); + + controller_->ShowDialog(NULL, kAction1, kType); + WaitForDialogToShow(); + + delegate_->OnServiceChosen(1); + ASSERT_EQ(2, browser()->tab_count()); + EXPECT_EQ(GURL(kServiceURL2), + browser()->GetSelectedTabContents()->GetURL()); +} diff --git a/chrome/browser/ui/intents/web_intent_picker_controller_unittest.cc b/chrome/browser/ui/intents/web_intent_picker_controller_unittest.cc index 979783f..1419877 100644 --- a/chrome/browser/ui/intents/web_intent_picker_controller_unittest.cc +++ b/chrome/browser/ui/intents/web_intent_picker_controller_unittest.cc @@ -73,7 +73,7 @@ MATCHER_P(VectorIsOfSize, n, "") { return arg.size() == static_cast<size_t>(n); } -} // namespace +} // namespace class WebIntentPickerMock : public WebIntentPicker { public: @@ -196,7 +196,10 @@ class WebIntentPickerControllerTest : public TabContentsWrapperTestHarness { BrowserThread ui_thread_; BrowserThread db_thread_; WebIntentPickerMock picker_; - WebIntentPickerFactoryMock* picker_factory_; // controller_ takes ownership. + + // |controller_| takes ownership. + WebIntentPickerFactoryMock* picker_factory_; + scoped_ptr<TestWebIntentPickerController> controller_; WebIntentPickerDelegate* delegate_; WebDataService* web_data_service_; @@ -240,23 +243,6 @@ TEST_F(WebIntentPickerControllerTest, DISABLED_ShowFavicon) { WaitForDialogToShow(); } -TEST_F(WebIntentPickerControllerTest, ChooseService) { - SetPickerExpectations(2, 2); - AddWebIntentService(kAction1, kServiceURL1); - AddWebIntentService(kAction1, kServiceURL2); - - EXPECT_CALL(*controller_, OnServiceChosen(0)) - .WillOnce(Invoke(controller_.get(), - &TestWebIntentPickerController::BaseOnServiceChosen)); - EXPECT_CALL(*controller_, OnCancelled()) - .Times(0); - EXPECT_CALL(*picker_factory_, ClosePicker(_)); - - controller_->ShowDialog(NULL, kAction1, kType); - WaitForDialogToShow(); - delegate_->OnServiceChosen(0); -} - TEST_F(WebIntentPickerControllerTest, Cancel) { SetPickerExpectations(2, 2); AddWebIntentService(kAction1, kServiceURL1); diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index a3bd85e..b89b478 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2396,6 +2396,7 @@ 'browser/ui/find_bar/find_bar_host_browsertest.cc', 'browser/ui/global_error_service_browsertest.cc', 'browser/ui/gtk/view_id_util_browsertest.cc', + 'browser/ui/intents/web_intent_picker_controller_browsertest.cc', 'browser/ui/login/login_prompt_browsertest.cc', 'browser/ui/panels/base_panel_browser_test.cc', 'browser/ui/panels/base_panel_browser_test.h', diff --git a/content/browser/intents/intent_injector.cc b/content/browser/intents/intent_injector.cc index 600baad..7c416d0 100644 --- a/content/browser/intents/intent_injector.cc +++ b/content/browser/intents/intent_injector.cc @@ -28,17 +28,11 @@ void IntentInjector::TabContentsDestroyed(TabContents* tab) { } void IntentInjector::SetIntent(int routing_id, - int intent_id, - const string16& action, - const string16& type, - const string16& data) { - webkit_glue::WebIntentData* intent_data = new webkit_glue::WebIntentData; - intent_data->action = action; - intent_data->type = type; - intent_data->data = data; - source_intent_.reset(intent_data); - intent_id_ = intent_id; + const webkit_glue::WebIntentData& intent, + int intent_id) { source_routing_id_ = routing_id; + source_intent_.reset(new webkit_glue::WebIntentData(intent)); + intent_id_ = intent_id; SendIntent(); } diff --git a/content/browser/intents/intent_injector.h b/content/browser/intents/intent_injector.h index 0250060..f658446 100644 --- a/content/browser/intents/intent_injector.h +++ b/content/browser/intents/intent_injector.h @@ -43,10 +43,8 @@ class IntentInjector : public TabContentsObserver { // Sets the intent data to be injected. Call after the user has selected a // service to pass the intent data to that service. void SetIntent(int routing_id, - int intent_id, - const string16& action, - const string16& type, - const string16& data); + const webkit_glue::WebIntentData& intent, + int intent_id); private: // Delivers the intent data to the renderer. |