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/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/scoped_path_override.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_service_test_base.h"
13 #include "chrome/browser/extensions/tab_helper.h"
14 #include "chrome/browser/prefs/session_startup_pref.h"
15 #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h"
16 #include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
17 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
18 #include "chrome/browser/search_engines/template_url_service_factory.h"
19 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
20 #include "chrome/browser/themes/theme_service.h"
21 #include "chrome/browser/themes/theme_service_factory.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/webdata/web_data_service_factory.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/browser_with_test_window_test.h"
26 #include "components/content_settings/core/browser/host_content_settings_map.h"
27 #include "components/search_engines/template_url_service.h"
28 #include "components/search_engines/template_url_service_client.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/test/test_browser_thread.h"
31 #include "extensions/browser/extension_registry.h"
32 #include "extensions/common/extension.h"
33 #include "extensions/common/manifest_constants.h"
34 #include "net/http/http_response_headers.h"
35 #include "net/http/http_status_code.h"
36 #include "net/url_request/test_url_fetcher_factory.h"
37 #include "net/url_request/url_request_status.h"
41 #include "base/files/file_util.h"
42 #include "base/path_service.h"
43 #include "base/process/process_handle.h"
44 #include "base/rand_util.h"
45 #include "base/strings/string_number_conversions.h"
46 #include "base/win/scoped_com_initializer.h"
47 #include "base/win/shortcut.h"
53 const char kDistributionConfig
[] = "{"
54 " \"homepage\" : \"http://www.foo.com\","
55 " \"homepage_is_newtabpage\" : false,"
57 " \"show_home_button\" : true"
60 " \"restore_on_startup\" : 4,"
61 " \"startup_urls\" : [\"http://goo.gl\", \"http://foo.de\"]"
63 " \"search_provider_overrides\" : ["
65 " \"name\" : \"first\","
66 " \"keyword\" : \"firstkey\","
67 " \"search_url\" : \"http://www.foo.com/s?q={searchTerms}\","
68 " \"favicon_url\" : \"http://www.foo.com/favicon.ico\","
69 " \"suggest_url\" : \"http://www.foo.com/s?q={searchTerms}\","
70 " \"encoding\" : \"UTF-8\","
76 " \"placeholder_for_id\": {"
82 const char kXmlConfig
[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
83 "<response protocol=\"3.0\" server=\"prod\">"
84 "<app appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\" status=\"ok\">"
85 "<data index=\"skipfirstrunui-importsearch-defaultbrowser\" "
86 "name=\"install\" status=\"ok\">"
87 "placeholder_for_data"
92 using extensions::Extension
;
93 using extensions::Manifest
;
96 // ProfileResetterTest --------------------------------------------------------
98 // ProfileResetterTest sets up the extension, WebData and TemplateURL services.
99 class ProfileResetterTest
: public extensions::ExtensionServiceTestBase
,
100 public ProfileResetterTestBase
{
102 ProfileResetterTest();
103 ~ProfileResetterTest() override
;
106 void SetUp() override
;
108 TestingProfile
* profile() { return profile_
.get(); }
110 static KeyedService
* CreateTemplateURLService(
111 content::BrowserContext
* context
);
115 base::ScopedPathOverride user_desktop_override_
;
116 base::ScopedPathOverride app_dir_override_
;
117 base::ScopedPathOverride start_menu_override_
;
118 base::ScopedPathOverride taskbar_pins_override_
;
119 base::win::ScopedCOMInitializer com_init_
;
123 ProfileResetterTest::ProfileResetterTest()
125 : user_desktop_override_(base::DIR_USER_DESKTOP
),
126 app_dir_override_(base::DIR_APP_DATA
),
127 start_menu_override_(base::DIR_START_MENU
),
128 taskbar_pins_override_(base::DIR_TASKBAR_PINS
)
132 ProfileResetterTest::~ProfileResetterTest() {
135 void ProfileResetterTest::SetUp() {
136 extensions::ExtensionServiceTestBase::SetUp();
137 InitializeEmptyExtensionService();
139 profile()->CreateWebDataService();
140 TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
142 &ProfileResetterTest::CreateTemplateURLService
);
143 resetter_
.reset(new ProfileResetter(profile()));
147 KeyedService
* ProfileResetterTest::CreateTemplateURLService(
148 content::BrowserContext
* context
) {
149 Profile
* profile
= static_cast<Profile
*>(context
);
150 return new TemplateURLService(
152 scoped_ptr
<SearchTermsData
>(new UIThreadSearchTermsData(profile
)),
153 WebDataServiceFactory::GetKeywordWebDataForProfile(
154 profile
, ServiceAccessType::EXPLICIT_ACCESS
),
155 scoped_ptr
<TemplateURLServiceClient
>(), NULL
, NULL
, base::Closure());
159 // PinnedTabsResetTest --------------------------------------------------------
161 class PinnedTabsResetTest
: public BrowserWithTestWindowTest
,
162 public ProfileResetterTestBase
{
164 void SetUp() override
;
166 content::WebContents
* CreateWebContents();
169 void PinnedTabsResetTest::SetUp() {
170 BrowserWithTestWindowTest::SetUp();
171 resetter_
.reset(new ProfileResetter(profile()));
174 content::WebContents
* PinnedTabsResetTest::CreateWebContents() {
175 return content::WebContents::Create(
176 content::WebContents::CreateParams(profile()));
180 // ConfigParserTest -----------------------------------------------------------
182 // URLFetcher delegate that simply records the upload data.
183 struct URLFetcherRequestListener
: net::URLFetcherDelegate
{
184 URLFetcherRequestListener();
185 ~URLFetcherRequestListener() override
;
187 void OnURLFetchComplete(const net::URLFetcher
* source
) override
;
189 std::string upload_data
;
190 net::URLFetcherDelegate
* real_delegate
;
193 URLFetcherRequestListener::URLFetcherRequestListener()
194 : real_delegate(NULL
) {
197 URLFetcherRequestListener::~URLFetcherRequestListener() {
200 void URLFetcherRequestListener::OnURLFetchComplete(
201 const net::URLFetcher
* source
) {
202 const net::TestURLFetcher
* test_fetcher
=
203 static_cast<const net::TestURLFetcher
*>(source
);
204 upload_data
= test_fetcher
->upload_data();
205 DCHECK(real_delegate
);
206 real_delegate
->OnURLFetchComplete(source
);
209 class ConfigParserTest
: public testing::Test
{
212 virtual ~ConfigParserTest();
214 scoped_ptr
<BrandcodeConfigFetcher
> WaitForRequest(const GURL
& url
);
216 net::FakeURLFetcherFactory
& factory() { return factory_
; }
219 scoped_ptr
<net::FakeURLFetcher
> CreateFakeURLFetcher(
221 net::URLFetcherDelegate
* fetcher_delegate
,
222 const std::string
& response_data
,
223 net::HttpStatusCode response_code
,
224 net::URLRequestStatus::Status status
);
226 MOCK_METHOD0(Callback
, void(void));
228 base::MessageLoopForIO loop_
;
229 content::TestBrowserThread ui_thread_
;
230 content::TestBrowserThread io_thread_
;
231 URLFetcherRequestListener request_listener_
;
232 net::FakeURLFetcherFactory factory_
;
235 ConfigParserTest::ConfigParserTest()
236 : ui_thread_(content::BrowserThread::UI
, &loop_
),
237 io_thread_(content::BrowserThread::IO
, &loop_
),
238 factory_(NULL
, base::Bind(&ConfigParserTest::CreateFakeURLFetcher
,
239 base::Unretained(this))) {
242 ConfigParserTest::~ConfigParserTest() {}
244 scoped_ptr
<BrandcodeConfigFetcher
> ConfigParserTest::WaitForRequest(
246 EXPECT_CALL(*this, Callback());
247 scoped_ptr
<BrandcodeConfigFetcher
> fetcher(
248 new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback
,
249 base::Unretained(this)),
252 base::MessageLoop::current()->RunUntilIdle();
253 EXPECT_FALSE(fetcher
->IsActive());
254 // Look for the brand code in the request.
255 EXPECT_NE(std::string::npos
, request_listener_
.upload_data
.find("ABCD"));
256 return fetcher
.Pass();
259 scoped_ptr
<net::FakeURLFetcher
> ConfigParserTest::CreateFakeURLFetcher(
261 net::URLFetcherDelegate
* fetcher_delegate
,
262 const std::string
& response_data
,
263 net::HttpStatusCode response_code
,
264 net::URLRequestStatus::Status status
) {
265 request_listener_
.real_delegate
= fetcher_delegate
;
266 scoped_ptr
<net::FakeURLFetcher
> fetcher(
267 new net::FakeURLFetcher(
268 url
, &request_listener_
, response_data
, response_code
, status
));
269 scoped_refptr
<net::HttpResponseHeaders
> download_headers
=
270 new net::HttpResponseHeaders("");
271 download_headers
->AddHeader("Content-Type: text/xml");
272 fetcher
->set_response_headers(download_headers
);
273 return fetcher
.Pass();
276 // A helper class to create/delete/check a Chrome desktop shortcut on Windows.
277 class ShortcutHandler
{
282 static bool IsSupported();
283 ShortcutCommand
CreateWithArguments(const base::string16
& name
,
284 const base::string16
& args
);
285 void CheckShortcutHasArguments(const base::string16
& desired_args
) const;
290 base::FilePath shortcut_path_
;
292 DISALLOW_COPY_AND_ASSIGN(ShortcutHandler
);
296 ShortcutHandler::ShortcutHandler() {
299 ShortcutHandler::~ShortcutHandler() {
300 if (!shortcut_path_
.empty())
305 bool ShortcutHandler::IsSupported() {
309 ShortcutCommand
ShortcutHandler::CreateWithArguments(
310 const base::string16
& name
,
311 const base::string16
& args
) {
312 EXPECT_TRUE(shortcut_path_
.empty());
313 base::FilePath path_to_create
;
314 EXPECT_TRUE(PathService::Get(base::DIR_USER_DESKTOP
, &path_to_create
));
315 path_to_create
= path_to_create
.Append(name
);
316 EXPECT_FALSE(base::PathExists(path_to_create
)) << path_to_create
.value();
318 base::FilePath path_exe
;
319 EXPECT_TRUE(PathService::Get(base::FILE_EXE
, &path_exe
));
320 base::win::ShortcutProperties shortcut_properties
;
321 shortcut_properties
.set_target(path_exe
);
322 shortcut_properties
.set_arguments(args
);
323 EXPECT_TRUE(base::win::CreateOrUpdateShortcutLink(
324 path_to_create
, shortcut_properties
,
325 base::win::SHORTCUT_CREATE_ALWAYS
)) << path_to_create
.value();
326 shortcut_path_
= path_to_create
;
327 return ShortcutCommand(shortcut_path_
, args
);
330 void ShortcutHandler::CheckShortcutHasArguments(
331 const base::string16
& desired_args
) const {
332 EXPECT_FALSE(shortcut_path_
.empty());
334 EXPECT_TRUE(base::win::ResolveShortcut(shortcut_path_
, NULL
, &args
));
335 EXPECT_EQ(desired_args
, args
);
338 void ShortcutHandler::Delete() {
339 EXPECT_FALSE(shortcut_path_
.empty());
340 EXPECT_TRUE(base::DeleteFile(shortcut_path_
, false));
341 shortcut_path_
.clear();
344 ShortcutHandler::ShortcutHandler() {}
346 ShortcutHandler::~ShortcutHandler() {}
349 bool ShortcutHandler::IsSupported() {
353 ShortcutCommand
ShortcutHandler::CreateWithArguments(
354 const base::string16
& name
,
355 const base::string16
& args
) {
356 return ShortcutCommand();
359 void ShortcutHandler::CheckShortcutHasArguments(
360 const base::string16
& desired_args
) const {
363 void ShortcutHandler::Delete() {
365 #endif // defined(OS_WIN)
368 // helper functions -----------------------------------------------------------
370 scoped_refptr
<Extension
> CreateExtension(const base::string16
& name
,
371 const base::FilePath
& path
,
372 Manifest::Location location
,
373 extensions::Manifest::Type type
,
374 bool installed_by_default
) {
375 base::DictionaryValue manifest
;
376 manifest
.SetString(extensions::manifest_keys::kVersion
, "1.0.0.0");
377 manifest
.SetString(extensions::manifest_keys::kName
, name
);
379 case extensions::Manifest::TYPE_THEME
:
380 manifest
.Set(extensions::manifest_keys::kTheme
,
381 new base::DictionaryValue
);
383 case extensions::Manifest::TYPE_HOSTED_APP
:
384 manifest
.SetString(extensions::manifest_keys::kLaunchWebURL
,
385 "http://www.google.com");
386 manifest
.SetString(extensions::manifest_keys::kUpdateURL
,
387 "http://clients2.google.com/service/update2/crx");
389 case extensions::Manifest::TYPE_EXTENSION
:
395 manifest
.SetString(extensions::manifest_keys::kOmniboxKeyword
, name
);
397 scoped_refptr
<Extension
> extension
= Extension::Create(
401 installed_by_default
? Extension::WAS_INSTALLED_BY_DEFAULT
402 : Extension::NO_FLAGS
,
404 EXPECT_TRUE(extension
.get() != NULL
) << error
;
408 void ReplaceString(std::string
* str
,
409 const std::string
& placeholder
,
410 const std::string
& substitution
) {
411 ASSERT_NE(static_cast<std::string
*>(NULL
), str
);
412 size_t placeholder_pos
= str
->find(placeholder
);
413 ASSERT_NE(std::string::npos
, placeholder_pos
);
414 str
->replace(placeholder_pos
, placeholder
.size(), substitution
);
418 /********************* Tests *********************/
420 TEST_F(ProfileResetterTest
, ResetNothing
) {
421 // The callback should be called even if there is nothing to reset.
425 TEST_F(ProfileResetterTest
, ResetDefaultSearchEngineNonOrganic
) {
426 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
, kDistributionConfig
);
428 TemplateURLService
* model
=
429 TemplateURLServiceFactory::GetForProfile(profile());
430 TemplateURL
* default_engine
= model
->GetDefaultSearchProvider();
431 ASSERT_NE(static_cast<TemplateURL
*>(NULL
), default_engine
);
432 EXPECT_EQ(base::ASCIIToUTF16("first"), default_engine
->short_name());
433 EXPECT_EQ(base::ASCIIToUTF16("firstkey"), default_engine
->keyword());
434 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", default_engine
->url());
437 TEST_F(ProfileResetterTest
, ResetDefaultSearchEnginePartially
) {
438 // Search engine's logic is tested by
439 // TemplateURLServiceTest.RepairPrepopulatedSearchEngines.
440 // Make sure TemplateURLService has loaded.
441 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
);
443 TemplateURLService
* model
=
444 TemplateURLServiceFactory::GetForProfile(profile());
445 TemplateURLService::TemplateURLVector urls
= model
->GetTemplateURLs();
447 // The second call should produce no effect.
448 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
);
450 EXPECT_EQ(urls
, model
->GetTemplateURLs());
453 TEST_F(ProfileResetterTest
, ResetHomepageNonOrganic
) {
454 PrefService
* prefs
= profile()->GetPrefs();
456 prefs
->SetBoolean(prefs::kHomePageIsNewTabPage
, true);
457 prefs
->SetString(prefs::kHomePage
, "http://google.com");
458 prefs
->SetBoolean(prefs::kShowHomeButton
, false);
460 ResetAndWait(ProfileResetter::HOMEPAGE
, kDistributionConfig
);
462 EXPECT_FALSE(prefs
->GetBoolean(prefs::kHomePageIsNewTabPage
));
463 EXPECT_EQ("http://www.foo.com", prefs
->GetString(prefs::kHomePage
));
464 EXPECT_TRUE(prefs
->GetBoolean(prefs::kShowHomeButton
));
467 TEST_F(ProfileResetterTest
, ResetHomepagePartially
) {
468 PrefService
* prefs
= profile()->GetPrefs();
470 prefs
->SetBoolean(prefs::kHomePageIsNewTabPage
, false);
471 prefs
->SetString(prefs::kHomePage
, "http://www.foo.com");
472 prefs
->SetBoolean(prefs::kShowHomeButton
, true);
474 ResetAndWait(ProfileResetter::HOMEPAGE
);
476 EXPECT_TRUE(prefs
->GetBoolean(prefs::kHomePageIsNewTabPage
));
477 EXPECT_EQ("http://www.foo.com", prefs
->GetString(prefs::kHomePage
));
478 EXPECT_FALSE(prefs
->GetBoolean(prefs::kShowHomeButton
));
481 TEST_F(ProfileResetterTest
, ResetContentSettings
) {
482 HostContentSettingsMap
* host_content_settings_map
=
483 profile()->GetHostContentSettingsMap();
484 ContentSettingsPattern pattern
=
485 ContentSettingsPattern::FromString("[*.]example.org");
486 std::map
<ContentSettingsType
, ContentSetting
> default_settings
;
488 for (int type
= 0; type
< CONTENT_SETTINGS_NUM_TYPES
; ++type
) {
489 if (type
== CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
||
490 type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
||
491 type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
492 // These types are excluded because one can't call
493 // GetDefaultContentSetting() for them.
495 ContentSettingsType content_type
= static_cast<ContentSettingsType
>(type
);
496 ContentSetting default_setting
=
497 host_content_settings_map
->GetDefaultContentSetting(content_type
,
499 default_settings
[content_type
] = default_setting
;
500 ContentSetting wildcard_setting
=
501 default_setting
== CONTENT_SETTING_BLOCK
? CONTENT_SETTING_ALLOW
502 : CONTENT_SETTING_BLOCK
;
503 ContentSetting site_setting
=
504 default_setting
== CONTENT_SETTING_ALLOW
? CONTENT_SETTING_ALLOW
505 : CONTENT_SETTING_BLOCK
;
506 if (HostContentSettingsMap::IsSettingAllowedForType(
507 profile()->GetPrefs(),
510 host_content_settings_map
->SetDefaultContentSetting(
514 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
) &&
515 HostContentSettingsMap::IsSettingAllowedForType(
516 profile()->GetPrefs(),
519 host_content_settings_map
->SetContentSetting(
521 ContentSettingsPattern::Wildcard(),
525 ContentSettingsForOneType host_settings
;
526 host_content_settings_map
->GetSettingsForOneType(
527 content_type
, std::string(), &host_settings
);
528 EXPECT_EQ(2U, host_settings
.size());
533 ResetAndWait(ProfileResetter::CONTENT_SETTINGS
);
535 for (int type
= 0; type
< CONTENT_SETTINGS_NUM_TYPES
; ++type
) {
536 ContentSettingsType content_type
= static_cast<ContentSettingsType
>(type
);
537 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
) ||
538 type
== CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
||
539 content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
||
540 content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
)
542 ContentSetting default_setting
=
543 host_content_settings_map
->GetDefaultContentSetting(content_type
,
545 EXPECT_TRUE(default_settings
.count(content_type
));
546 EXPECT_EQ(default_settings
[content_type
], default_setting
);
547 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
)) {
548 ContentSetting site_setting
=
549 host_content_settings_map
->GetContentSetting(
554 EXPECT_EQ(default_setting
, site_setting
);
557 ContentSettingsForOneType host_settings
;
558 host_content_settings_map
->GetSettingsForOneType(
559 content_type
, std::string(), &host_settings
);
560 EXPECT_EQ(1U, host_settings
.size());
564 TEST_F(ProfileResetterTest
, ResetExtensionsByDisabling
) {
567 base::ScopedTempDir temp_dir
;
568 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
570 scoped_refptr
<Extension
> theme
=
571 CreateExtension(base::ASCIIToUTF16("example1"),
573 Manifest::INVALID_LOCATION
,
574 extensions::Manifest::TYPE_THEME
,
576 service_
->FinishInstallationForTest(theme
.get());
577 // Let ThemeService finish creating the theme pack.
578 base::MessageLoop::current()->RunUntilIdle();
580 ThemeService
* theme_service
=
581 ThemeServiceFactory::GetForProfile(profile());
582 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
584 scoped_refptr
<Extension
> ext2
= CreateExtension(
585 base::ASCIIToUTF16("example2"),
586 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
587 Manifest::INVALID_LOCATION
,
588 extensions::Manifest::TYPE_EXTENSION
,
590 service_
->AddExtension(ext2
.get());
591 // Component extensions and policy-managed extensions shouldn't be disabled.
592 scoped_refptr
<Extension
> ext3
= CreateExtension(
593 base::ASCIIToUTF16("example3"),
594 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
596 extensions::Manifest::TYPE_EXTENSION
,
598 service_
->AddExtension(ext3
.get());
599 scoped_refptr
<Extension
> ext4
=
600 CreateExtension(base::ASCIIToUTF16("example4"),
601 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
602 Manifest::EXTERNAL_POLICY_DOWNLOAD
,
603 extensions::Manifest::TYPE_EXTENSION
,
605 service_
->AddExtension(ext4
.get());
606 scoped_refptr
<Extension
> ext5
= CreateExtension(
607 base::ASCIIToUTF16("example5"),
608 base::FilePath(FILE_PATH_LITERAL("//nonexistent4")),
609 Manifest::EXTERNAL_COMPONENT
,
610 extensions::Manifest::TYPE_EXTENSION
,
612 service_
->AddExtension(ext5
.get());
613 scoped_refptr
<Extension
> ext6
= CreateExtension(
614 base::ASCIIToUTF16("example6"),
615 base::FilePath(FILE_PATH_LITERAL("//nonexistent5")),
616 Manifest::EXTERNAL_POLICY
,
617 extensions::Manifest::TYPE_EXTENSION
,
619 service_
->AddExtension(ext6
.get());
620 EXPECT_EQ(6u, registry()->enabled_extensions().size());
622 ResetAndWait(ProfileResetter::EXTENSIONS
);
623 EXPECT_EQ(4u, registry()->enabled_extensions().size());
624 EXPECT_FALSE(registry()->enabled_extensions().Contains(theme
->id()));
625 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2
->id()));
626 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3
->id()));
627 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext4
->id()));
628 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext5
->id()));
629 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext6
->id()));
630 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
633 TEST_F(ProfileResetterTest
, ResetExtensionsByDisablingNonOrganic
) {
634 scoped_refptr
<Extension
> ext2
= CreateExtension(
635 base::ASCIIToUTF16("example2"),
636 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
637 Manifest::INVALID_LOCATION
,
638 extensions::Manifest::TYPE_EXTENSION
,
640 service_
->AddExtension(ext2
.get());
641 // Components and external policy extensions shouldn't be deleted.
642 scoped_refptr
<Extension
> ext3
= CreateExtension(
643 base::ASCIIToUTF16("example3"),
644 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
645 Manifest::INVALID_LOCATION
,
646 extensions::Manifest::TYPE_EXTENSION
,
648 service_
->AddExtension(ext3
.get());
649 EXPECT_EQ(2u, registry()->enabled_extensions().size());
651 std::string
master_prefs(kDistributionConfig
);
652 ReplaceString(&master_prefs
, "placeholder_for_id", ext3
->id());
654 ResetAndWait(ProfileResetter::EXTENSIONS
, master_prefs
);
656 EXPECT_EQ(1u, registry()->enabled_extensions().size());
657 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3
->id()));
660 TEST_F(ProfileResetterTest
, ResetExtensionsAndDefaultApps
) {
663 base::ScopedTempDir temp_dir
;
664 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
666 scoped_refptr
<Extension
> ext1
=
667 CreateExtension(base::ASCIIToUTF16("example1"),
669 Manifest::INVALID_LOCATION
,
670 extensions::Manifest::TYPE_THEME
,
672 service_
->FinishInstallationForTest(ext1
.get());
673 // Let ThemeService finish creating the theme pack.
674 base::MessageLoop::current()->RunUntilIdle();
676 ThemeService
* theme_service
=
677 ThemeServiceFactory::GetForProfile(profile());
678 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
680 scoped_refptr
<Extension
> ext2
=
681 CreateExtension(base::ASCIIToUTF16("example2"),
682 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
683 Manifest::INVALID_LOCATION
,
684 extensions::Manifest::TYPE_EXTENSION
,
686 service_
->AddExtension(ext2
.get());
688 scoped_refptr
<Extension
> ext3
=
689 CreateExtension(base::ASCIIToUTF16("example2"),
690 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
691 Manifest::INVALID_LOCATION
,
692 extensions::Manifest::TYPE_HOSTED_APP
,
694 service_
->AddExtension(ext3
.get());
695 EXPECT_EQ(3u, registry()->enabled_extensions().size());
697 ResetAndWait(ProfileResetter::EXTENSIONS
);
699 EXPECT_EQ(1u, registry()->enabled_extensions().size());
700 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext1
->id()));
701 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2
->id()));
702 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3
->id()));
703 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
706 TEST_F(ProfileResetterTest
, ResetStartPageNonOrganic
) {
707 PrefService
* prefs
= profile()->GetPrefs();
710 SessionStartupPref
startup_pref(SessionStartupPref::LAST
);
711 SessionStartupPref::SetStartupPref(prefs
, startup_pref
);
713 ResetAndWait(ProfileResetter::STARTUP_PAGES
, kDistributionConfig
);
715 startup_pref
= SessionStartupPref::GetStartupPref(prefs
);
716 EXPECT_EQ(SessionStartupPref::URLS
, startup_pref
.type
);
717 const GURL urls
[] = {GURL("http://goo.gl"), GURL("http://foo.de")};
718 EXPECT_EQ(std::vector
<GURL
>(urls
, urls
+ arraysize(urls
)), startup_pref
.urls
);
722 TEST_F(ProfileResetterTest
, ResetStartPagePartially
) {
723 PrefService
* prefs
= profile()->GetPrefs();
726 const GURL urls
[] = {GURL("http://foo"), GURL("http://bar")};
727 SessionStartupPref
startup_pref(SessionStartupPref::URLS
);
728 startup_pref
.urls
.assign(urls
, urls
+ arraysize(urls
));
729 SessionStartupPref::SetStartupPref(prefs
, startup_pref
);
731 ResetAndWait(ProfileResetter::STARTUP_PAGES
, std::string());
733 startup_pref
= SessionStartupPref::GetStartupPref(prefs
);
734 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref
.type
);
735 EXPECT_EQ(std::vector
<GURL
>(urls
, urls
+ arraysize(urls
)), startup_pref
.urls
);
738 TEST_F(PinnedTabsResetTest
, ResetPinnedTabs
) {
739 scoped_refptr
<Extension
> extension_app
= CreateExtension(
740 base::ASCIIToUTF16("hello!"),
741 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
742 Manifest::INVALID_LOCATION
,
743 extensions::Manifest::TYPE_HOSTED_APP
,
745 scoped_ptr
<content::WebContents
> contents1(CreateWebContents());
746 extensions::TabHelper::CreateForWebContents(contents1
.get());
747 extensions::TabHelper::FromWebContents(contents1
.get())->
748 SetExtensionApp(extension_app
.get());
749 scoped_ptr
<content::WebContents
> contents2(CreateWebContents());
750 scoped_ptr
<content::WebContents
> contents3(CreateWebContents());
751 scoped_ptr
<content::WebContents
> contents4(CreateWebContents());
752 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
754 tab_strip_model
->AppendWebContents(contents4
.get(), true);
755 tab_strip_model
->AppendWebContents(contents3
.get(), true);
756 tab_strip_model
->AppendWebContents(contents2
.get(), true);
757 tab_strip_model
->SetTabPinned(2, true);
758 tab_strip_model
->AppendWebContents(contents1
.get(), true);
759 tab_strip_model
->SetTabPinned(3, true);
761 EXPECT_EQ(contents2
, tab_strip_model
->GetWebContentsAt(0));
762 EXPECT_EQ(contents1
, tab_strip_model
->GetWebContentsAt(1));
763 EXPECT_EQ(contents3
, tab_strip_model
->GetWebContentsAt(2));
764 EXPECT_EQ(contents4
, tab_strip_model
->GetWebContentsAt(3));
765 EXPECT_EQ(3, tab_strip_model
->IndexOfFirstNonMiniTab());
767 ResetAndWait(ProfileResetter::PINNED_TABS
);
769 EXPECT_EQ(contents1
, tab_strip_model
->GetWebContentsAt(0));
770 EXPECT_EQ(contents2
, tab_strip_model
->GetWebContentsAt(1));
771 EXPECT_EQ(contents3
, tab_strip_model
->GetWebContentsAt(2));
772 EXPECT_EQ(contents4
, tab_strip_model
->GetWebContentsAt(3));
773 EXPECT_EQ(1, tab_strip_model
->IndexOfFirstNonMiniTab());
776 TEST_F(ProfileResetterTest
, ResetShortcuts
) {
777 ShortcutHandler shortcut
;
778 ShortcutCommand command_line
= shortcut
.CreateWithArguments(
779 base::ASCIIToUTF16("chrome.lnk"),
780 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
781 shortcut
.CheckShortcutHasArguments(base::ASCIIToUTF16(
782 "--profile-directory=Default foo.com"));
784 ResetAndWait(ProfileResetter::SHORTCUTS
);
786 shortcut
.CheckShortcutHasArguments(base::ASCIIToUTF16(
787 "--profile-directory=Default"));
790 TEST_F(ProfileResetterTest
, ResetFewFlags
) {
791 // mock_object_ is a StrictMock, so we verify that it is called only once.
792 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
793 ProfileResetter::HOMEPAGE
|
794 ProfileResetter::CONTENT_SETTINGS
);
797 // Tries to load unavailable config file.
798 TEST_F(ConfigParserTest
, NoConnectivity
) {
799 const GURL
url("http://test");
800 factory().SetFakeResponse(url
, "", net::HTTP_INTERNAL_SERVER_ERROR
,
801 net::URLRequestStatus::FAILED
);
803 scoped_ptr
<BrandcodeConfigFetcher
> fetcher
= WaitForRequest(GURL(url
));
804 EXPECT_FALSE(fetcher
->GetSettings());
807 // Tries to load available config file.
808 TEST_F(ConfigParserTest
, ParseConfig
) {
809 const GURL
url("http://test");
810 std::string
xml_config(kXmlConfig
);
811 ReplaceString(&xml_config
, "placeholder_for_data", kDistributionConfig
);
812 ReplaceString(&xml_config
,
813 "placeholder_for_id",
814 "abbaabbaabbaabbaabbaabbaabbaabba");
815 factory().SetFakeResponse(url
, xml_config
, net::HTTP_OK
,
816 net::URLRequestStatus::SUCCESS
);
818 scoped_ptr
<BrandcodeConfigFetcher
> fetcher
= WaitForRequest(GURL(url
));
819 scoped_ptr
<BrandcodedDefaultSettings
> settings
= fetcher
->GetSettings();
820 ASSERT_TRUE(settings
);
822 std::vector
<std::string
> extension_ids
;
823 EXPECT_TRUE(settings
->GetExtensions(&extension_ids
));
824 EXPECT_EQ(1u, extension_ids
.size());
825 EXPECT_EQ("abbaabbaabbaabbaabbaabbaabbaabba", extension_ids
[0]);
827 std::string homepage
;
828 EXPECT_TRUE(settings
->GetHomepage(&homepage
));
829 EXPECT_EQ("http://www.foo.com", homepage
);
831 scoped_ptr
<base::ListValue
> startup_list(
832 settings
->GetUrlsToRestoreOnStartup());
833 EXPECT_TRUE(startup_list
);
834 std::vector
<std::string
> startup_pages
;
835 for (base::ListValue::iterator i
= startup_list
->begin();
836 i
!= startup_list
->end(); ++i
) {
838 EXPECT_TRUE((*i
)->GetAsString(&url
));
839 startup_pages
.push_back(url
);
841 ASSERT_EQ(2u, startup_pages
.size());
842 EXPECT_EQ("http://goo.gl", startup_pages
[0]);
843 EXPECT_EQ("http://foo.de", startup_pages
[1]);
846 TEST_F(ProfileResetterTest
, CheckSnapshots
) {
847 ResettableSettingsSnapshot
empty_snap(profile());
848 EXPECT_EQ(0, empty_snap
.FindDifferentFields(empty_snap
));
850 scoped_refptr
<Extension
> ext
= CreateExtension(
851 base::ASCIIToUTF16("example"),
852 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
853 Manifest::INVALID_LOCATION
,
854 extensions::Manifest::TYPE_EXTENSION
,
856 ASSERT_TRUE(ext
.get());
857 service_
->AddExtension(ext
.get());
859 std::string
master_prefs(kDistributionConfig
);
860 std::string ext_id
= ext
->id();
861 ReplaceString(&master_prefs
, "placeholder_for_id", ext_id
);
863 // Reset to non organic defaults.
864 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
865 ProfileResetter::HOMEPAGE
|
866 ProfileResetter::STARTUP_PAGES
,
868 ShortcutHandler shortcut_hijacked
;
869 ShortcutCommand command_line
= shortcut_hijacked
.CreateWithArguments(
870 base::ASCIIToUTF16("chrome1.lnk"),
871 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
872 shortcut_hijacked
.CheckShortcutHasArguments(
873 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
874 ShortcutHandler shortcut_ok
;
875 shortcut_ok
.CreateWithArguments(
876 base::ASCIIToUTF16("chrome2.lnk"),
877 base::ASCIIToUTF16("--profile-directory=Default1"));
879 ResettableSettingsSnapshot
nonorganic_snap(profile());
880 nonorganic_snap
.RequestShortcuts(base::Closure());
881 // Let it enumerate shortcuts on the FILE thread.
882 base::MessageLoop::current()->RunUntilIdle();
883 int diff_fields
= ResettableSettingsSnapshot::ALL_FIELDS
;
884 if (!ShortcutHandler::IsSupported())
885 diff_fields
&= ~ResettableSettingsSnapshot::SHORTCUTS
;
886 EXPECT_EQ(diff_fields
,
887 empty_snap
.FindDifferentFields(nonorganic_snap
));
888 empty_snap
.Subtract(nonorganic_snap
);
889 EXPECT_TRUE(empty_snap
.startup_urls().empty());
890 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
891 empty_snap
.startup_type());
892 EXPECT_TRUE(empty_snap
.homepage().empty());
893 EXPECT_TRUE(empty_snap
.homepage_is_ntp());
894 EXPECT_FALSE(empty_snap
.show_home_button());
895 EXPECT_NE(std::string::npos
, empty_snap
.dse_url().find("{google:baseURL}"));
896 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(),
897 empty_snap
.enabled_extensions());
898 EXPECT_EQ(std::vector
<ShortcutCommand
>(), empty_snap
.shortcuts());
900 // Reset to organic defaults.
901 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
902 ProfileResetter::HOMEPAGE
|
903 ProfileResetter::STARTUP_PAGES
|
904 ProfileResetter::EXTENSIONS
|
905 ProfileResetter::SHORTCUTS
);
907 ResettableSettingsSnapshot
organic_snap(profile());
908 organic_snap
.RequestShortcuts(base::Closure());
909 // Let it enumerate shortcuts on the FILE thread.
910 base::MessageLoop::current()->RunUntilIdle();
911 EXPECT_EQ(diff_fields
, nonorganic_snap
.FindDifferentFields(organic_snap
));
912 nonorganic_snap
.Subtract(organic_snap
);
913 const GURL urls
[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
914 EXPECT_EQ(std::vector
<GURL
>(urls
, urls
+ arraysize(urls
)),
915 nonorganic_snap
.startup_urls());
916 EXPECT_EQ(SessionStartupPref::URLS
, nonorganic_snap
.startup_type());
917 EXPECT_EQ("http://www.foo.com", nonorganic_snap
.homepage());
918 EXPECT_FALSE(nonorganic_snap
.homepage_is_ntp());
919 EXPECT_TRUE(nonorganic_snap
.show_home_button());
920 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap
.dse_url());
921 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(
922 1, std::make_pair(ext_id
, "example")),
923 nonorganic_snap
.enabled_extensions());
924 if (ShortcutHandler::IsSupported()) {
925 std::vector
<ShortcutCommand
> shortcuts
= nonorganic_snap
.shortcuts();
926 ASSERT_EQ(1u, shortcuts
.size());
927 EXPECT_EQ(command_line
.first
.value(), shortcuts
[0].first
.value());
928 EXPECT_EQ(command_line
.second
, shortcuts
[0].second
);
932 TEST_F(ProfileResetterTest
, FeedbackSerializationTest
) {
933 // Reset to non organic defaults.
934 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE
|
935 ProfileResetter::HOMEPAGE
|
936 ProfileResetter::STARTUP_PAGES
,
937 kDistributionConfig
);
939 scoped_refptr
<Extension
> ext
= CreateExtension(
940 base::ASCIIToUTF16("example"),
941 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
942 Manifest::INVALID_LOCATION
,
943 extensions::Manifest::TYPE_EXTENSION
,
945 ASSERT_TRUE(ext
.get());
946 service_
->AddExtension(ext
.get());
948 ShortcutHandler shortcut
;
949 ShortcutCommand command_line
= shortcut
.CreateWithArguments(
950 base::ASCIIToUTF16("chrome.lnk"),
951 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
953 ResettableSettingsSnapshot
nonorganic_snap(profile());
954 nonorganic_snap
.RequestShortcuts(base::Closure());
955 // Let it enumerate shortcuts on the FILE thread.
956 base::MessageLoop::current()->RunUntilIdle();
958 static_assert(ResettableSettingsSnapshot::ALL_FIELDS
== 31,
959 "this test needs to be expanded");
960 for (int field_mask
= 0; field_mask
<= ResettableSettingsSnapshot::ALL_FIELDS
;
962 std::string report
= SerializeSettingsReport(nonorganic_snap
, field_mask
);
963 JSONStringValueSerializer
json(report
);
965 scoped_ptr
<base::Value
> root(json
.Deserialize(NULL
, &error
));
966 ASSERT_TRUE(root
) << error
;
967 ASSERT_TRUE(root
->IsType(base::Value::TYPE_DICTIONARY
)) << error
;
969 base::DictionaryValue
* dict
=
970 static_cast<base::DictionaryValue
*>(root
.get());
972 base::ListValue
* startup_urls
= NULL
;
973 int startup_type
= 0;
974 std::string homepage
;
975 bool homepage_is_ntp
= true;
976 bool show_home_button
= true;
977 std::string default_search_engine
;
978 base::ListValue
* extensions
= NULL
;
979 base::ListValue
* shortcuts
= NULL
;
981 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::STARTUP_MODE
),
982 dict
->GetList("startup_urls", &startup_urls
));
983 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::STARTUP_MODE
),
984 dict
->GetInteger("startup_type", &startup_type
));
985 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::HOMEPAGE
),
986 dict
->GetString("homepage", &homepage
));
987 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::HOMEPAGE
),
988 dict
->GetBoolean("homepage_is_ntp", &homepage_is_ntp
));
989 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::HOMEPAGE
),
990 dict
->GetBoolean("show_home_button", &show_home_button
));
991 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::DSE_URL
),
992 dict
->GetString("default_search_engine", &default_search_engine
));
993 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::EXTENSIONS
),
994 dict
->GetList("enabled_extensions", &extensions
));
995 EXPECT_EQ(!!(field_mask
& ResettableSettingsSnapshot::SHORTCUTS
),
996 dict
->GetList("shortcuts", &shortcuts
));
1000 struct FeedbackCapture
{
1001 void SetFeedback(Profile
* profile
,
1002 const ResettableSettingsSnapshot
& snapshot
) {
1003 list_
= GetReadableFeedbackForSnapshot(profile
, snapshot
).Pass();
1008 ADD_FAILURE() << "This method shouldn't be called.";
1011 MOCK_METHOD0(OnUpdatedList
, void(void));
1013 scoped_ptr
<base::ListValue
> list_
;
1016 // Make sure GetReadableFeedback handles non-ascii letters.
1017 TEST_F(ProfileResetterTest
, GetReadableFeedback
) {
1018 scoped_refptr
<Extension
> ext
= CreateExtension(
1019 base::WideToUTF16(L
"Tiësto"),
1020 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
1021 Manifest::INVALID_LOCATION
,
1022 extensions::Manifest::TYPE_EXTENSION
,
1024 ASSERT_TRUE(ext
.get());
1025 service_
->AddExtension(ext
.get());
1027 PrefService
* prefs
= profile()->GetPrefs();
1029 // The URL is "http://россия.рф".
1030 std::wstring
url(L
"http://"
1031 L
"\u0440\u043e\u0441\u0441\u0438\u044f.\u0440\u0444");
1032 prefs
->SetBoolean(prefs::kHomePageIsNewTabPage
, false);
1033 prefs
->SetString(prefs::kHomePage
, base::WideToUTF8(url
));
1035 SessionStartupPref
startup_pref(SessionStartupPref::URLS
);
1036 startup_pref
.urls
.push_back(GURL(base::WideToUTF8(url
)));
1037 SessionStartupPref::SetStartupPref(prefs
, startup_pref
);
1039 ShortcutHandler shortcut
;
1040 ShortcutCommand command_line
= shortcut
.CreateWithArguments(
1041 base::ASCIIToUTF16("chrome.lnk"),
1042 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
1044 FeedbackCapture capture
;
1045 EXPECT_CALL(capture
, OnUpdatedList());
1046 ResettableSettingsSnapshot
snapshot(profile());
1047 snapshot
.RequestShortcuts(base::Bind(&FeedbackCapture::SetFeedback
,
1048 base::Unretained(&capture
),
1050 base::ConstRef(snapshot
)));
1051 // Let it enumerate shortcuts on the FILE thread.
1052 base::MessageLoop::current()->RunUntilIdle();
1053 ::testing::Mock::VerifyAndClearExpectations(&capture
);
1054 // The homepage and the startup page are in punycode. They are unreadable.
1055 // Trying to find the extension name.
1056 scoped_ptr
<base::ListValue
> list
= capture
.list_
.Pass();
1058 bool checked_extensions
= false;
1059 bool checked_shortcuts
= false;
1060 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
1061 base::DictionaryValue
* dict
= NULL
;
1062 ASSERT_TRUE(list
->GetDictionary(i
, &dict
));
1064 ASSERT_TRUE(dict
->GetString("key", &value
));
1065 if (value
== "Extensions") {
1066 base::string16 extensions
;
1067 EXPECT_TRUE(dict
->GetString("value", &extensions
));
1068 EXPECT_EQ(base::WideToUTF16(L
"Tiësto"), extensions
);
1069 checked_extensions
= true;
1070 } else if (value
== "Shortcut targets") {
1071 base::string16 targets
;
1072 EXPECT_TRUE(dict
->GetString("value", &targets
));
1073 EXPECT_NE(base::string16::npos
,
1074 targets
.find(base::ASCIIToUTF16("foo.com"))) << targets
;
1075 checked_shortcuts
= true;
1078 EXPECT_TRUE(checked_extensions
);
1079 EXPECT_EQ(ShortcutHandler::IsSupported(), checked_shortcuts
);
1082 TEST_F(ProfileResetterTest
, DestroySnapshotFast
) {
1083 FeedbackCapture capture
;
1084 scoped_ptr
<ResettableSettingsSnapshot
> deleted_snapshot(
1085 new ResettableSettingsSnapshot(profile()));
1086 deleted_snapshot
->RequestShortcuts(base::Bind(&FeedbackCapture::Fail
,
1087 base::Unretained(&capture
)));
1088 deleted_snapshot
.reset();
1089 // Running remaining tasks shouldn't trigger the callback to be called as
1090 // |deleted_snapshot| was deleted before it could run.
1091 base::MessageLoop::current()->RunUntilIdle();