Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / profile_resetter / profile_resetter_unittest.cc
blobbafed456ad4cf028e8b16e20e91f7b279e4a318c
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/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_service_test_base.h"
14 #include "chrome/browser/extensions/tab_helper.h"
15 #include "chrome/browser/prefs/session_startup_pref.h"
16 #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h"
17 #include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
18 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
19 #include "chrome/browser/search_engines/template_url_service_factory.h"
20 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
21 #include "chrome/browser/themes/theme_service.h"
22 #include "chrome/browser/themes/theme_service_factory.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/browser/web_data_service_factory.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/test/base/browser_with_test_window_test.h"
27 #include "components/content_settings/core/browser/host_content_settings_map.h"
28 #include "components/search_engines/template_url_service.h"
29 #include "components/search_engines/template_url_service_client.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/test/test_browser_thread.h"
32 #include "extensions/browser/extension_registry.h"
33 #include "extensions/common/extension.h"
34 #include "extensions/common/manifest_constants.h"
35 #include "net/http/http_response_headers.h"
36 #include "net/http/http_status_code.h"
37 #include "net/url_request/test_url_fetcher_factory.h"
38 #include "net/url_request/url_request_status.h"
39 #include "url/gurl.h"
41 #if defined(OS_WIN)
42 #include "base/files/file_util.h"
43 #include "base/path_service.h"
44 #include "base/process/process_handle.h"
45 #include "base/rand_util.h"
46 #include "base/strings/string_number_conversions.h"
47 #include "base/win/scoped_com_initializer.h"
48 #include "base/win/shortcut.h"
49 #endif
52 namespace {
54 const char kDistributionConfig[] = "{"
55 " \"homepage\" : \"http://www.foo.com\","
56 " \"homepage_is_newtabpage\" : false,"
57 " \"browser\" : {"
58 " \"show_home_button\" : true"
59 " },"
60 " \"session\" : {"
61 " \"restore_on_startup\" : 4,"
62 " \"startup_urls\" : [\"http://goo.gl\", \"http://foo.de\"]"
63 " },"
64 " \"search_provider_overrides\" : ["
65 " {"
66 " \"name\" : \"first\","
67 " \"keyword\" : \"firstkey\","
68 " \"search_url\" : \"http://www.foo.com/s?q={searchTerms}\","
69 " \"favicon_url\" : \"http://www.foo.com/favicon.ico\","
70 " \"suggest_url\" : \"http://www.foo.com/s?q={searchTerms}\","
71 " \"encoding\" : \"UTF-8\","
72 " \"id\" : 1001"
73 " }"
74 " ],"
75 " \"extensions\" : {"
76 " \"settings\" : {"
77 " \"placeholder_for_id\": {"
78 " }"
79 " }"
80 " }"
81 "}";
83 const char kXmlConfig[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
84 "<response protocol=\"3.0\" server=\"prod\">"
85 "<app appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\" status=\"ok\">"
86 "<data index=\"skipfirstrunui-importsearch-defaultbrowser\" "
87 "name=\"install\" status=\"ok\">"
88 "placeholder_for_data"
89 "</data>"
90 "</app>"
91 "</response>";
93 using extensions::Extension;
94 using extensions::Manifest;
97 // ProfileResetterTest --------------------------------------------------------
99 // ProfileResetterTest sets up the extension, WebData and TemplateURL services.
100 class ProfileResetterTest : public extensions::ExtensionServiceTestBase,
101 public ProfileResetterTestBase {
102 public:
103 ProfileResetterTest();
104 ~ProfileResetterTest() override;
106 protected:
107 void SetUp() override;
109 TestingProfile* profile() { return profile_.get(); }
111 static scoped_ptr<KeyedService> CreateTemplateURLService(
112 content::BrowserContext* context);
114 private:
115 #if defined(OS_WIN)
116 base::ScopedPathOverride user_desktop_override_;
117 base::ScopedPathOverride app_dir_override_;
118 base::ScopedPathOverride start_menu_override_;
119 base::ScopedPathOverride taskbar_pins_override_;
120 base::win::ScopedCOMInitializer com_init_;
121 #endif
124 ProfileResetterTest::ProfileResetterTest()
125 #if defined(OS_WIN)
126 : user_desktop_override_(base::DIR_USER_DESKTOP),
127 app_dir_override_(base::DIR_APP_DATA),
128 start_menu_override_(base::DIR_START_MENU),
129 taskbar_pins_override_(base::DIR_TASKBAR_PINS)
130 #endif
133 ProfileResetterTest::~ProfileResetterTest() {
136 void ProfileResetterTest::SetUp() {
137 extensions::ExtensionServiceTestBase::SetUp();
138 InitializeEmptyExtensionService();
140 profile()->CreateWebDataService();
141 TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
142 profile(),
143 &ProfileResetterTest::CreateTemplateURLService);
144 resetter_.reset(new ProfileResetter(profile()));
147 // static
148 scoped_ptr<KeyedService> ProfileResetterTest::CreateTemplateURLService(
149 content::BrowserContext* context) {
150 Profile* profile = static_cast<Profile*>(context);
151 return make_scoped_ptr(new TemplateURLService(
152 profile->GetPrefs(),
153 scoped_ptr<SearchTermsData>(new UIThreadSearchTermsData(profile)),
154 WebDataServiceFactory::GetKeywordWebDataForProfile(
155 profile, ServiceAccessType::EXPLICIT_ACCESS),
156 scoped_ptr<TemplateURLServiceClient>(), NULL, NULL, base::Closure()));
160 // PinnedTabsResetTest --------------------------------------------------------
162 class PinnedTabsResetTest : public BrowserWithTestWindowTest,
163 public ProfileResetterTestBase {
164 protected:
165 void SetUp() override;
167 content::WebContents* CreateWebContents();
170 void PinnedTabsResetTest::SetUp() {
171 BrowserWithTestWindowTest::SetUp();
172 resetter_.reset(new ProfileResetter(profile()));
175 content::WebContents* PinnedTabsResetTest::CreateWebContents() {
176 return content::WebContents::Create(
177 content::WebContents::CreateParams(profile()));
181 // ConfigParserTest -----------------------------------------------------------
183 // URLFetcher delegate that simply records the upload data.
184 struct URLFetcherRequestListener : net::URLFetcherDelegate {
185 URLFetcherRequestListener();
186 ~URLFetcherRequestListener() override;
188 void OnURLFetchComplete(const net::URLFetcher* source) override;
190 std::string upload_data;
191 net::URLFetcherDelegate* real_delegate;
194 URLFetcherRequestListener::URLFetcherRequestListener()
195 : real_delegate(NULL) {
198 URLFetcherRequestListener::~URLFetcherRequestListener() {
201 void URLFetcherRequestListener::OnURLFetchComplete(
202 const net::URLFetcher* source) {
203 const net::TestURLFetcher* test_fetcher =
204 static_cast<const net::TestURLFetcher*>(source);
205 upload_data = test_fetcher->upload_data();
206 DCHECK(real_delegate);
207 real_delegate->OnURLFetchComplete(source);
210 class ConfigParserTest : public testing::Test {
211 protected:
212 ConfigParserTest();
213 virtual ~ConfigParserTest();
215 scoped_ptr<BrandcodeConfigFetcher> WaitForRequest(const GURL& url);
217 net::FakeURLFetcherFactory& factory() { return factory_; }
219 private:
220 scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
221 const GURL& url,
222 net::URLFetcherDelegate* fetcher_delegate,
223 const std::string& response_data,
224 net::HttpStatusCode response_code,
225 net::URLRequestStatus::Status status);
227 MOCK_METHOD0(Callback, void(void));
229 base::MessageLoopForIO loop_;
230 content::TestBrowserThread ui_thread_;
231 content::TestBrowserThread io_thread_;
232 URLFetcherRequestListener request_listener_;
233 net::FakeURLFetcherFactory factory_;
236 ConfigParserTest::ConfigParserTest()
237 : ui_thread_(content::BrowserThread::UI, &loop_),
238 io_thread_(content::BrowserThread::IO, &loop_),
239 factory_(NULL, base::Bind(&ConfigParserTest::CreateFakeURLFetcher,
240 base::Unretained(this))) {
243 ConfigParserTest::~ConfigParserTest() {}
245 scoped_ptr<BrandcodeConfigFetcher> ConfigParserTest::WaitForRequest(
246 const GURL& url) {
247 EXPECT_CALL(*this, Callback());
248 scoped_ptr<BrandcodeConfigFetcher> fetcher(
249 new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback,
250 base::Unretained(this)),
251 url,
252 "ABCD"));
253 base::MessageLoop::current()->RunUntilIdle();
254 EXPECT_FALSE(fetcher->IsActive());
255 // Look for the brand code in the request.
256 EXPECT_NE(std::string::npos, request_listener_.upload_data.find("ABCD"));
257 return fetcher.Pass();
260 scoped_ptr<net::FakeURLFetcher> ConfigParserTest::CreateFakeURLFetcher(
261 const GURL& url,
262 net::URLFetcherDelegate* fetcher_delegate,
263 const std::string& response_data,
264 net::HttpStatusCode response_code,
265 net::URLRequestStatus::Status status) {
266 request_listener_.real_delegate = fetcher_delegate;
267 scoped_ptr<net::FakeURLFetcher> fetcher(
268 new net::FakeURLFetcher(
269 url, &request_listener_, response_data, response_code, status));
270 scoped_refptr<net::HttpResponseHeaders> download_headers =
271 new net::HttpResponseHeaders("");
272 download_headers->AddHeader("Content-Type: text/xml");
273 fetcher->set_response_headers(download_headers);
274 return fetcher.Pass();
277 // A helper class to create/delete/check a Chrome desktop shortcut on Windows.
278 class ShortcutHandler {
279 public:
280 ShortcutHandler();
281 ~ShortcutHandler();
283 static bool IsSupported();
284 ShortcutCommand CreateWithArguments(const base::string16& name,
285 const base::string16& args);
286 void CheckShortcutHasArguments(const base::string16& desired_args) const;
287 void Delete();
289 private:
290 #if defined(OS_WIN)
291 base::FilePath shortcut_path_;
292 #endif
293 DISALLOW_COPY_AND_ASSIGN(ShortcutHandler);
296 #if defined(OS_WIN)
297 ShortcutHandler::ShortcutHandler() {
300 ShortcutHandler::~ShortcutHandler() {
301 if (!shortcut_path_.empty())
302 Delete();
305 // static
306 bool ShortcutHandler::IsSupported() {
307 return true;
310 ShortcutCommand ShortcutHandler::CreateWithArguments(
311 const base::string16& name,
312 const base::string16& args) {
313 EXPECT_TRUE(shortcut_path_.empty());
314 base::FilePath path_to_create;
315 EXPECT_TRUE(PathService::Get(base::DIR_USER_DESKTOP, &path_to_create));
316 path_to_create = path_to_create.Append(name);
317 EXPECT_FALSE(base::PathExists(path_to_create)) << path_to_create.value();
319 base::FilePath path_exe;
320 EXPECT_TRUE(PathService::Get(base::FILE_EXE, &path_exe));
321 base::win::ShortcutProperties shortcut_properties;
322 shortcut_properties.set_target(path_exe);
323 shortcut_properties.set_arguments(args);
324 EXPECT_TRUE(base::win::CreateOrUpdateShortcutLink(
325 path_to_create, shortcut_properties,
326 base::win::SHORTCUT_CREATE_ALWAYS)) << path_to_create.value();
327 shortcut_path_ = path_to_create;
328 return ShortcutCommand(shortcut_path_, args);
331 void ShortcutHandler::CheckShortcutHasArguments(
332 const base::string16& desired_args) const {
333 EXPECT_FALSE(shortcut_path_.empty());
334 base::string16 args;
335 EXPECT_TRUE(base::win::ResolveShortcut(shortcut_path_, NULL, &args));
336 EXPECT_EQ(desired_args, args);
339 void ShortcutHandler::Delete() {
340 EXPECT_FALSE(shortcut_path_.empty());
341 EXPECT_TRUE(base::DeleteFile(shortcut_path_, false));
342 shortcut_path_.clear();
344 #else
345 ShortcutHandler::ShortcutHandler() {}
347 ShortcutHandler::~ShortcutHandler() {}
349 // static
350 bool ShortcutHandler::IsSupported() {
351 return false;
354 ShortcutCommand ShortcutHandler::CreateWithArguments(
355 const base::string16& name,
356 const base::string16& args) {
357 return ShortcutCommand();
360 void ShortcutHandler::CheckShortcutHasArguments(
361 const base::string16& desired_args) const {
364 void ShortcutHandler::Delete() {
366 #endif // defined(OS_WIN)
369 // helper functions -----------------------------------------------------------
371 scoped_refptr<Extension> CreateExtension(const base::string16& name,
372 const base::FilePath& path,
373 Manifest::Location location,
374 extensions::Manifest::Type type,
375 bool installed_by_default) {
376 base::DictionaryValue manifest;
377 manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
378 manifest.SetString(extensions::manifest_keys::kName, name);
379 switch (type) {
380 case extensions::Manifest::TYPE_THEME:
381 manifest.Set(extensions::manifest_keys::kTheme,
382 new base::DictionaryValue);
383 break;
384 case extensions::Manifest::TYPE_HOSTED_APP:
385 manifest.SetString(extensions::manifest_keys::kLaunchWebURL,
386 "http://www.google.com");
387 manifest.SetString(extensions::manifest_keys::kUpdateURL,
388 "http://clients2.google.com/service/update2/crx");
389 break;
390 case extensions::Manifest::TYPE_EXTENSION:
391 // do nothing
392 break;
393 default:
394 NOTREACHED();
396 manifest.SetString(extensions::manifest_keys::kOmniboxKeyword, name);
397 std::string error;
398 scoped_refptr<Extension> extension = Extension::Create(
399 path,
400 location,
401 manifest,
402 installed_by_default ? Extension::WAS_INSTALLED_BY_DEFAULT
403 : Extension::NO_FLAGS,
404 &error);
405 EXPECT_TRUE(extension.get() != NULL) << error;
406 return extension;
409 void ReplaceString(std::string* str,
410 const std::string& placeholder,
411 const std::string& substitution) {
412 ASSERT_NE(static_cast<std::string*>(NULL), str);
413 size_t placeholder_pos = str->find(placeholder);
414 ASSERT_NE(std::string::npos, placeholder_pos);
415 str->replace(placeholder_pos, placeholder.size(), substitution);
419 /********************* Tests *********************/
421 TEST_F(ProfileResetterTest, ResetNothing) {
422 // The callback should be called even if there is nothing to reset.
423 ResetAndWait(0);
426 TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) {
427 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE, kDistributionConfig);
429 TemplateURLService* model =
430 TemplateURLServiceFactory::GetForProfile(profile());
431 TemplateURL* default_engine = model->GetDefaultSearchProvider();
432 ASSERT_NE(static_cast<TemplateURL*>(NULL), default_engine);
433 EXPECT_EQ(base::ASCIIToUTF16("first"), default_engine->short_name());
434 EXPECT_EQ(base::ASCIIToUTF16("firstkey"), default_engine->keyword());
435 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", default_engine->url());
438 TEST_F(ProfileResetterTest, ResetDefaultSearchEnginePartially) {
439 // Search engine's logic is tested by
440 // TemplateURLServiceTest.RepairPrepopulatedSearchEngines.
441 // Make sure TemplateURLService has loaded.
442 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);
444 TemplateURLService* model =
445 TemplateURLServiceFactory::GetForProfile(profile());
446 TemplateURLService::TemplateURLVector urls = model->GetTemplateURLs();
448 // The second call should produce no effect.
449 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);
451 EXPECT_EQ(urls, model->GetTemplateURLs());
454 TEST_F(ProfileResetterTest, ResetHomepageNonOrganic) {
455 PrefService* prefs = profile()->GetPrefs();
456 DCHECK(prefs);
457 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, true);
458 prefs->SetString(prefs::kHomePage, "http://google.com");
459 prefs->SetBoolean(prefs::kShowHomeButton, false);
461 ResetAndWait(ProfileResetter::HOMEPAGE, kDistributionConfig);
463 EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
464 EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
465 EXPECT_TRUE(prefs->GetBoolean(prefs::kShowHomeButton));
468 TEST_F(ProfileResetterTest, ResetHomepagePartially) {
469 PrefService* prefs = profile()->GetPrefs();
470 DCHECK(prefs);
471 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
472 prefs->SetString(prefs::kHomePage, "http://www.foo.com");
473 prefs->SetBoolean(prefs::kShowHomeButton, true);
475 ResetAndWait(ProfileResetter::HOMEPAGE);
477 EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
478 EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
479 EXPECT_FALSE(prefs->GetBoolean(prefs::kShowHomeButton));
482 TEST_F(ProfileResetterTest, ResetContentSettings) {
483 HostContentSettingsMap* host_content_settings_map =
484 profile()->GetHostContentSettingsMap();
485 ContentSettingsPattern pattern =
486 ContentSettingsPattern::FromString("[*.]example.org");
487 std::map<ContentSettingsType, ContentSetting> default_settings;
489 for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
490 ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
491 if (content_type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
492 content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
493 content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
494 // These types are excluded because one can't call
495 // GetDefaultContentSetting() for them.
496 continue;
498 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
499 // This has been deprecated so we can neither set nor get it's value.
500 continue;
502 ContentSetting default_setting =
503 host_content_settings_map->GetDefaultContentSetting(content_type, NULL);
504 default_settings[content_type] = default_setting;
505 ContentSetting wildcard_setting = default_setting == CONTENT_SETTING_BLOCK
506 ? CONTENT_SETTING_ALLOW
507 : CONTENT_SETTING_BLOCK;
508 ContentSetting site_setting = default_setting == CONTENT_SETTING_ALLOW
509 ? CONTENT_SETTING_ALLOW
510 : CONTENT_SETTING_BLOCK;
511 if (HostContentSettingsMap::IsSettingAllowedForType(
512 profile()->GetPrefs(), wildcard_setting, content_type)) {
513 host_content_settings_map->SetDefaultContentSetting(content_type,
514 wildcard_setting);
516 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) &&
517 HostContentSettingsMap::IsSettingAllowedForType(
518 profile()->GetPrefs(), site_setting, content_type)) {
519 host_content_settings_map->SetContentSetting(
520 pattern, ContentSettingsPattern::Wildcard(), content_type,
521 std::string(), site_setting);
522 ContentSettingsForOneType host_settings;
523 host_content_settings_map->GetSettingsForOneType(
524 content_type, std::string(), &host_settings);
525 EXPECT_EQ(2U, host_settings.size());
529 ResetAndWait(ProfileResetter::CONTENT_SETTINGS);
531 for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
532 ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
533 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) ||
534 content_type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
535 content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
536 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
537 content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS)
538 continue;
539 ContentSetting default_setting =
540 host_content_settings_map->GetDefaultContentSetting(content_type,
541 NULL);
542 EXPECT_TRUE(default_settings.count(content_type));
543 EXPECT_EQ(default_settings[content_type], default_setting);
544 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
545 ContentSetting site_setting =
546 host_content_settings_map->GetContentSetting(
547 GURL("example.org"),
548 GURL(),
549 content_type,
550 std::string());
551 EXPECT_EQ(default_setting, site_setting);
554 ContentSettingsForOneType host_settings;
555 host_content_settings_map->GetSettingsForOneType(
556 content_type, std::string(), &host_settings);
557 EXPECT_EQ(1U, host_settings.size());
561 TEST_F(ProfileResetterTest, ResetExtensionsByDisabling) {
562 service_->Init();
564 base::ScopedTempDir temp_dir;
565 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
567 scoped_refptr<Extension> theme =
568 CreateExtension(base::ASCIIToUTF16("example1"),
569 temp_dir.path(),
570 Manifest::INVALID_LOCATION,
571 extensions::Manifest::TYPE_THEME,
572 false);
573 service_->FinishInstallationForTest(theme.get());
574 // Let ThemeService finish creating the theme pack.
575 base::MessageLoop::current()->RunUntilIdle();
577 ThemeService* theme_service =
578 ThemeServiceFactory::GetForProfile(profile());
579 EXPECT_FALSE(theme_service->UsingDefaultTheme());
581 scoped_refptr<Extension> ext2 = CreateExtension(
582 base::ASCIIToUTF16("example2"),
583 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
584 Manifest::INVALID_LOCATION,
585 extensions::Manifest::TYPE_EXTENSION,
586 false);
587 service_->AddExtension(ext2.get());
588 // Component extensions and policy-managed extensions shouldn't be disabled.
589 scoped_refptr<Extension> ext3 = CreateExtension(
590 base::ASCIIToUTF16("example3"),
591 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
592 Manifest::COMPONENT,
593 extensions::Manifest::TYPE_EXTENSION,
594 false);
595 service_->AddExtension(ext3.get());
596 scoped_refptr<Extension> ext4 =
597 CreateExtension(base::ASCIIToUTF16("example4"),
598 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
599 Manifest::EXTERNAL_POLICY_DOWNLOAD,
600 extensions::Manifest::TYPE_EXTENSION,
601 false);
602 service_->AddExtension(ext4.get());
603 scoped_refptr<Extension> ext5 = CreateExtension(
604 base::ASCIIToUTF16("example5"),
605 base::FilePath(FILE_PATH_LITERAL("//nonexistent4")),
606 Manifest::EXTERNAL_COMPONENT,
607 extensions::Manifest::TYPE_EXTENSION,
608 false);
609 service_->AddExtension(ext5.get());
610 scoped_refptr<Extension> ext6 = CreateExtension(
611 base::ASCIIToUTF16("example6"),
612 base::FilePath(FILE_PATH_LITERAL("//nonexistent5")),
613 Manifest::EXTERNAL_POLICY,
614 extensions::Manifest::TYPE_EXTENSION,
615 false);
616 service_->AddExtension(ext6.get());
617 EXPECT_EQ(6u, registry()->enabled_extensions().size());
619 ResetAndWait(ProfileResetter::EXTENSIONS);
620 EXPECT_EQ(4u, registry()->enabled_extensions().size());
621 EXPECT_FALSE(registry()->enabled_extensions().Contains(theme->id()));
622 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2->id()));
623 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3->id()));
624 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext4->id()));
625 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext5->id()));
626 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext6->id()));
627 EXPECT_TRUE(theme_service->UsingDefaultTheme());
630 TEST_F(ProfileResetterTest, ResetExtensionsByDisablingNonOrganic) {
631 scoped_refptr<Extension> ext2 = CreateExtension(
632 base::ASCIIToUTF16("example2"),
633 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
634 Manifest::INVALID_LOCATION,
635 extensions::Manifest::TYPE_EXTENSION,
636 false);
637 service_->AddExtension(ext2.get());
638 // Components and external policy extensions shouldn't be deleted.
639 scoped_refptr<Extension> ext3 = CreateExtension(
640 base::ASCIIToUTF16("example3"),
641 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
642 Manifest::INVALID_LOCATION,
643 extensions::Manifest::TYPE_EXTENSION,
644 false);
645 service_->AddExtension(ext3.get());
646 EXPECT_EQ(2u, registry()->enabled_extensions().size());
648 std::string master_prefs(kDistributionConfig);
649 ReplaceString(&master_prefs, "placeholder_for_id", ext3->id());
651 ResetAndWait(ProfileResetter::EXTENSIONS, master_prefs);
653 EXPECT_EQ(1u, registry()->enabled_extensions().size());
654 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3->id()));
657 TEST_F(ProfileResetterTest, ResetExtensionsAndDefaultApps) {
658 service_->Init();
660 base::ScopedTempDir temp_dir;
661 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
663 scoped_refptr<Extension> ext1 =
664 CreateExtension(base::ASCIIToUTF16("example1"),
665 temp_dir.path(),
666 Manifest::INVALID_LOCATION,
667 extensions::Manifest::TYPE_THEME,
668 false);
669 service_->FinishInstallationForTest(ext1.get());
670 // Let ThemeService finish creating the theme pack.
671 base::MessageLoop::current()->RunUntilIdle();
673 ThemeService* theme_service =
674 ThemeServiceFactory::GetForProfile(profile());
675 EXPECT_FALSE(theme_service->UsingDefaultTheme());
677 scoped_refptr<Extension> ext2 =
678 CreateExtension(base::ASCIIToUTF16("example2"),
679 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
680 Manifest::INVALID_LOCATION,
681 extensions::Manifest::TYPE_EXTENSION,
682 false);
683 service_->AddExtension(ext2.get());
685 scoped_refptr<Extension> ext3 =
686 CreateExtension(base::ASCIIToUTF16("example2"),
687 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
688 Manifest::INVALID_LOCATION,
689 extensions::Manifest::TYPE_HOSTED_APP,
690 true);
691 service_->AddExtension(ext3.get());
692 EXPECT_EQ(3u, registry()->enabled_extensions().size());
694 ResetAndWait(ProfileResetter::EXTENSIONS);
696 EXPECT_EQ(1u, registry()->enabled_extensions().size());
697 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext1->id()));
698 EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2->id()));
699 EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3->id()));
700 EXPECT_TRUE(theme_service->UsingDefaultTheme());
703 TEST_F(ProfileResetterTest, ResetStartPageNonOrganic) {
704 PrefService* prefs = profile()->GetPrefs();
705 DCHECK(prefs);
707 SessionStartupPref startup_pref(SessionStartupPref::LAST);
708 SessionStartupPref::SetStartupPref(prefs, startup_pref);
710 ResetAndWait(ProfileResetter::STARTUP_PAGES, kDistributionConfig);
712 startup_pref = SessionStartupPref::GetStartupPref(prefs);
713 EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type);
714 const GURL urls[] = {GURL("http://goo.gl"), GURL("http://foo.de")};
715 EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls);
719 TEST_F(ProfileResetterTest, ResetStartPagePartially) {
720 PrefService* prefs = profile()->GetPrefs();
721 DCHECK(prefs);
723 const GURL urls[] = {GURL("http://foo"), GURL("http://bar")};
724 SessionStartupPref startup_pref(SessionStartupPref::URLS);
725 startup_pref.urls.assign(urls, urls + arraysize(urls));
726 SessionStartupPref::SetStartupPref(prefs, startup_pref);
728 ResetAndWait(ProfileResetter::STARTUP_PAGES, std::string());
730 startup_pref = SessionStartupPref::GetStartupPref(prefs);
731 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref.type);
732 EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls);
735 TEST_F(PinnedTabsResetTest, ResetPinnedTabs) {
736 scoped_ptr<content::WebContents> contents1(CreateWebContents());
737 scoped_ptr<content::WebContents> contents2(CreateWebContents());
738 scoped_ptr<content::WebContents> contents3(CreateWebContents());
739 scoped_ptr<content::WebContents> contents4(CreateWebContents());
740 TabStripModel* tab_strip_model = browser()->tab_strip_model();
742 tab_strip_model->AppendWebContents(contents4.get(), true);
743 tab_strip_model->AppendWebContents(contents3.get(), true);
744 tab_strip_model->AppendWebContents(contents2.get(), true);
745 tab_strip_model->SetTabPinned(2, true);
746 tab_strip_model->AppendWebContents(contents1.get(), true);
747 tab_strip_model->SetTabPinned(3, true);
749 EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(0));
750 EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(1));
751 EXPECT_EQ(contents4, tab_strip_model->GetWebContentsAt(2));
752 EXPECT_EQ(contents3, tab_strip_model->GetWebContentsAt(3));
753 EXPECT_EQ(2, tab_strip_model->IndexOfFirstNonPinnedTab());
755 ResetAndWait(ProfileResetter::PINNED_TABS);
757 EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(0));
758 EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(1));
759 EXPECT_EQ(contents4, tab_strip_model->GetWebContentsAt(2));
760 EXPECT_EQ(contents3, tab_strip_model->GetWebContentsAt(3));
761 EXPECT_EQ(0, tab_strip_model->IndexOfFirstNonPinnedTab());
764 TEST_F(ProfileResetterTest, ResetShortcuts) {
765 ShortcutHandler shortcut;
766 ShortcutCommand command_line = shortcut.CreateWithArguments(
767 base::ASCIIToUTF16("chrome.lnk"),
768 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
769 shortcut.CheckShortcutHasArguments(base::ASCIIToUTF16(
770 "--profile-directory=Default foo.com"));
772 ResetAndWait(ProfileResetter::SHORTCUTS);
774 shortcut.CheckShortcutHasArguments(base::ASCIIToUTF16(
775 "--profile-directory=Default"));
778 TEST_F(ProfileResetterTest, ResetFewFlags) {
779 // mock_object_ is a StrictMock, so we verify that it is called only once.
780 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
781 ProfileResetter::HOMEPAGE |
782 ProfileResetter::CONTENT_SETTINGS);
785 // Tries to load unavailable config file.
786 TEST_F(ConfigParserTest, NoConnectivity) {
787 const GURL url("http://test");
788 factory().SetFakeResponse(url, "", net::HTTP_INTERNAL_SERVER_ERROR,
789 net::URLRequestStatus::FAILED);
791 scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
792 EXPECT_FALSE(fetcher->GetSettings());
795 // Tries to load available config file.
796 TEST_F(ConfigParserTest, ParseConfig) {
797 const GURL url("http://test");
798 std::string xml_config(kXmlConfig);
799 ReplaceString(&xml_config, "placeholder_for_data", kDistributionConfig);
800 ReplaceString(&xml_config,
801 "placeholder_for_id",
802 "abbaabbaabbaabbaabbaabbaabbaabba");
803 factory().SetFakeResponse(url, xml_config, net::HTTP_OK,
804 net::URLRequestStatus::SUCCESS);
806 scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
807 scoped_ptr<BrandcodedDefaultSettings> settings = fetcher->GetSettings();
808 ASSERT_TRUE(settings);
810 std::vector<std::string> extension_ids;
811 EXPECT_TRUE(settings->GetExtensions(&extension_ids));
812 EXPECT_EQ(1u, extension_ids.size());
813 EXPECT_EQ("abbaabbaabbaabbaabbaabbaabbaabba", extension_ids[0]);
815 std::string homepage;
816 EXPECT_TRUE(settings->GetHomepage(&homepage));
817 EXPECT_EQ("http://www.foo.com", homepage);
819 scoped_ptr<base::ListValue> startup_list(
820 settings->GetUrlsToRestoreOnStartup());
821 EXPECT_TRUE(startup_list);
822 std::vector<std::string> startup_pages;
823 for (base::ListValue::iterator i = startup_list->begin();
824 i != startup_list->end(); ++i) {
825 std::string url;
826 EXPECT_TRUE((*i)->GetAsString(&url));
827 startup_pages.push_back(url);
829 ASSERT_EQ(2u, startup_pages.size());
830 EXPECT_EQ("http://goo.gl", startup_pages[0]);
831 EXPECT_EQ("http://foo.de", startup_pages[1]);
834 TEST_F(ProfileResetterTest, CheckSnapshots) {
835 ResettableSettingsSnapshot empty_snap(profile());
836 EXPECT_EQ(0, empty_snap.FindDifferentFields(empty_snap));
838 scoped_refptr<Extension> ext = CreateExtension(
839 base::ASCIIToUTF16("example"),
840 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
841 Manifest::INVALID_LOCATION,
842 extensions::Manifest::TYPE_EXTENSION,
843 false);
844 ASSERT_TRUE(ext.get());
845 service_->AddExtension(ext.get());
847 std::string master_prefs(kDistributionConfig);
848 std::string ext_id = ext->id();
849 ReplaceString(&master_prefs, "placeholder_for_id", ext_id);
851 // Reset to non organic defaults.
852 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
853 ProfileResetter::HOMEPAGE |
854 ProfileResetter::STARTUP_PAGES,
855 master_prefs);
856 ShortcutHandler shortcut_hijacked;
857 ShortcutCommand command_line = shortcut_hijacked.CreateWithArguments(
858 base::ASCIIToUTF16("chrome1.lnk"),
859 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
860 shortcut_hijacked.CheckShortcutHasArguments(
861 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
862 ShortcutHandler shortcut_ok;
863 shortcut_ok.CreateWithArguments(
864 base::ASCIIToUTF16("chrome2.lnk"),
865 base::ASCIIToUTF16("--profile-directory=Default1"));
867 ResettableSettingsSnapshot nonorganic_snap(profile());
868 nonorganic_snap.RequestShortcuts(base::Closure());
869 // Let it enumerate shortcuts on the FILE thread.
870 base::MessageLoop::current()->RunUntilIdle();
871 int diff_fields = ResettableSettingsSnapshot::ALL_FIELDS;
872 if (!ShortcutHandler::IsSupported())
873 diff_fields &= ~ResettableSettingsSnapshot::SHORTCUTS;
874 EXPECT_EQ(diff_fields,
875 empty_snap.FindDifferentFields(nonorganic_snap));
876 empty_snap.Subtract(nonorganic_snap);
877 EXPECT_TRUE(empty_snap.startup_urls().empty());
878 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
879 empty_snap.startup_type());
880 EXPECT_TRUE(empty_snap.homepage().empty());
881 EXPECT_TRUE(empty_snap.homepage_is_ntp());
882 EXPECT_FALSE(empty_snap.show_home_button());
883 EXPECT_NE(std::string::npos, empty_snap.dse_url().find("{google:baseURL}"));
884 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(),
885 empty_snap.enabled_extensions());
886 EXPECT_EQ(std::vector<ShortcutCommand>(), empty_snap.shortcuts());
888 // Reset to organic defaults.
889 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
890 ProfileResetter::HOMEPAGE |
891 ProfileResetter::STARTUP_PAGES |
892 ProfileResetter::EXTENSIONS |
893 ProfileResetter::SHORTCUTS);
895 ResettableSettingsSnapshot organic_snap(profile());
896 organic_snap.RequestShortcuts(base::Closure());
897 // Let it enumerate shortcuts on the FILE thread.
898 base::MessageLoop::current()->RunUntilIdle();
899 EXPECT_EQ(diff_fields, nonorganic_snap.FindDifferentFields(organic_snap));
900 nonorganic_snap.Subtract(organic_snap);
901 const GURL urls[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
902 EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)),
903 nonorganic_snap.startup_urls());
904 EXPECT_EQ(SessionStartupPref::URLS, nonorganic_snap.startup_type());
905 EXPECT_EQ("http://www.foo.com", nonorganic_snap.homepage());
906 EXPECT_FALSE(nonorganic_snap.homepage_is_ntp());
907 EXPECT_TRUE(nonorganic_snap.show_home_button());
908 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap.dse_url());
909 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(
910 1, std::make_pair(ext_id, "example")),
911 nonorganic_snap.enabled_extensions());
912 if (ShortcutHandler::IsSupported()) {
913 std::vector<ShortcutCommand> shortcuts = nonorganic_snap.shortcuts();
914 ASSERT_EQ(1u, shortcuts.size());
915 EXPECT_EQ(command_line.first.value(), shortcuts[0].first.value());
916 EXPECT_EQ(command_line.second, shortcuts[0].second);
920 TEST_F(ProfileResetterTest, FeedbackSerializationTest) {
921 // Reset to non organic defaults.
922 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
923 ProfileResetter::HOMEPAGE |
924 ProfileResetter::STARTUP_PAGES,
925 kDistributionConfig);
927 scoped_refptr<Extension> ext = CreateExtension(
928 base::ASCIIToUTF16("example"),
929 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
930 Manifest::INVALID_LOCATION,
931 extensions::Manifest::TYPE_EXTENSION,
932 false);
933 ASSERT_TRUE(ext.get());
934 service_->AddExtension(ext.get());
936 ShortcutHandler shortcut;
937 ShortcutCommand command_line = shortcut.CreateWithArguments(
938 base::ASCIIToUTF16("chrome.lnk"),
939 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
941 ResettableSettingsSnapshot nonorganic_snap(profile());
942 nonorganic_snap.RequestShortcuts(base::Closure());
943 // Let it enumerate shortcuts on the FILE thread.
944 base::MessageLoop::current()->RunUntilIdle();
946 static_assert(ResettableSettingsSnapshot::ALL_FIELDS == 31,
947 "this test needs to be expanded");
948 for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS;
949 ++field_mask) {
950 std::string report = SerializeSettingsReport(nonorganic_snap, field_mask);
951 JSONStringValueDeserializer json(report);
952 std::string error;
953 scoped_ptr<base::Value> root(json.Deserialize(NULL, &error));
954 ASSERT_TRUE(root) << error;
955 ASSERT_TRUE(root->IsType(base::Value::TYPE_DICTIONARY)) << error;
957 base::DictionaryValue* dict =
958 static_cast<base::DictionaryValue*>(root.get());
960 base::ListValue* startup_urls = NULL;
961 int startup_type = 0;
962 std::string homepage;
963 bool homepage_is_ntp = true;
964 bool show_home_button = true;
965 std::string default_search_engine;
966 base::ListValue* extensions = NULL;
967 base::ListValue* shortcuts = NULL;
969 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
970 dict->GetList("startup_urls", &startup_urls));
971 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
972 dict->GetInteger("startup_type", &startup_type));
973 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
974 dict->GetString("homepage", &homepage));
975 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
976 dict->GetBoolean("homepage_is_ntp", &homepage_is_ntp));
977 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
978 dict->GetBoolean("show_home_button", &show_home_button));
979 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL),
980 dict->GetString("default_search_engine", &default_search_engine));
981 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::EXTENSIONS),
982 dict->GetList("enabled_extensions", &extensions));
983 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::SHORTCUTS),
984 dict->GetList("shortcuts", &shortcuts));
988 struct FeedbackCapture {
989 void SetFeedback(Profile* profile,
990 const ResettableSettingsSnapshot& snapshot) {
991 list_ = GetReadableFeedbackForSnapshot(profile, snapshot).Pass();
992 OnUpdatedList();
995 void Fail() {
996 ADD_FAILURE() << "This method shouldn't be called.";
999 MOCK_METHOD0(OnUpdatedList, void(void));
1001 scoped_ptr<base::ListValue> list_;
1004 // Make sure GetReadableFeedback handles non-ascii letters.
1005 TEST_F(ProfileResetterTest, GetReadableFeedback) {
1006 scoped_refptr<Extension> ext = CreateExtension(
1007 base::WideToUTF16(L"Tiësto"),
1008 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
1009 Manifest::INVALID_LOCATION,
1010 extensions::Manifest::TYPE_EXTENSION,
1011 false);
1012 ASSERT_TRUE(ext.get());
1013 service_->AddExtension(ext.get());
1015 PrefService* prefs = profile()->GetPrefs();
1016 DCHECK(prefs);
1017 // The URL is "http://россия.рф".
1018 std::wstring url(L"http://"
1019 L"\u0440\u043e\u0441\u0441\u0438\u044f.\u0440\u0444");
1020 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
1021 prefs->SetString(prefs::kHomePage, base::WideToUTF8(url));
1023 SessionStartupPref startup_pref(SessionStartupPref::URLS);
1024 startup_pref.urls.push_back(GURL(base::WideToUTF8(url)));
1025 SessionStartupPref::SetStartupPref(prefs, startup_pref);
1027 ShortcutHandler shortcut;
1028 ShortcutCommand command_line = shortcut.CreateWithArguments(
1029 base::ASCIIToUTF16("chrome.lnk"),
1030 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
1032 FeedbackCapture capture;
1033 EXPECT_CALL(capture, OnUpdatedList());
1034 ResettableSettingsSnapshot snapshot(profile());
1035 snapshot.RequestShortcuts(base::Bind(&FeedbackCapture::SetFeedback,
1036 base::Unretained(&capture),
1037 profile(),
1038 base::ConstRef(snapshot)));
1039 // Let it enumerate shortcuts on the FILE thread.
1040 base::MessageLoop::current()->RunUntilIdle();
1041 ::testing::Mock::VerifyAndClearExpectations(&capture);
1042 // The homepage and the startup page are in punycode. They are unreadable.
1043 // Trying to find the extension name.
1044 scoped_ptr<base::ListValue> list = capture.list_.Pass();
1045 ASSERT_TRUE(list);
1046 bool checked_extensions = false;
1047 bool checked_shortcuts = false;
1048 for (size_t i = 0; i < list->GetSize(); ++i) {
1049 base::DictionaryValue* dict = NULL;
1050 ASSERT_TRUE(list->GetDictionary(i, &dict));
1051 std::string value;
1052 ASSERT_TRUE(dict->GetString("key", &value));
1053 if (value == "Extensions") {
1054 base::string16 extensions;
1055 EXPECT_TRUE(dict->GetString("value", &extensions));
1056 EXPECT_EQ(base::WideToUTF16(L"Tiësto"), extensions);
1057 checked_extensions = true;
1058 } else if (value == "Shortcut targets") {
1059 base::string16 targets;
1060 EXPECT_TRUE(dict->GetString("value", &targets));
1061 EXPECT_NE(base::string16::npos,
1062 targets.find(base::ASCIIToUTF16("foo.com"))) << targets;
1063 checked_shortcuts = true;
1066 EXPECT_TRUE(checked_extensions);
1067 EXPECT_EQ(ShortcutHandler::IsSupported(), checked_shortcuts);
1070 TEST_F(ProfileResetterTest, DestroySnapshotFast) {
1071 FeedbackCapture capture;
1072 scoped_ptr<ResettableSettingsSnapshot> deleted_snapshot(
1073 new ResettableSettingsSnapshot(profile()));
1074 deleted_snapshot->RequestShortcuts(base::Bind(&FeedbackCapture::Fail,
1075 base::Unretained(&capture)));
1076 deleted_snapshot.reset();
1077 // Running remaining tasks shouldn't trigger the callback to be called as
1078 // |deleted_snapshot| was deleted before it could run.
1079 base::MessageLoop::current()->RunUntilIdle();
1082 } // namespace