1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/profile_resetter/profile_resetter.h"
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/test/scoped_path_override.h"
12 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/extension_service_test_base.h"
15 #include "chrome/browser/extensions/tab_helper.h"
16 #include "chrome/browser/prefs/session_startup_pref.h"
17 #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h"
18 #include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
19 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
20 #include "chrome/browser/search_engines/template_url_service_factory.h"
21 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
22 #include "chrome/browser/themes/theme_service.h"
23 #include "chrome/browser/themes/theme_service_factory.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/browser/web_data_service_factory.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/test/base/browser_with_test_window_test.h"
28 #include "components/content_settings/core/browser/host_content_settings_map.h"
29 #include "components/content_settings/core/browser/website_settings_info.h"
30 #include "components/content_settings/core/browser/website_settings_registry.h"
31 #include "components/search_engines/template_url_service.h"
32 #include "components/search_engines/template_url_service_client.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/test/test_browser_thread.h"
35 #include "extensions/browser/extension_registry.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/common/manifest_constants.h"
38 #include "net/http/http_response_headers.h"
39 #include "net/http/http_status_code.h"
40 #include "net/url_request/test_url_fetcher_factory.h"
41 #include "net/url_request/url_request_status.h"
45 #include "base/files/file_util.h"
46 #include "base/path_service.h"
47 #include "base/process/process_handle.h"
48 #include "base/rand_util.h"
49 #include "base/strings/string_number_conversions.h"
50 #include "base/win/scoped_com_initializer.h"
51 #include "base/win/shortcut.h"
57 const char kDistributionConfig
[] = "{"
58 " \"homepage\" : \"http://www.foo.com\","
59 " \"homepage_is_newtabpage\" : false,"
61 " \"show_home_button\" : true"
64 " \"restore_on_startup\" : 4,"
65 " \"startup_urls\" : [\"http://goo.gl\", \"http://foo.de\"]"
67 " \"search_provider_overrides\" : ["
69 " \"name\" : \"first\","
70 " \"keyword\" : \"firstkey\","
71 " \"search_url\" : \"http://www.foo.com/s?q={searchTerms}\","
72 " \"favicon_url\" : \"http://www.foo.com/favicon.ico\","
73 " \"suggest_url\" : \"http://www.foo.com/s?q={searchTerms}\","
74 " \"encoding\" : \"UTF-8\","
80 " \"placeholder_for_id\": {"
86 const char kXmlConfig
[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
87 "<response protocol=\"3.0\" server=\"prod\">"
88 "<app appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\" status=\"ok\">"
89 "<data index=\"skipfirstrunui-importsearch-defaultbrowser\" "
90 "name=\"install\" status=\"ok\">"
91 "placeholder_for_data"
96 using extensions::Extension
;
97 using extensions::Manifest
;
100 // ProfileResetterTest --------------------------------------------------------
102 // ProfileResetterTest sets up the extension, WebData and TemplateURL services.
103 class ProfileResetterTest
: public extensions::ExtensionServiceTestBase
,
104 public ProfileResetterTestBase
{
106 ProfileResetterTest();
107 ~ProfileResetterTest() override
;
110 void SetUp() override
;
112 TestingProfile
* profile() { return profile_
.get(); }
114 static scoped_ptr
<KeyedService
> CreateTemplateURLService(
115 content::BrowserContext
* context
);
119 base::ScopedPathOverride user_desktop_override_
;
120 base::ScopedPathOverride app_dir_override_
;
121 base::ScopedPathOverride start_menu_override_
;
122 base::ScopedPathOverride taskbar_pins_override_
;
123 base::win::ScopedCOMInitializer com_init_
;
127 ProfileResetterTest::ProfileResetterTest()
129 : user_desktop_override_(base::DIR_USER_DESKTOP
),
130 app_dir_override_(base::DIR_APP_DATA
),
131 start_menu_override_(base::DIR_START_MENU
),
132 taskbar_pins_override_(base::DIR_TASKBAR_PINS
)
136 ProfileResetterTest::~ProfileResetterTest() {
139 void ProfileResetterTest::SetUp() {
140 extensions::ExtensionServiceTestBase::SetUp();
141 InitializeEmptyExtensionService();
143 profile()->CreateWebDataService();
144 TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
146 &ProfileResetterTest::CreateTemplateURLService
);
147 resetter_
.reset(new ProfileResetter(profile()));
151 scoped_ptr
<KeyedService
> ProfileResetterTest::CreateTemplateURLService(
152 content::BrowserContext
* context
) {
153 Profile
* profile
= static_cast<Profile
*>(context
);
154 return make_scoped_ptr(new TemplateURLService(
156 scoped_ptr
<SearchTermsData
>(new UIThreadSearchTermsData(profile
)),
157 WebDataServiceFactory::GetKeywordWebDataForProfile(
158 profile
, ServiceAccessType::EXPLICIT_ACCESS
),
159 scoped_ptr
<TemplateURLServiceClient
>(), NULL
, NULL
, base::Closure()));
163 // PinnedTabsResetTest --------------------------------------------------------
165 class PinnedTabsResetTest
: public BrowserWithTestWindowTest
,
166 public ProfileResetterTestBase
{
168 void SetUp() override
;
170 content::WebContents
* CreateWebContents();
173 void PinnedTabsResetTest::SetUp() {
174 BrowserWithTestWindowTest::SetUp();
175 resetter_
.reset(new ProfileResetter(profile()));
178 content::WebContents
* PinnedTabsResetTest::CreateWebContents() {
179 return content::WebContents::Create(
180 content::WebContents::CreateParams(profile()));
184 // ConfigParserTest -----------------------------------------------------------
186 // URLFetcher delegate that simply records the upload data.
187 struct URLFetcherRequestListener
: net::URLFetcherDelegate
{
188 URLFetcherRequestListener();
189 ~URLFetcherRequestListener() override
;
191 void OnURLFetchComplete(const net::URLFetcher
* source
) override
;
193 std::string upload_data
;
194 net::URLFetcherDelegate
* real_delegate
;
197 URLFetcherRequestListener::URLFetcherRequestListener()
198 : real_delegate(NULL
) {
201 URLFetcherRequestListener::~URLFetcherRequestListener() {
204 void URLFetcherRequestListener::OnURLFetchComplete(
205 const net::URLFetcher
* source
) {
206 const net::TestURLFetcher
* test_fetcher
=
207 static_cast<const net::TestURLFetcher
*>(source
);
208 upload_data
= test_fetcher
->upload_data();
209 DCHECK(real_delegate
);
210 real_delegate
->OnURLFetchComplete(source
);
213 class ConfigParserTest
: public testing::Test
{
216 virtual ~ConfigParserTest();
218 scoped_ptr
<BrandcodeConfigFetcher
> WaitForRequest(const GURL
& url
);
220 net::FakeURLFetcherFactory
& factory() { return factory_
; }
223 scoped_ptr
<net::FakeURLFetcher
> CreateFakeURLFetcher(
225 net::URLFetcherDelegate
* fetcher_delegate
,
226 const std::string
& response_data
,
227 net::HttpStatusCode response_code
,
228 net::URLRequestStatus::Status status
);
230 MOCK_METHOD0(Callback
, void(void));
232 base::MessageLoopForIO loop_
;
233 content::TestBrowserThread ui_thread_
;
234 content::TestBrowserThread io_thread_
;
235 URLFetcherRequestListener request_listener_
;
236 net::FakeURLFetcherFactory factory_
;
239 ConfigParserTest::ConfigParserTest()
240 : ui_thread_(content::BrowserThread::UI
, &loop_
),
241 io_thread_(content::BrowserThread::IO
, &loop_
),
242 factory_(NULL
, base::Bind(&ConfigParserTest::CreateFakeURLFetcher
,
243 base::Unretained(this))) {
246 ConfigParserTest::~ConfigParserTest() {}
248 scoped_ptr
<BrandcodeConfigFetcher
> ConfigParserTest::WaitForRequest(
250 EXPECT_CALL(*this, Callback());
251 scoped_ptr
<BrandcodeConfigFetcher
> fetcher(
252 new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback
,
253 base::Unretained(this)),
256 base::MessageLoop::current()->RunUntilIdle();
257 EXPECT_FALSE(fetcher
->IsActive());
258 // Look for the brand code in the request.
259 EXPECT_NE(std::string::npos
, request_listener_
.upload_data
.find("ABCD"));
260 return fetcher
.Pass();
263 scoped_ptr
<net::FakeURLFetcher
> ConfigParserTest::CreateFakeURLFetcher(
265 net::URLFetcherDelegate
* fetcher_delegate
,
266 const std::string
& response_data
,
267 net::HttpStatusCode response_code
,
268 net::URLRequestStatus::Status status
) {
269 request_listener_
.real_delegate
= fetcher_delegate
;
270 scoped_ptr
<net::FakeURLFetcher
> fetcher(
271 new net::FakeURLFetcher(
272 url
, &request_listener_
, response_data
, response_code
, status
));
273 scoped_refptr
<net::HttpResponseHeaders
> download_headers
=
274 new net::HttpResponseHeaders("");
275 download_headers
->AddHeader("Content-Type: text/xml");
276 fetcher
->set_response_headers(download_headers
);
277 return fetcher
.Pass();
280 // A helper class to create/delete/check a Chrome desktop shortcut on Windows.
281 class ShortcutHandler
{
286 static bool IsSupported();
287 ShortcutCommand
CreateWithArguments(const base::string16
& name
,
288 const base::string16
& args
);
289 void CheckShortcutHasArguments(const base::string16
& desired_args
) const;
294 base::FilePath shortcut_path_
;
296 DISALLOW_COPY_AND_ASSIGN(ShortcutHandler
);
300 ShortcutHandler::ShortcutHandler() {
303 ShortcutHandler::~ShortcutHandler() {
304 if (!shortcut_path_
.empty())
309 bool ShortcutHandler::IsSupported() {
313 ShortcutCommand
ShortcutHandler::CreateWithArguments(
314 const base::string16
& name
,
315 const base::string16
& args
) {
316 EXPECT_TRUE(shortcut_path_
.empty());
317 base::FilePath path_to_create
;
318 EXPECT_TRUE(PathService::Get(base::DIR_USER_DESKTOP
, &path_to_create
));
319 path_to_create
= path_to_create
.Append(name
);
320 EXPECT_FALSE(base::PathExists(path_to_create
)) << path_to_create
.value();
322 base::FilePath path_exe
;
323 EXPECT_TRUE(PathService::Get(base::FILE_EXE
, &path_exe
));
324 base::win::ShortcutProperties shortcut_properties
;
325 shortcut_properties
.set_target(path_exe
);
326 shortcut_properties
.set_arguments(args
);
327 EXPECT_TRUE(base::win::CreateOrUpdateShortcutLink(
328 path_to_create
, shortcut_properties
,
329 base::win::SHORTCUT_CREATE_ALWAYS
)) << path_to_create
.value();
330 shortcut_path_
= path_to_create
;
331 return ShortcutCommand(shortcut_path_
, args
);
334 void ShortcutHandler::CheckShortcutHasArguments(
335 const base::string16
& desired_args
) const {
336 EXPECT_FALSE(shortcut_path_
.empty());
338 EXPECT_TRUE(base::win::ResolveShortcut(shortcut_path_
, NULL
, &args
));
339 EXPECT_EQ(desired_args
, args
);
342 void ShortcutHandler::Delete() {
343 EXPECT_FALSE(shortcut_path_
.empty());
344 EXPECT_TRUE(base::DeleteFile(shortcut_path_
, false));
345 shortcut_path_
.clear();
348 ShortcutHandler::ShortcutHandler() {}
350 ShortcutHandler::~ShortcutHandler() {}
353 bool ShortcutHandler::IsSupported() {
357 ShortcutCommand
ShortcutHandler::CreateWithArguments(
358 const base::string16
& name
,
359 const base::string16
& args
) {
360 return ShortcutCommand();
363 void ShortcutHandler::CheckShortcutHasArguments(
364 const base::string16
& desired_args
) const {
367 void ShortcutHandler::Delete() {
369 #endif // defined(OS_WIN)
372 // helper functions -----------------------------------------------------------
374 scoped_refptr
<Extension
> CreateExtension(const base::string16
& name
,
375 const base::FilePath
& path
,
376 Manifest::Location location
,
377 extensions::Manifest::Type type
,
378 bool installed_by_default
) {
379 base::DictionaryValue manifest
;
380 manifest
.SetString(extensions::manifest_keys::kVersion
, "1.0.0.0");
381 manifest
.SetString(extensions::manifest_keys::kName
, name
);
383 case extensions::Manifest::TYPE_THEME
:
384 manifest
.Set(extensions::manifest_keys::kTheme
,
385 new base::DictionaryValue
);
387 case extensions::Manifest::TYPE_HOSTED_APP
:
388 manifest
.SetString(extensions::manifest_keys::kLaunchWebURL
,
389 "http://www.google.com");
390 manifest
.SetString(extensions::manifest_keys::kUpdateURL
,
391 "http://clients2.google.com/service/update2/crx");
393 case extensions::Manifest::TYPE_EXTENSION
:
399 manifest
.SetString(extensions::manifest_keys::kOmniboxKeyword
, name
);
401 scoped_refptr
<Extension
> extension
= Extension::Create(
405 installed_by_default
? Extension::WAS_INSTALLED_BY_DEFAULT
406 : Extension::NO_FLAGS
,
408 EXPECT_TRUE(extension
.get() != NULL
) << error
;
412 void ReplaceString(std::string
* str
,
413 const std::string
& placeholder
,
414 const std::string
& substitution
) {
415 ASSERT_NE(static_cast<std::string
*>(NULL
), str
);
416 size_t placeholder_pos
= str
->find(placeholder
);
417 ASSERT_NE(std::string::npos
, placeholder_pos
);
418 str
->replace(placeholder_pos
, placeholder
.size(), substitution
);
422 /********************* Tests *********************/
424 TEST_F(ProfileResetterTest
, ResetNothing
) {
425 // The callback should be called even if there is nothing to reset.
429 TEST_F(ProfileResetterTest
, ResetDefaultSearchEngineNonOrganic
) {
430 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
, kDistributionConfig
);
432 TemplateURLService
* model
=
433 TemplateURLServiceFactory::GetForProfile(profile());
434 TemplateURL
* default_engine
= model
->GetDefaultSearchProvider();
435 ASSERT_NE(static_cast<TemplateURL
*>(NULL
), default_engine
);
436 EXPECT_EQ(base::ASCIIToUTF16("first"), default_engine
->short_name());
437 EXPECT_EQ(base::ASCIIToUTF16("firstkey"), default_engine
->keyword());
438 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", default_engine
->url());
441 TEST_F(ProfileResetterTest
, ResetDefaultSearchEnginePartially
) {
442 // Search engine's logic is tested by
443 // TemplateURLServiceTest.RepairPrepopulatedSearchEngines.
444 // Make sure TemplateURLService has loaded.
445 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
);
447 TemplateURLService
* model
=
448 TemplateURLServiceFactory::GetForProfile(profile());
449 TemplateURLService::TemplateURLVector urls
= model
->GetTemplateURLs();
451 // The second call should produce no effect.
452 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
);
454 EXPECT_EQ(urls
, model
->GetTemplateURLs());
457 TEST_F(ProfileResetterTest
, ResetHomepageNonOrganic
) {
458 PrefService
* prefs
= profile()->GetPrefs();
460 prefs
->SetBoolean(prefs::kHomePageIsNewTabPage
, true);
461 prefs
->SetString(prefs::kHomePage
, "http://google.com");
462 prefs
->SetBoolean(prefs::kShowHomeButton
, false);
464 ResetAndWait(ProfileResetter::HOMEPAGE
, kDistributionConfig
);
466 EXPECT_FALSE(prefs
->GetBoolean(prefs::kHomePageIsNewTabPage
));
467 EXPECT_EQ("http://www.foo.com", prefs
->GetString(prefs::kHomePage
));
468 EXPECT_TRUE(prefs
->GetBoolean(prefs::kShowHomeButton
));
471 TEST_F(ProfileResetterTest
, ResetHomepagePartially
) {
472 PrefService
* prefs
= profile()->GetPrefs();
474 prefs
->SetBoolean(prefs::kHomePageIsNewTabPage
, false);
475 prefs
->SetString(prefs::kHomePage
, "http://www.foo.com");
476 prefs
->SetBoolean(prefs::kShowHomeButton
, true);
478 ResetAndWait(ProfileResetter::HOMEPAGE
);
480 EXPECT_TRUE(prefs
->GetBoolean(prefs::kHomePageIsNewTabPage
));
481 EXPECT_EQ("http://www.foo.com", prefs
->GetString(prefs::kHomePage
));
482 EXPECT_FALSE(prefs
->GetBoolean(prefs::kShowHomeButton
));
485 TEST_F(ProfileResetterTest
, ResetContentSettings
) {
486 HostContentSettingsMap
* host_content_settings_map
=
487 HostContentSettingsMapFactory::GetForProfile(profile());
488 ContentSettingsPattern pattern
=
489 ContentSettingsPattern::FromString("[*.]example.org");
490 std::map
<ContentSettingsType
, ContentSetting
> default_settings
;
492 // TODO(raymes): Clean up this test so that we don't have such ugly iteration
493 // over the content settings.
494 content_settings::WebsiteSettingsRegistry
* registry
=
495 content_settings::WebsiteSettingsRegistry::GetInstance();
496 for (const content_settings::WebsiteSettingsInfo
* info
: *registry
) {
497 ContentSettingsType content_type
= info
->type();
498 if (content_type
== CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
||
499 content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
||
500 content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
501 // These types are excluded because one can't call
502 // GetDefaultContentSetting() for them.
505 if (content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
) {
506 // This has been deprecated so we can neither set nor get it's value.
509 ContentSetting default_setting
=
510 host_content_settings_map
->GetDefaultContentSetting(content_type
, NULL
);
511 default_settings
[content_type
] = default_setting
;
512 ContentSetting wildcard_setting
= default_setting
== CONTENT_SETTING_BLOCK
513 ? CONTENT_SETTING_ALLOW
514 : CONTENT_SETTING_BLOCK
;
515 ContentSetting site_setting
= default_setting
== CONTENT_SETTING_ALLOW
516 ? CONTENT_SETTING_ALLOW
517 : CONTENT_SETTING_BLOCK
;
518 if (HostContentSettingsMap::IsSettingAllowedForType(
519 profile()->GetPrefs(), wildcard_setting
, content_type
)) {
520 host_content_settings_map
->SetDefaultContentSetting(content_type
,
523 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
) &&
524 HostContentSettingsMap::IsSettingAllowedForType(
525 profile()->GetPrefs(), site_setting
, content_type
)) {
526 host_content_settings_map
->SetContentSetting(
527 pattern
, ContentSettingsPattern::Wildcard(), content_type
,
528 std::string(), site_setting
);
529 ContentSettingsForOneType host_settings
;
530 host_content_settings_map
->GetSettingsForOneType(
531 content_type
, std::string(), &host_settings
);
532 EXPECT_EQ(2U, host_settings
.size());
536 ResetAndWait(ProfileResetter::CONTENT_SETTINGS
);
538 for (const content_settings::WebsiteSettingsInfo
* info
: *registry
) {
539 ContentSettingsType content_type
= info
->type();
540 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
) ||
541 content_type
== CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
||
542 content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
||
543 content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
||
544 content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
)
546 ContentSetting default_setting
=
547 host_content_settings_map
->GetDefaultContentSetting(content_type
,
549 EXPECT_TRUE(default_settings
.count(content_type
));
550 EXPECT_EQ(default_settings
[content_type
], default_setting
);
551 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
)) {
552 ContentSetting site_setting
=
553 host_content_settings_map
->GetContentSetting(
558 EXPECT_EQ(default_setting
, site_setting
);
561 ContentSettingsForOneType host_settings
;
562 host_content_settings_map
->GetSettingsForOneType(
563 content_type
, std::string(), &host_settings
);
564 EXPECT_EQ(1U, host_settings
.size());
568 TEST_F(ProfileResetterTest
, ResetExtensionsByDisabling
) {
571 base::ScopedTempDir temp_dir
;
572 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
574 scoped_refptr
<Extension
> theme
=
575 CreateExtension(base::ASCIIToUTF16("example1"),
577 Manifest::INVALID_LOCATION
,
578 extensions::Manifest::TYPE_THEME
,
580 service_
->FinishInstallationForTest(theme
.get());
581 // Let ThemeService finish creating the theme pack.
582 base::MessageLoop::current()->RunUntilIdle();
584 ThemeService
* theme_service
=
585 ThemeServiceFactory::GetForProfile(profile());
586 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
588 scoped_refptr
<Extension
> ext2
= CreateExtension(
589 base::ASCIIToUTF16("example2"),
590 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
591 Manifest::INVALID_LOCATION
,
592 extensions::Manifest::TYPE_EXTENSION
,
594 service_
->AddExtension(ext2
.get());
595 // Component extensions and policy-managed extensions shouldn't be disabled.
596 scoped_refptr
<Extension
> ext3
= CreateExtension(
597 base::ASCIIToUTF16("example3"),
598 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
600 extensions::Manifest::TYPE_EXTENSION
,
602 service_
->AddExtension(ext3
.get());
603 scoped_refptr
<Extension
> ext4
=
604 CreateExtension(base::ASCIIToUTF16("example4"),
605 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
606 Manifest::EXTERNAL_POLICY_DOWNLOAD
,
607 extensions::Manifest::TYPE_EXTENSION
,
609 service_
->AddExtension(ext4
.get());
610 scoped_refptr
<Extension
> ext5
= CreateExtension(
611 base::ASCIIToUTF16("example5"),
612 base::FilePath(FILE_PATH_LITERAL("//nonexistent4")),
613 Manifest::EXTERNAL_COMPONENT
,
614 extensions::Manifest::TYPE_EXTENSION
,
616 service_
->AddExtension(ext5
.get());
617 scoped_refptr
<Extension
> ext6
= CreateExtension(
618 base::ASCIIToUTF16("example6"),
619 base::FilePath(FILE_PATH_LITERAL("//nonexistent5")),
620 Manifest::EXTERNAL_POLICY
,
621 extensions::Manifest::TYPE_EXTENSION
,
623 service_
->AddExtension(ext6
.get());
624 EXPECT_EQ(6u, registry()->enabled_extensions().size());
626 ResetAndWait(ProfileResetter::EXTENSIONS
);
627 EXPECT_EQ(4u, registry()->enabled_extensions().size());
628 EXPECT_FALSE(registry()->enabled_extensions().Contains(theme
->id()));
629 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2
->id()));
630 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3
->id()));
631 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext4
->id()));
632 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext5
->id()));
633 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext6
->id()));
634 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
637 TEST_F(ProfileResetterTest
, ResetExtensionsByDisablingNonOrganic
) {
638 scoped_refptr
<Extension
> ext2
= CreateExtension(
639 base::ASCIIToUTF16("example2"),
640 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
641 Manifest::INVALID_LOCATION
,
642 extensions::Manifest::TYPE_EXTENSION
,
644 service_
->AddExtension(ext2
.get());
645 // Components and external policy extensions shouldn't be deleted.
646 scoped_refptr
<Extension
> ext3
= CreateExtension(
647 base::ASCIIToUTF16("example3"),
648 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
649 Manifest::INVALID_LOCATION
,
650 extensions::Manifest::TYPE_EXTENSION
,
652 service_
->AddExtension(ext3
.get());
653 EXPECT_EQ(2u, registry()->enabled_extensions().size());
655 std::string
master_prefs(kDistributionConfig
);
656 ReplaceString(&master_prefs
, "placeholder_for_id", ext3
->id());
658 ResetAndWait(ProfileResetter::EXTENSIONS
, master_prefs
);
660 EXPECT_EQ(1u, registry()->enabled_extensions().size());
661 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3
->id()));
664 TEST_F(ProfileResetterTest
, ResetExtensionsAndDefaultApps
) {
667 base::ScopedTempDir temp_dir
;
668 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
670 scoped_refptr
<Extension
> ext1
=
671 CreateExtension(base::ASCIIToUTF16("example1"),
673 Manifest::INVALID_LOCATION
,
674 extensions::Manifest::TYPE_THEME
,
676 service_
->FinishInstallationForTest(ext1
.get());
677 // Let ThemeService finish creating the theme pack.
678 base::MessageLoop::current()->RunUntilIdle();
680 ThemeService
* theme_service
=
681 ThemeServiceFactory::GetForProfile(profile());
682 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
684 scoped_refptr
<Extension
> ext2
=
685 CreateExtension(base::ASCIIToUTF16("example2"),
686 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
687 Manifest::INVALID_LOCATION
,
688 extensions::Manifest::TYPE_EXTENSION
,
690 service_
->AddExtension(ext2
.get());
692 scoped_refptr
<Extension
> ext3
=
693 CreateExtension(base::ASCIIToUTF16("example2"),
694 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
695 Manifest::INVALID_LOCATION
,
696 extensions::Manifest::TYPE_HOSTED_APP
,
698 service_
->AddExtension(ext3
.get());
699 EXPECT_EQ(3u, registry()->enabled_extensions().size());
701 ResetAndWait(ProfileResetter::EXTENSIONS
);
703 EXPECT_EQ(1u, registry()->enabled_extensions().size());
704 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext1
->id()));
705 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2
->id()));
706 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3
->id()));
707 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
710 TEST_F(ProfileResetterTest
, ResetStartPageNonOrganic
) {
711 PrefService
* prefs
= profile()->GetPrefs();
714 SessionStartupPref
startup_pref(SessionStartupPref::LAST
);
715 SessionStartupPref::SetStartupPref(prefs
, startup_pref
);
717 ResetAndWait(ProfileResetter::STARTUP_PAGES
, kDistributionConfig
);
719 startup_pref
= SessionStartupPref::GetStartupPref(prefs
);
720 EXPECT_EQ(SessionStartupPref::URLS
, startup_pref
.type
);
721 const GURL urls
[] = {GURL("http://goo.gl"), GURL("http://foo.de")};
722 EXPECT_EQ(std::vector
<GURL
>(urls
, urls
+ arraysize(urls
)), startup_pref
.urls
);
726 TEST_F(ProfileResetterTest
, ResetStartPagePartially
) {
727 PrefService
* prefs
= profile()->GetPrefs();
730 const GURL urls
[] = {GURL("http://foo"), GURL("http://bar")};
731 SessionStartupPref
startup_pref(SessionStartupPref::URLS
);
732 startup_pref
.urls
.assign(urls
, urls
+ arraysize(urls
));
733 SessionStartupPref::SetStartupPref(prefs
, startup_pref
);
735 ResetAndWait(ProfileResetter::STARTUP_PAGES
, std::string());
737 startup_pref
= SessionStartupPref::GetStartupPref(prefs
);
738 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref
.type
);
739 EXPECT_EQ(std::vector
<GURL
>(urls
, urls
+ arraysize(urls
)), startup_pref
.urls
);
742 TEST_F(PinnedTabsResetTest
, ResetPinnedTabs
) {
743 scoped_ptr
<content::WebContents
> contents1(CreateWebContents());
744 scoped_ptr
<content::WebContents
> contents2(CreateWebContents());
745 scoped_ptr
<content::WebContents
> contents3(CreateWebContents());
746 scoped_ptr
<content::WebContents
> contents4(CreateWebContents());
747 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
749 tab_strip_model
->AppendWebContents(contents4
.get(), true);
750 tab_strip_model
->AppendWebContents(contents3
.get(), true);
751 tab_strip_model
->AppendWebContents(contents2
.get(), true);
752 tab_strip_model
->SetTabPinned(2, true);
753 tab_strip_model
->AppendWebContents(contents1
.get(), true);
754 tab_strip_model
->SetTabPinned(3, true);
756 EXPECT_EQ(contents2
, tab_strip_model
->GetWebContentsAt(0));
757 EXPECT_EQ(contents1
, tab_strip_model
->GetWebContentsAt(1));
758 EXPECT_EQ(contents4
, tab_strip_model
->GetWebContentsAt(2));
759 EXPECT_EQ(contents3
, tab_strip_model
->GetWebContentsAt(3));
760 EXPECT_EQ(2, tab_strip_model
->IndexOfFirstNonPinnedTab());
762 ResetAndWait(ProfileResetter::PINNED_TABS
);
764 EXPECT_EQ(contents2
, tab_strip_model
->GetWebContentsAt(0));
765 EXPECT_EQ(contents1
, tab_strip_model
->GetWebContentsAt(1));
766 EXPECT_EQ(contents4
, tab_strip_model
->GetWebContentsAt(2));
767 EXPECT_EQ(contents3
, tab_strip_model
->GetWebContentsAt(3));
768 EXPECT_EQ(0, tab_strip_model
->IndexOfFirstNonPinnedTab());
771 TEST_F(ProfileResetterTest
, ResetShortcuts
) {
772 ShortcutHandler shortcut
;
773 ShortcutCommand command_line
= shortcut
.CreateWithArguments(
774 base::ASCIIToUTF16("chrome.lnk"),
775 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
776 shortcut
.CheckShortcutHasArguments(base::ASCIIToUTF16(
777 "--profile-directory=Default foo.com"));
779 ResetAndWait(ProfileResetter::SHORTCUTS
);
781 shortcut
.CheckShortcutHasArguments(base::ASCIIToUTF16(
782 "--profile-directory=Default"));
785 TEST_F(ProfileResetterTest
, ResetFewFlags
) {
786 // mock_object_ is a StrictMock, so we verify that it is called only once.
787 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
788 ProfileResetter::HOMEPAGE
|
789 ProfileResetter::CONTENT_SETTINGS
);
792 // Tries to load unavailable config file.
793 TEST_F(ConfigParserTest
, NoConnectivity
) {
794 const GURL
url("http://test");
795 factory().SetFakeResponse(url
, "", net::HTTP_INTERNAL_SERVER_ERROR
,
796 net::URLRequestStatus::FAILED
);
798 scoped_ptr
<BrandcodeConfigFetcher
> fetcher
= WaitForRequest(GURL(url
));
799 EXPECT_FALSE(fetcher
->GetSettings());
802 // Tries to load available config file.
803 TEST_F(ConfigParserTest
, ParseConfig
) {
804 const GURL
url("http://test");
805 std::string
xml_config(kXmlConfig
);
806 ReplaceString(&xml_config
, "placeholder_for_data", kDistributionConfig
);
807 ReplaceString(&xml_config
,
808 "placeholder_for_id",
809 "abbaabbaabbaabbaabbaabbaabbaabba");
810 factory().SetFakeResponse(url
, xml_config
, net::HTTP_OK
,
811 net::URLRequestStatus::SUCCESS
);
813 scoped_ptr
<BrandcodeConfigFetcher
> fetcher
= WaitForRequest(GURL(url
));
814 scoped_ptr
<BrandcodedDefaultSettings
> settings
= fetcher
->GetSettings();
815 ASSERT_TRUE(settings
);
817 std::vector
<std::string
> extension_ids
;
818 EXPECT_TRUE(settings
->GetExtensions(&extension_ids
));
819 EXPECT_EQ(1u, extension_ids
.size());
820 EXPECT_EQ("abbaabbaabbaabbaabbaabbaabbaabba", extension_ids
[0]);
822 std::string homepage
;
823 EXPECT_TRUE(settings
->GetHomepage(&homepage
));
824 EXPECT_EQ("http://www.foo.com", homepage
);
826 scoped_ptr
<base::ListValue
> startup_list(
827 settings
->GetUrlsToRestoreOnStartup());
828 EXPECT_TRUE(startup_list
);
829 std::vector
<std::string
> startup_pages
;
830 for (base::ListValue::iterator i
= startup_list
->begin();
831 i
!= startup_list
->end(); ++i
) {
833 EXPECT_TRUE((*i
)->GetAsString(&url
));
834 startup_pages
.push_back(url
);
836 ASSERT_EQ(2u, startup_pages
.size());
837 EXPECT_EQ("http://goo.gl", startup_pages
[0]);
838 EXPECT_EQ("http://foo.de", startup_pages
[1]);
841 TEST_F(ProfileResetterTest
, CheckSnapshots
) {
842 ResettableSettingsSnapshot
empty_snap(profile());
843 EXPECT_EQ(0, empty_snap
.FindDifferentFields(empty_snap
));
845 scoped_refptr
<Extension
> ext
= CreateExtension(
846 base::ASCIIToUTF16("example"),
847 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
848 Manifest::INVALID_LOCATION
,
849 extensions::Manifest::TYPE_EXTENSION
,
851 ASSERT_TRUE(ext
.get());
852 service_
->AddExtension(ext
.get());
854 std::string
master_prefs(kDistributionConfig
);
855 std::string ext_id
= ext
->id();
856 ReplaceString(&master_prefs
, "placeholder_for_id", ext_id
);
858 // Reset to non organic defaults.
859 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
860 ProfileResetter::HOMEPAGE
|
861 ProfileResetter::STARTUP_PAGES
,
863 ShortcutHandler shortcut_hijacked
;
864 ShortcutCommand command_line
= shortcut_hijacked
.CreateWithArguments(
865 base::ASCIIToUTF16("chrome1.lnk"),
866 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
867 shortcut_hijacked
.CheckShortcutHasArguments(
868 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
869 ShortcutHandler shortcut_ok
;
870 shortcut_ok
.CreateWithArguments(
871 base::ASCIIToUTF16("chrome2.lnk"),
872 base::ASCIIToUTF16("--profile-directory=Default1"));
874 ResettableSettingsSnapshot
nonorganic_snap(profile());
875 nonorganic_snap
.RequestShortcuts(base::Closure());
876 // Let it enumerate shortcuts on the FILE thread.
877 base::MessageLoop::current()->RunUntilIdle();
878 int diff_fields
= ResettableSettingsSnapshot::ALL_FIELDS
;
879 if (!ShortcutHandler::IsSupported())
880 diff_fields
&= ~ResettableSettingsSnapshot::SHORTCUTS
;
881 EXPECT_EQ(diff_fields
,
882 empty_snap
.FindDifferentFields(nonorganic_snap
));
883 empty_snap
.Subtract(nonorganic_snap
);
884 EXPECT_TRUE(empty_snap
.startup_urls().empty());
885 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
886 empty_snap
.startup_type());
887 EXPECT_TRUE(empty_snap
.homepage().empty());
888 EXPECT_TRUE(empty_snap
.homepage_is_ntp());
889 EXPECT_FALSE(empty_snap
.show_home_button());
890 EXPECT_NE(std::string::npos
, empty_snap
.dse_url().find("{google:baseURL}"));
891 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(),
892 empty_snap
.enabled_extensions());
893 EXPECT_EQ(std::vector
<ShortcutCommand
>(), empty_snap
.shortcuts());
895 // Reset to organic defaults.
896 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
897 ProfileResetter::HOMEPAGE
|
898 ProfileResetter::STARTUP_PAGES
|
899 ProfileResetter::EXTENSIONS
|
900 ProfileResetter::SHORTCUTS
);
902 ResettableSettingsSnapshot
organic_snap(profile());
903 organic_snap
.RequestShortcuts(base::Closure());
904 // Let it enumerate shortcuts on the FILE thread.
905 base::MessageLoop::current()->RunUntilIdle();
906 EXPECT_EQ(diff_fields
, nonorganic_snap
.FindDifferentFields(organic_snap
));
907 nonorganic_snap
.Subtract(organic_snap
);
908 const GURL urls
[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
909 EXPECT_EQ(std::vector
<GURL
>(urls
, urls
+ arraysize(urls
)),
910 nonorganic_snap
.startup_urls());
911 EXPECT_EQ(SessionStartupPref::URLS
, nonorganic_snap
.startup_type());
912 EXPECT_EQ("http://www.foo.com", nonorganic_snap
.homepage());
913 EXPECT_FALSE(nonorganic_snap
.homepage_is_ntp());
914 EXPECT_TRUE(nonorganic_snap
.show_home_button());
915 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap
.dse_url());
916 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(
917 1, std::make_pair(ext_id
, "example")),
918 nonorganic_snap
.enabled_extensions());
919 if (ShortcutHandler::IsSupported()) {
920 std::vector
<ShortcutCommand
> shortcuts
= nonorganic_snap
.shortcuts();
921 ASSERT_EQ(1u, shortcuts
.size());
922 EXPECT_EQ(command_line
.first
.value(), shortcuts
[0].first
.value());
923 EXPECT_EQ(command_line
.second
, shortcuts
[0].second
);
927 TEST_F(ProfileResetterTest
, FeedbackSerializationTest
) {
928 // Reset to non organic defaults.
929 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
930 ProfileResetter::HOMEPAGE
|
931 ProfileResetter::STARTUP_PAGES
,
932 kDistributionConfig
);
934 scoped_refptr
<Extension
> ext
= CreateExtension(
935 base::ASCIIToUTF16("example"),
936 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
937 Manifest::INVALID_LOCATION
,
938 extensions::Manifest::TYPE_EXTENSION
,
940 ASSERT_TRUE(ext
.get());
941 service_
->AddExtension(ext
.get());
943 ShortcutHandler shortcut
;
944 ShortcutCommand command_line
= shortcut
.CreateWithArguments(
945 base::ASCIIToUTF16("chrome.lnk"),
946 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
948 ResettableSettingsSnapshot
nonorganic_snap(profile());
949 nonorganic_snap
.RequestShortcuts(base::Closure());
950 // Let it enumerate shortcuts on the FILE thread.
951 base::MessageLoop::current()->RunUntilIdle();
953 static_assert(ResettableSettingsSnapshot::ALL_FIELDS
== 31,
954 "this test needs to be expanded");
955 for (int field_mask
= 0; field_mask
<= ResettableSettingsSnapshot::ALL_FIELDS
;
957 std::string report
= SerializeSettingsReport(nonorganic_snap
, field_mask
);
958 JSONStringValueDeserializer
json(report
);
960 scoped_ptr
<base::Value
> root(json
.Deserialize(NULL
, &error
));
961 ASSERT_TRUE(root
) << error
;
962 ASSERT_TRUE(root
->IsType(base::Value::TYPE_DICTIONARY
)) << error
;
964 base::DictionaryValue
* dict
=
965 static_cast<base::DictionaryValue
*>(root
.get());
967 base::ListValue
* startup_urls
= NULL
;
968 int startup_type
= 0;
969 std::string homepage
;
970 bool homepage_is_ntp
= true;
971 bool show_home_button
= true;
972 std::string default_search_engine
;
973 base::ListValue
* extensions
= NULL
;
974 base::ListValue
* shortcuts
= NULL
;
976 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::STARTUP_MODE
),
977 dict
->GetList("startup_urls", &startup_urls
));
978 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::STARTUP_MODE
),
979 dict
->GetInteger("startup_type", &startup_type
));
980 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::HOMEPAGE
),
981 dict
->GetString("homepage", &homepage
));
982 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::HOMEPAGE
),
983 dict
->GetBoolean("homepage_is_ntp", &homepage_is_ntp
));
984 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::HOMEPAGE
),
985 dict
->GetBoolean("show_home_button", &show_home_button
));
986 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::DSE_URL
),
987 dict
->GetString("default_search_engine", &default_search_engine
));
988 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::EXTENSIONS
),
989 dict
->GetList("enabled_extensions", &extensions
));
990 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::SHORTCUTS
),
991 dict
->GetList("shortcuts", &shortcuts
));
995 struct FeedbackCapture
{
996 void SetFeedback(Profile
* profile
,
997 const ResettableSettingsSnapshot
& snapshot
) {
998 list_
= GetReadableFeedbackForSnapshot(profile
, snapshot
).Pass();
1003 ADD_FAILURE() << "This method shouldn't be called.";
1006 MOCK_METHOD0(OnUpdatedList
, void(void));
1008 scoped_ptr
<base::ListValue
> list_
;
1011 // Make sure GetReadableFeedback handles non-ascii letters.
1012 TEST_F(ProfileResetterTest
, GetReadableFeedback
) {
1013 scoped_refptr
<Extension
> ext
= CreateExtension(
1014 base::WideToUTF16(L
"Tiësto"),
1015 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
1016 Manifest::INVALID_LOCATION
,
1017 extensions::Manifest::TYPE_EXTENSION
,
1019 ASSERT_TRUE(ext
.get());
1020 service_
->AddExtension(ext
.get());
1022 PrefService
* prefs
= profile()->GetPrefs();
1024 // The URL is "http://россия.рф".
1025 std::wstring
url(L
"http://"
1026 L
"\u0440\u043e\u0441\u0441\u0438\u044f.\u0440\u0444");
1027 prefs
->SetBoolean(prefs::kHomePageIsNewTabPage
, false);
1028 prefs
->SetString(prefs::kHomePage
, base::WideToUTF8(url
));
1030 SessionStartupPref
startup_pref(SessionStartupPref::URLS
);
1031 startup_pref
.urls
.push_back(GURL(base::WideToUTF8(url
)));
1032 SessionStartupPref::SetStartupPref(prefs
, startup_pref
);
1034 ShortcutHandler shortcut
;
1035 ShortcutCommand command_line
= shortcut
.CreateWithArguments(
1036 base::ASCIIToUTF16("chrome.lnk"),
1037 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
1039 FeedbackCapture capture
;
1040 EXPECT_CALL(capture
, OnUpdatedList());
1041 ResettableSettingsSnapshot
snapshot(profile());
1042 snapshot
.RequestShortcuts(base::Bind(&FeedbackCapture::SetFeedback
,
1043 base::Unretained(&capture
),
1045 base::ConstRef(snapshot
)));
1046 // Let it enumerate shortcuts on the FILE thread.
1047 base::MessageLoop::current()->RunUntilIdle();
1048 ::testing::Mock::VerifyAndClearExpectations(&capture
);
1049 // The homepage and the startup page are in punycode. They are unreadable.
1050 // Trying to find the extension name.
1051 scoped_ptr
<base::ListValue
> list
= capture
.list_
.Pass();
1053 bool checked_extensions
= false;
1054 bool checked_shortcuts
= false;
1055 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
1056 base::DictionaryValue
* dict
= NULL
;
1057 ASSERT_TRUE(list
->GetDictionary(i
, &dict
));
1059 ASSERT_TRUE(dict
->GetString("key", &value
));
1060 if (value
== "Extensions") {
1061 base::string16 extensions
;
1062 EXPECT_TRUE(dict
->GetString("value", &extensions
));
1063 EXPECT_EQ(base::WideToUTF16(L
"Tiësto"), extensions
);
1064 checked_extensions
= true;
1065 } else if (value
== "Shortcut targets") {
1066 base::string16 targets
;
1067 EXPECT_TRUE(dict
->GetString("value", &targets
));
1068 EXPECT_NE(base::string16::npos
,
1069 targets
.find(base::ASCIIToUTF16("foo.com"))) << targets
;
1070 checked_shortcuts
= true;
1073 EXPECT_TRUE(checked_extensions
);
1074 EXPECT_EQ(ShortcutHandler::IsSupported(), checked_shortcuts
);
1077 TEST_F(ProfileResetterTest
, DestroySnapshotFast
) {
1078 FeedbackCapture capture
;
1079 scoped_ptr
<ResettableSettingsSnapshot
> deleted_snapshot(
1080 new ResettableSettingsSnapshot(profile()));
1081 deleted_snapshot
->RequestShortcuts(base::Bind(&FeedbackCapture::Fail
,
1082 base::Unretained(&capture
)));
1083 deleted_snapshot
.reset();
1084 // Running remaining tasks shouldn't trigger the callback to be called as
1085 // |deleted_snapshot| was deleted before it could run.
1086 base::MessageLoop::current()->RunUntilIdle();