From 47a8c50b2ff6cd18bd637c377298a5989c4d4903 Mon Sep 17 00:00:00 2001 From: "jhawkins@chromium.org" Date: Thu, 11 Aug 2011 20:49:48 +0000 Subject: Web Intents: Hook up the register intent InfoBar with the WebIntentsRegistry. BUG=none TEST=RegisterIntentHandlerInfoBarDelegateTest.Accept R=groby@chromium.org Review URL: http://codereview.chromium.org/7601013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96449 0039d316-1c4b-4281-b951-d872f2087c98 --- .../register_intent_handler_infobar_delegate.cc | 25 +++++-- .../register_intent_handler_infobar_delegate.h | 13 +++- ...ter_intent_handler_infobar_delegate_unittest.cc | 84 ++++++++++++++++++++++ chrome/browser/intents/web_intent_data.cc | 15 ++++ chrome/browser/intents/web_intent_data.h | 6 ++ chrome/browser/intents/web_intents_registry.h | 21 ++++-- .../intents/web_intents_registry_factory.cc | 39 ++++++++++ .../browser/intents/web_intents_registry_factory.h | 40 +++++++++++ .../intents/web_intents_registry_unittest.cc | 2 + .../profiles/profile_keyed_service_factory.cc | 2 +- chrome/browser/themes/theme_service_factory.h | 7 +- .../ui/tab_contents/tab_contents_wrapper.cc | 16 ++++- chrome/browser/webdata/autofill_table.cc | 37 +++++----- chrome/browser/webdata/autofill_table.h | 22 +++--- chrome/browser/webdata/token_service_table.h | 4 +- chrome/browser/webdata/web_data_service.cc | 8 +-- chrome/browser/webdata/web_database_table.cc | 5 ++ chrome/browser/webdata/web_database_table.h | 12 ++-- chrome/browser/webdata/web_intents_table.cc | 29 ++++---- chrome/browser/webdata/web_intents_table.h | 13 ++-- .../browser/webdata/web_intents_table_unittest.cc | 35 ++++----- chrome/chrome_browser.gypi | 8 ++- chrome/chrome_tests.gypi | 1 + chrome/test/base/testing_profile.h | 1 - 24 files changed, 346 insertions(+), 99 deletions(-) create mode 100644 chrome/browser/intents/register_intent_handler_infobar_delegate_unittest.cc create mode 100644 chrome/browser/intents/web_intent_data.cc create mode 100644 chrome/browser/intents/web_intents_registry_factory.cc create mode 100644 chrome/browser/intents/web_intents_registry_factory.h diff --git a/chrome/browser/intents/register_intent_handler_infobar_delegate.cc b/chrome/browser/intents/register_intent_handler_infobar_delegate.cc index 2097e3e..cac9b91 100644 --- a/chrome/browser/intents/register_intent_handler_infobar_delegate.cc +++ b/chrome/browser/intents/register_intent_handler_infobar_delegate.cc @@ -5,14 +5,20 @@ #include "chrome/browser/intents/register_intent_handler_infobar_delegate.h" #include "base/logging.h" +#include "base/utf_string_conversions.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 "content/browser/tab_contents/tab_contents.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" RegisterIntentHandlerInfoBarDelegate::RegisterIntentHandlerInfoBarDelegate( - TabContents* tab_contents) + TabContents* tab_contents, const WebIntentData& intent) : ConfirmInfoBarDelegate(tab_contents), - tab_contents_(tab_contents) { + tab_contents_(tab_contents), + profile_(Profile::FromBrowserContext(tab_contents->browser_context())), + intent_(intent) { } InfoBarDelegate::Type @@ -21,21 +27,30 @@ InfoBarDelegate::Type } string16 RegisterIntentHandlerInfoBarDelegate::GetMessageText() const { - return l10n_util::GetStringFUTF16(IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM, - string16(), string16()); + return l10n_util::GetStringFUTF16( + IDS_REGISTER_INTENT_HANDLER_CONFIRM, + intent_.title, + UTF8ToUTF16(intent_.service_url.host())); } string16 RegisterIntentHandlerInfoBarDelegate::GetButtonLabel( InfoBarButton button) const { if (button == BUTTON_OK) { return l10n_util::GetStringFUTF16(IDS_REGISTER_INTENT_HANDLER_ACCEPT, - string16()); + UTF8ToUTF16(intent_.service_url.host())); } DCHECK(button == BUTTON_CANCEL); return l10n_util::GetStringUTF16(IDS_REGISTER_INTENT_HANDLER_DENY); } +bool RegisterIntentHandlerInfoBarDelegate::Accept() { + WebIntentsRegistry* registry = + WebIntentsRegistryFactory::GetForProfile(profile_); + registry->RegisterIntentProvider(intent_); + return true; +} + string16 RegisterIntentHandlerInfoBarDelegate::GetLinkText() const { return l10n_util::GetStringUTF16(IDS_LEARN_MORE); } diff --git a/chrome/browser/intents/register_intent_handler_infobar_delegate.h b/chrome/browser/intents/register_intent_handler_infobar_delegate.h index 315691a..0c74071 100644 --- a/chrome/browser/intents/register_intent_handler_infobar_delegate.h +++ b/chrome/browser/intents/register_intent_handler_infobar_delegate.h @@ -8,21 +8,24 @@ #include "base/basictypes.h" #include "base/string16.h" +#include "chrome/browser/intents/web_intent_data.h" #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" +class Profile; class TabContents; // The InfoBar used to request permission for a site to be registered as an // Intent handler. class RegisterIntentHandlerInfoBarDelegate : public ConfirmInfoBarDelegate { public: - // TODO(jhawkins): Pass in WebIntentData. - explicit RegisterIntentHandlerInfoBarDelegate(TabContents* tab_contents); + RegisterIntentHandlerInfoBarDelegate(TabContents* tab_contents, + const WebIntentData& intent); // ConfirmInfoBarDelegate implementation. virtual Type GetInfoBarType() const OVERRIDE; virtual string16 GetMessageText() const OVERRIDE; virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; + virtual bool Accept() OVERRIDE; virtual string16 GetLinkText() const OVERRIDE; virtual bool LinkClicked(WindowOpenDisposition disposition) OVERRIDE; @@ -30,6 +33,12 @@ class RegisterIntentHandlerInfoBarDelegate : public ConfirmInfoBarDelegate { // The TabContents that contains this InfoBar. Weak pointer. TabContents* tab_contents_; + // The profile associated with |tab_contents_|. Weak pointer. + Profile* profile_; + + // The cached intent data bundle passed up from the renderer. + WebIntentData intent_; + DISALLOW_COPY_AND_ASSIGN(RegisterIntentHandlerInfoBarDelegate); }; diff --git a/chrome/browser/intents/register_intent_handler_infobar_delegate_unittest.cc b/chrome/browser/intents/register_intent_handler_infobar_delegate_unittest.cc new file mode 100644 index 0000000..48e0639 --- /dev/null +++ b/chrome/browser/intents/register_intent_handler_infobar_delegate_unittest.cc @@ -0,0 +1,84 @@ +// 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/scoped_ptr.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/intents/register_intent_handler_infobar_delegate.h" +#include "chrome/browser/intents/web_intents_registry.h" +#include "chrome/browser/intents/web_intents_registry_factory.h" +#include "chrome/browser/intents/web_intent_data.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/testing_browser_process_test.h" +#include "content/browser/browser_thread.h" +#include "content/browser/renderer_host/test_render_view_host.h" +#include "content/browser/site_instance.h" +#include "content/browser/tab_contents/test_tab_contents.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class MockWebIntentsRegistry : public WebIntentsRegistry { + public: + MOCK_METHOD1(RegisterIntentProvider, void(const WebIntentData&)); +}; + +ProfileKeyedService* BuildMockWebIntentsRegistry(Profile* profile) { + return new MockWebIntentsRegistry; +} + +MockWebIntentsRegistry* BuildForProfile(Profile* profile) { + return static_cast( + WebIntentsRegistryFactory::GetInstance()->SetTestingFactoryAndUse( + profile, BuildMockWebIntentsRegistry)); +} + +class RegisterIntentHandlerInfoBarDelegateTest + : public RenderViewHostTestHarness { + protected: + RegisterIntentHandlerInfoBarDelegateTest() + : ui_thread_(BrowserThread::UI, MessageLoopForUI::current()) {} + + virtual void SetUp() { + RenderViewHostTestHarness::SetUp(); + + profile_.reset(new TestingProfile); + profile_->CreateWebDataService(false); + + SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get()); + tab_contents_.reset(new TestTabContents(profile_.get(), instance)); + + web_intents_registry_ = BuildForProfile(profile_.get()); + } + + virtual void TearDown() { + tab_contents_.reset(); + web_intents_registry_ = NULL; + profile_.reset(); + + RenderViewHostTestHarness::TearDown(); + } + + scoped_ptr tab_contents_; + MockWebIntentsRegistry* web_intents_registry_; + + private: + BrowserThread ui_thread_; + scoped_ptr profile_; + + DISALLOW_COPY_AND_ASSIGN(RegisterIntentHandlerInfoBarDelegateTest); +}; + +TEST_F(RegisterIntentHandlerInfoBarDelegateTest, Accept) { + WebIntentData intent; + intent.service_url = GURL("google.com"); + intent.action = ASCIIToUTF16("http://webintents.org/share"); + intent.type = ASCIIToUTF16("text/url"); + RegisterIntentHandlerInfoBarDelegate delegate(tab_contents_.get(), intent); + + EXPECT_CALL(*web_intents_registry_, RegisterIntentProvider(intent)); + delegate.Accept(); +} + +} // namespace diff --git a/chrome/browser/intents/web_intent_data.cc b/chrome/browser/intents/web_intent_data.cc new file mode 100644 index 0000000..3f7339f --- /dev/null +++ b/chrome/browser/intents/web_intent_data.cc @@ -0,0 +1,15 @@ +// 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 "chrome/browser/intents/web_intent_data.h" + +WebIntentData::WebIntentData() {} + +WebIntentData::~WebIntentData() {} + +bool WebIntentData::operator==(const WebIntentData& other) const { + return (service_url == other.service_url && + action == other.action && + type == other.type); +} diff --git a/chrome/browser/intents/web_intent_data.h b/chrome/browser/intents/web_intent_data.h index 9d4b006..b920e7c 100644 --- a/chrome/browser/intents/web_intent_data.h +++ b/chrome/browser/intents/web_intent_data.h @@ -11,9 +11,15 @@ // Describes the relevant elements of a WebIntent. struct WebIntentData { + WebIntentData(); + ~WebIntentData(); + + bool operator==(const WebIntentData& other) const; + GURL service_url; // URL for service invocation. string16 action; // Name of action provided by service. string16 type; // MIME type of data accepted by service. + string16 title; // The title of the service. }; #endif // CHROME_BROWSER_INTENTS_WEB_INTENT_DATA_H_ diff --git a/chrome/browser/intents/web_intents_registry.h b/chrome/browser/intents/web_intents_registry.h index 76c01db..02ab4fd 100644 --- a/chrome/browser/intents/web_intents_registry.h +++ b/chrome/browser/intents/web_intents_registry.h @@ -9,11 +9,14 @@ #include "base/hash_tables.h" #include "base/memory/ref_counted.h" #include "chrome/browser/intents/web_intent_data.h" +#include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/browser/webdata/web_data_service.h" // Handles storing and retrieving of web intents in the web database. // The registry provides filtering logic to retrieve specific types of intents. -class WebIntentsRegistry : public WebDataServiceConsumer { +class WebIntentsRegistry + : public WebDataServiceConsumer, + public ProfileKeyedService { public: // Unique identifier for intent queries. typedef int QueryID; @@ -31,14 +34,11 @@ class WebIntentsRegistry : public WebDataServiceConsumer { virtual ~Consumer() {} }; - WebIntentsRegistry(); - virtual ~WebIntentsRegistry(); - // Initializes, binds to a valid WebDataService. void Initialize(scoped_refptr wds); // Registers a web intent provider. - void RegisterIntentProvider(const WebIntentData& intent); + virtual void RegisterIntentProvider(const WebIntentData& intent); // Removes a web intent provider from the registry. void UnregisterIntentProvider(const WebIntentData& intent); @@ -47,11 +47,20 @@ class WebIntentsRegistry : public WebDataServiceConsumer { // |consumer| must not be NULL. QueryID GetIntentProviders(const string16& action, Consumer* consumer); + protected: + // Make sure that only WebIntentsRegistryFactory can create an instance of + // WebIntentsRegistry. + friend class WebIntentsRegistryFactory; + friend class WebIntentsRegistryTest; + + WebIntentsRegistry(); + virtual ~WebIntentsRegistry(); + private: struct IntentsQuery; // Maps web data requests to intents queries. - // Allows OnWebDataServiceRequestDone to forward to appropiate consumer. + // Allows OnWebDataServiceRequestDone to forward to appropriate consumer. typedef base::hash_map QueryMap; // WebDataServiceConsumer implementation. diff --git a/chrome/browser/intents/web_intents_registry_factory.cc b/chrome/browser/intents/web_intents_registry_factory.cc new file mode 100644 index 0000000..7c4af1d --- /dev/null +++ b/chrome/browser/intents/web_intents_registry_factory.cc @@ -0,0 +1,39 @@ +// 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 "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/profiles/profile_dependency_manager.h" + +// static +WebIntentsRegistry* WebIntentsRegistryFactory::GetForProfile(Profile* profile) { + return static_cast( + GetInstance()->GetServiceForProfile(profile, true)); +} + +WebIntentsRegistryFactory::WebIntentsRegistryFactory() + : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { + // TODO(erg): For Shutdown() order, we need to: + // DependsOn(WebDataServiceFactory::GetInstance()); +} + +WebIntentsRegistryFactory::~WebIntentsRegistryFactory() { +} + +// static +WebIntentsRegistryFactory* WebIntentsRegistryFactory::GetInstance() { + return Singleton::get(); +} + +ProfileKeyedService* WebIntentsRegistryFactory::BuildServiceInstanceFor( + Profile* profile) const { + WebIntentsRegistry* registry = new WebIntentsRegistry; + registry->Initialize(profile->GetWebDataService(Profile::EXPLICIT_ACCESS)); + return registry; +} + +bool WebIntentsRegistryFactory::ServiceRedirectedInIncognito() { + return false; +} diff --git a/chrome/browser/intents/web_intents_registry_factory.h b/chrome/browser/intents/web_intents_registry_factory.h new file mode 100644 index 0000000..4827097 --- /dev/null +++ b/chrome/browser/intents/web_intents_registry_factory.h @@ -0,0 +1,40 @@ +// 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. + +#ifndef CHROME_BROWSER_INTENTS_WEB_INTENTS_REGISTRY_FACTORY_H_ +#define CHROME_BROWSER_INTENTS_WEB_INTENTS_REGISTRY_FACTORY_H_ + +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +class Profile; +class WebIntentsRegistry; + +// Singleton that owns all WebIntentsRegistrys and associates them with +// Profiles. Listens for the Profile's destruction notification and cleans up +// the associated WebIntentsRegistry. +class WebIntentsRegistryFactory : public ProfileKeyedServiceFactory { + public: + // Returns the WebIntentsRegistry that provides intent registration for + // |profile|. + static WebIntentsRegistry* GetForProfile(Profile* profile); + + // Returns the singleton instance of the WebIntentsRegistryFactory. + static WebIntentsRegistryFactory* GetInstance(); + + private: + friend struct DefaultSingletonTraits; + + WebIntentsRegistryFactory(); + virtual ~WebIntentsRegistryFactory(); + + // ProfileKeyedServiceFactory implementation. + virtual ProfileKeyedService* BuildServiceInstanceFor(Profile* profile) const; + virtual bool ServiceRedirectedInIncognito(); + + DISALLOW_COPY_AND_ASSIGN(WebIntentsRegistryFactory); +}; + +#endif // CHROME_BROWSER_INTENTS_WEB_INTENTS_REGISTRY_FACTORY_H_ diff --git a/chrome/browser/intents/web_intents_registry_unittest.cc b/chrome/browser/intents/web_intents_registry_unittest.cc index 55ae6aa..d35164a 100644 --- a/chrome/browser/intents/web_intents_registry_unittest.cc +++ b/chrome/browser/intents/web_intents_registry_unittest.cc @@ -22,6 +22,7 @@ class WebIntentsRegistryTest : public TestingBrowserProcessTest { wds_ = new WebDataService(); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); wds_->Init(temp_dir_.path()); + registry_.Initialize(wds_); } @@ -71,6 +72,7 @@ TEST_F(WebIntentsRegistryTest, BasicTests) { intent.service_url = GURL("http://google.com"); intent.action = ASCIIToUTF16("share"); intent.type = ASCIIToUTF16("image/*"); + intent.title = ASCIIToUTF16("Google's Sharing Service"); registry_.RegisterIntentProvider(intent); diff --git a/chrome/browser/profiles/profile_keyed_service_factory.cc b/chrome/browser/profiles/profile_keyed_service_factory.cc index 7ded5bf..1f334038 100644 --- a/chrome/browser/profiles/profile_keyed_service_factory.cc +++ b/chrome/browser/profiles/profile_keyed_service_factory.cc @@ -4,7 +4,7 @@ #include "chrome/browser/profiles/profile_keyed_service_factory.h" -#include +#include #include "base/memory/singleton.h" #include "chrome/browser/profiles/profile.h" diff --git a/chrome/browser/themes/theme_service_factory.h b/chrome/browser/themes/theme_service_factory.h index 924704b..33e903e 100644 --- a/chrome/browser/themes/theme_service_factory.h +++ b/chrome/browser/themes/theme_service_factory.h @@ -5,12 +5,9 @@ #ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_ #define CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_ -#include - +#include "base/basictypes.h" #include "base/memory/singleton.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h" -#include "content/common/notification_observer.h" -#include "content/common/notification_registrar.h" class ThemeService; class Extension; @@ -42,6 +39,8 @@ class ThemeServiceFactory : public ProfileKeyedServiceFactory { // ProfileKeyedServiceFactory: virtual ProfileKeyedService* BuildServiceInstanceFor(Profile* profile) const; virtual bool ServiceRedirectedInIncognito(); + + DISALLOW_COPY_AND_ASSIGN(ThemeServiceFactory); }; #endif // CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_ diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc index b657e6d..0cc656d 100644 --- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc +++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc @@ -4,6 +4,8 @@ #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "base/utf_string_conversions.h" + #include "base/command_line.h" #include "base/lazy_instance.h" #include "base/utf_string_conversions.h" @@ -23,6 +25,7 @@ #include "chrome/browser/google/google_util.h" #include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/intents/register_intent_handler_infobar_delegate.h" +#include "chrome/browser/intents/web_intent_data.h" #include "chrome/browser/omnibox_search_hint.h" #include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/password_manager_delegate_impl.h" @@ -604,7 +607,18 @@ void TabContentsWrapper::OnRegisterIntentHandler(const string16& action, if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebIntents)) return; - AddInfoBar(new RegisterIntentHandlerInfoBarDelegate(tab_contents())); + GURL service_url(href); + if (!service_url.is_valid()) { + const GURL& url = tab_contents()->GetURL(); + service_url = url.Resolve(href); + } + + WebIntentData intent; + intent.service_url = service_url; + intent.action = action; + intent.type = type; + intent.title = title; + AddInfoBar(new RegisterIntentHandlerInfoBarDelegate(tab_contents(), intent)); } void TabContentsWrapper::OnSnapshot(const SkBitmap& bitmap) { diff --git a/chrome/browser/webdata/autofill_table.cc b/chrome/browser/webdata/autofill_table.cc index c387d86..0d0591d 100644 --- a/chrome/browser/webdata/autofill_table.cc +++ b/chrome/browser/webdata/autofill_table.cc @@ -404,7 +404,7 @@ bool AutofillTable::AddFormFieldValues(const std::vector& elements, bool AutofillTable::AddFormFieldValue(const FormField& element, std::vector* changes) { - return AddFormFieldValueTime(element, changes, base::Time::Now()); + return AddFormFieldValueTime(element, changes, Time::Now()); } bool AutofillTable::GetFormValuesForElementName(const string16& name, @@ -457,8 +457,8 @@ bool AutofillTable::GetFormValuesForElementName(const string16& name, } bool AutofillTable::RemoveFormElementsAddedBetween( - base::Time delete_begin, - base::Time delete_end, + const Time& delete_begin, + const Time& delete_end, std::vector* changes) { DCHECK(changes); // Query for the pair_id, name, and value of all form elements that @@ -509,8 +509,8 @@ bool AutofillTable::RemoveFormElementsAddedBetween( } bool AutofillTable::RemoveFormElementForTimeRange(int64 pair_id, - const Time delete_begin, - const Time delete_end, + const Time& delete_begin, + const Time& delete_end, int* how_many) { sql::Statement s(db_->GetUniqueStatement( "DELETE FROM autofill_dates WHERE pair_id = ? AND " @@ -636,7 +636,7 @@ bool AutofillTable::InsertFormElement(const FormField& element, } bool AutofillTable::InsertPairIDAndDate(int64 pair_id, - base::Time date_created) { + const Time& date_created) { sql::Statement s(db_->GetUniqueStatement( "INSERT INTO autofill_dates " "(pair_id, date_created) VALUES (?, ?)")); @@ -659,7 +659,7 @@ bool AutofillTable::InsertPairIDAndDate(int64 pair_id, bool AutofillTable::AddFormFieldValuesTime( const std::vector& elements, std::vector* changes, - base::Time time) { + Time time) { // Only add one new entry for each unique element name. Use |seen_names| to // track this. Add up to |kMaximumUniqueNames| unique entries per form. const size_t kMaximumUniqueNames = 256; @@ -714,9 +714,9 @@ bool AutofillTable::GetAllAutofillEntries(std::vector* entries) { bool first_entry = true; AutofillKey* current_key_ptr = NULL; - std::vector* timestamps_ptr = NULL; + std::vector