// Copyright 2013 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 #include "base/run_loop.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/search.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/search_engines/ui_thread_search_terms_data.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/search_test_utils.h" #include "components/prefs/pref_service.h" #include "components/search_engines/default_search_manager.h" #include "components/search_engines/search_engines_test_util.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_prepopulate_data.h" #include "components/search_engines/template_url_service.h" #include "components/version_info/version_info.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/mock_external_provider.h" #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/feature_switch.h" #include "extensions/common/features/feature_channel.h" namespace extensions { namespace { #if defined(OS_WIN) || defined(OS_MACOSX) // Prepopulated id hardcoded in test_extension. const int kTestExtensionPrepopulatedId = 3; // TemplateURLData with search engines settings from test extension manifest. // chrome/test/data/extensions/settings_override/manifest.json std::unique_ptr TestExtensionSearchEngine(PrefService* prefs) { auto result = std::make_unique(); result->SetShortName(base::ASCIIToUTF16("name.de")); result->SetKeyword(base::ASCIIToUTF16("keyword.de")); result->SetURL("http://www.foo.de/s?q={searchTerms}&id=10"); result->favicon_url = GURL("http://www.foo.de/favicon.ico?id=10"); result->suggestions_url = "http://www.foo.de/suggest?q={searchTerms}&id=10"; result->image_url = "http://www.foo.de/image?q={searchTerms}&id=10"; result->search_url_post_params = "search_lang=de"; result->suggestions_url_post_params = "suggest_lang=de"; result->image_url_post_params = "image_lang=de"; result->alternate_urls.push_back("http://www.moo.de/s?q={searchTerms}&id=10"); result->alternate_urls.push_back("http://www.noo.de/s?q={searchTerms}&id=10"); result->input_encodings.push_back("UTF-8"); std::unique_ptr prepopulated = TemplateURLPrepopulateData::GetPrepopulatedEngine( prefs, kTestExtensionPrepopulatedId); // Values below do not exist in extension manifest and are taken from // prepopulated engine with prepopulated_id set in extension manifest. result->contextual_search_url = prepopulated->contextual_search_url; result->new_tab_url = prepopulated->new_tab_url; return result; } testing::AssertionResult VerifyTemplateURLServiceLoad( TemplateURLService* service) { if (service->loaded()) return testing::AssertionSuccess(); search_test_utils::WaitForTemplateURLServiceToLoad(service); if (service->loaded()) return testing::AssertionSuccess(); return testing::AssertionFailure() << "TemplateURLService isn't loaded"; } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OverrideHomePageSettings) { PrefService* prefs = profile()->GetPrefs(); ASSERT_TRUE(prefs); prefs->SetString(prefs::kHomePage, "http://google.com/"); prefs->SetBoolean(prefs::kHomePageIsNewTabPage, true); const extensions::Extension* extension = LoadExtensionWithInstallParam( test_data_dir_.AppendASCII("settings_override"), kFlagEnableFileAccess, "10"); ASSERT_TRUE(extension); EXPECT_EQ("http://www.homepage.de/?param=10", prefs->GetString(prefs::kHomePage)); EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage)); UnloadExtension(extension->id()); EXPECT_EQ("http://google.com/", prefs->GetString(prefs::kHomePage)); EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage)); } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OverrideStartupPagesSettings) { PrefService* prefs = profile()->GetPrefs(); ASSERT_TRUE(prefs); const GURL urls[] = {GURL("http://foo"), GURL("http://bar")}; SessionStartupPref startup_pref(SessionStartupPref::LAST); startup_pref.urls.assign(urls, urls + base::size(urls)); SessionStartupPref::SetStartupPref(prefs, startup_pref); const extensions::Extension* extension = LoadExtensionWithInstallParam( test_data_dir_.AppendASCII("settings_override"), kFlagEnableFileAccess, "10"); ASSERT_TRUE(extension); startup_pref = SessionStartupPref::GetStartupPref(prefs); EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type); EXPECT_EQ(std::vector(1, GURL("http://www.startup.de/?param=10")), startup_pref.urls); UnloadExtension(extension->id()); startup_pref = SessionStartupPref::GetStartupPref(prefs); EXPECT_EQ(SessionStartupPref::LAST, startup_pref.type); EXPECT_EQ(std::vector(urls, urls + base::size(urls)), startup_pref.urls); } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OverrideDSE) { PrefService* prefs = profile()->GetPrefs(); ASSERT_TRUE(prefs); TemplateURLService* url_service = TemplateURLServiceFactory::GetForProfile(profile()); ASSERT_TRUE(url_service); EXPECT_TRUE(VerifyTemplateURLServiceLoad(url_service)); const TemplateURL* default_provider = url_service->GetDefaultSearchProvider(); ASSERT_TRUE(default_provider); EXPECT_EQ(TemplateURL::NORMAL, default_provider->type()); const extensions::Extension* extension = LoadExtensionWithInstallParam( test_data_dir_.AppendASCII("settings_override"), kFlagEnableFileAccess, "10"); ASSERT_TRUE(extension); const TemplateURL* current_dse = url_service->GetDefaultSearchProvider(); EXPECT_EQ(TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, current_dse->type()); std::unique_ptr extension_dse = TestExtensionSearchEngine(prefs); ExpectSimilar(extension_dse.get(), ¤t_dse->data()); UnloadExtension(extension->id()); EXPECT_EQ(default_provider, url_service->GetDefaultSearchProvider()); } // Install and load extension into test profile. IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PRE_OverridenDSEPersists) { PrefService* prefs = profile()->GetPrefs(); ASSERT_TRUE(prefs); TemplateURLService* url_service = TemplateURLServiceFactory::GetForProfile(profile()); ASSERT_TRUE(url_service); EXPECT_TRUE(VerifyTemplateURLServiceLoad(url_service)); const TemplateURL* default_provider = url_service->GetDefaultSearchProvider(); ASSERT_TRUE(default_provider); // Check that default provider is normal before extension is // installed and loaded. EXPECT_EQ(TemplateURL::NORMAL, default_provider->type()); EXPECT_NE(base::ASCIIToUTF16("name.de"), default_provider->short_name()); EXPECT_NE(base::ASCIIToUTF16("keyword.de"), default_provider->keyword()); // Install extension that overrides DSE. const extensions::Extension* extension = LoadExtensionWithInstallParam( test_data_dir_.AppendASCII("settings_override"), kFlagEnableFileAccess, "10"); ASSERT_TRUE(extension); } // PRE_OverridenDSEPersists already installed extension with overriden DSE into // profile. Current test checks that after extension is installed, // default_search_manager correctly determines extension overriden DSE // from profile. IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OverridenDSEPersists) { Profile* profile = browser()->profile(); DefaultSearchManager default_manager( profile->GetPrefs(), DefaultSearchManager::ObserverCallback()); DefaultSearchManager::Source source; const TemplateURLData* current_dse = default_manager.GetDefaultSearchEngine(&source); ASSERT_TRUE(current_dse); std::unique_ptr extension_dse = TestExtensionSearchEngine(profile->GetPrefs()); ExpectSimilar(extension_dse.get(), current_dse); EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source); // Check that new tab url is correctly overriden by extension. TemplateURL ext_turl(*extension_dse, TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION); std::string new_tab_url_ext = ext_turl.new_tab_url_ref().ReplaceSearchTerms( TemplateURLRef::SearchTermsArgs(base::string16()), UIThreadSearchTermsData()); EXPECT_EQ(new_tab_url_ext, search::GetNewTabPageURL(profile).spec()); // Check that after template url service is loaded, extension dse persists. TemplateURLService* url_service = TemplateURLServiceFactory::GetForProfile(profile); ASSERT_TRUE(url_service); EXPECT_TRUE(VerifyTemplateURLServiceLoad(url_service)); EXPECT_TRUE(url_service->IsExtensionControlledDefaultSearch()); const TemplateURL* default_provider = url_service->GetDefaultSearchProvider(); ASSERT_TRUE(default_provider); ExpectSimilar(extension_dse.get(), &default_provider->data()); } // This test checks that an extension overriding the default search engine can // be correctly loaded before the TemplateURLService is loaded. IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, BeforeTemplateUrlServiceLoad) { PrefService* prefs = profile()->GetPrefs(); ASSERT_TRUE(prefs); TemplateURLService* url_service = TemplateURLServiceFactory::GetForProfile(profile()); ASSERT_TRUE(url_service); EXPECT_FALSE(url_service->IsExtensionControlledDefaultSearch()); const extensions::Extension* extension = LoadExtensionWithInstallParam( test_data_dir_.AppendASCII("settings_override"), kFlagEnableFileAccess, "10"); ASSERT_TRUE(extension); const TemplateURL* current_dse = url_service->GetDefaultSearchProvider(); EXPECT_EQ(TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, current_dse->type()); EXPECT_TRUE(url_service->IsExtensionControlledDefaultSearch()); std::unique_ptr extension_dse = TestExtensionSearchEngine(prefs); ExpectSimilar(extension_dse.get(), ¤t_dse->data()); UnloadExtension(extension->id()); EXPECT_NE(TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, url_service->GetDefaultSearchProvider()->type()); EXPECT_FALSE(url_service->IsExtensionControlledDefaultSearch()); } constexpr char kExternalId[] = "eloigjjcaheakkihngcgjhbopomgemdj"; class ExtensionsDisabledWithSettingsOverrideAPI : public ExtensionBrowserTest { public: ExtensionsDisabledWithSettingsOverrideAPI() : prompt_for_external_extensions_( FeatureSwitch::prompt_for_external_extensions(), false) {} ~ExtensionsDisabledWithSettingsOverrideAPI() override = default; void SetUpCommandLine(base::CommandLine* command_line) override { // A little tricky: we disable extensions (via the commandline) on the // non-PRE run. The PRE run is responsible for installing the external // extension. ExtensionBrowserTest::SetUpCommandLine(command_line); const char* test_name = testing::UnitTest::GetInstance()->current_test_info()->name(); if (!base::StartsWith(test_name, "PRE_", base::CompareCase::SENSITIVE)) { command_line->AppendSwitch(::switches::kDisableExtensions); } } private: FeatureSwitch::ScopedOverride prompt_for_external_extensions_; DISALLOW_COPY_AND_ASSIGN(ExtensionsDisabledWithSettingsOverrideAPI); }; // The following test combo is a regression test for https://crbug.com/828295. // When extensions are disabled with --disable-extensions, no // extension-controlled prefs were loaded. However, external extensions (such as // those from policy or specified in the registry) are still loaded with // --disable-extensions (this itself is somewhat strange; see // https://crbug.com/833540). This caused a CHECK failure in the settings // overrides API when an external extension used the API and // --disable-extensions was also used. // As a fix, we ensure that we load extension-controlled preferences for // extensions that will be loaded, even with --disable-extensions. IN_PROC_BROWSER_TEST_F(ExtensionsDisabledWithSettingsOverrideAPI, PRE_TestSettingsOverridesWithExtensionsDisabled) { // This first part of the test adds an external extension that uses the // settings overrides API. ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); TestExtensionRegistryObserver observer(registry); auto provider = std::make_unique( extension_service(), Manifest::EXTERNAL_PREF); provider->UpdateOrAddExtension( kExternalId, "2.1", test_data_dir_.AppendASCII("api_test/settings_overrides/homepage.crx")); extension_service()->AddProviderForTesting(std::move(provider)); extension_service()->CheckForExternalUpdates(); const Extension* extension = observer.WaitForExtensionLoaded(); EXPECT_EQ(kExternalId, extension->id()); } IN_PROC_BROWSER_TEST_F(ExtensionsDisabledWithSettingsOverrideAPI, TestSettingsOverridesWithExtensionsDisabled) { // The external extension was actually uninstalled at this point (see // https://crbug.com/833540). However, it was first loaded, before being // orphaned, which would have caused the settings API to look at the // extension controlled preferences. As long as this didn't crash, the test // succeeded. EXPECT_TRUE(ExtensionsBrowserClient::Get()->AreExtensionsDisabled( *base::CommandLine::ForCurrentProcess(), profile())); } #else IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, SettingsOverridesDisallowed) { const extensions::Extension* extension = LoadExtensionWithFlags(test_data_dir_.AppendASCII("settings_override"), kFlagIgnoreManifestWarnings); ASSERT_TRUE(extension); ASSERT_EQ(1u, extension->install_warnings().size()); EXPECT_EQ(std::string("'chrome_settings_overrides' " "is not allowed for specified platform."), extension->install_warnings().front().message); } #endif } // namespace } // namespace extensions