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.
4
5 #include "chrome/browser/profile_resetter/profile_resetter.h"
6
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/content_settings/host_content_settings_map.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/webdata/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/google/core/browser/google_pref_names.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/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"
38 #include "url/gurl.h"
39
40 #if defined(OS_WIN)
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"
48 #endif
49
50
51 namespace {
52
53 const char kDistributionConfig[] = "{"
54 " \"homepage\" : \"http://www.foo.com\","
55 " \"homepage_is_newtabpage\" : false,"
56 " \"browser\" : {"
57 " \"show_home_button\" : true"
58 " },"
59 " \"session\" : {"
60 " \"restore_on_startup\" : 4,"
61 " \"startup_urls\" : [\"http://goo.gl\", \"http://foo.de\"]"
62 " },"
63 " \"search_provider_overrides\" : ["
64 " {"
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\","
71 " \"id\" : 1001"
72 " }"
73 " ],"
74 " \"extensions\" : {"
75 " \"settings\" : {"
76 " \"placeholder_for_id\": {"
77 " }"
78 " }"
79 " }"
80 "}";
81
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"
88 "</data>"
89 "</app>"
90 "</response>";
91
92 using extensions::Extension;
93 using extensions::Manifest;
94
95
96 // ProfileResetterTest --------------------------------------------------------
97
98 // ProfileResetterTest sets up the extension, WebData and TemplateURL services.
99 class ProfileResetterTest : public extensions::ExtensionServiceTestBase,
100 public ProfileResetterTestBase {
101 public:
102 ProfileResetterTest();
103 virtual ~ProfileResetterTest();
104
105 protected:
106 virtual void SetUp() OVERRIDE;
107
profile()108 TestingProfile* profile() { return profile_.get(); }
109
110 static KeyedService* CreateTemplateURLService(
111 content::BrowserContext* context);
112
113 private:
114 #if defined(OS_WIN)
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_;
120 #endif
121 };
122
ProfileResetterTest()123 ProfileResetterTest::ProfileResetterTest()
124 #if defined(OS_WIN)
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)
129 #endif
130 {}
131
~ProfileResetterTest()132 ProfileResetterTest::~ProfileResetterTest() {
133 }
134
SetUp()135 void ProfileResetterTest::SetUp() {
136 extensions::ExtensionServiceTestBase::SetUp();
137 InitializeEmptyExtensionService();
138
139 profile()->CreateWebDataService();
140 TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
141 profile(),
142 &ProfileResetterTest::CreateTemplateURLService);
143 resetter_.reset(new ProfileResetter(profile()));
144 }
145
146 // static
CreateTemplateURLService(content::BrowserContext * context)147 KeyedService* ProfileResetterTest::CreateTemplateURLService(
148 content::BrowserContext* context) {
149 Profile* profile = static_cast<Profile*>(context);
150 return new TemplateURLService(
151 profile->GetPrefs(),
152 scoped_ptr<SearchTermsData>(new UIThreadSearchTermsData(profile)),
153 WebDataServiceFactory::GetKeywordWebDataForProfile(
154 profile, Profile::EXPLICIT_ACCESS),
155 scoped_ptr<TemplateURLServiceClient>(), NULL, NULL, base::Closure());
156 }
157
158
159 // PinnedTabsResetTest --------------------------------------------------------
160
161 class PinnedTabsResetTest : public BrowserWithTestWindowTest,
162 public ProfileResetterTestBase {
163 protected:
164 virtual void SetUp() OVERRIDE;
165
166 content::WebContents* CreateWebContents();
167 };
168
SetUp()169 void PinnedTabsResetTest::SetUp() {
170 BrowserWithTestWindowTest::SetUp();
171 resetter_.reset(new ProfileResetter(profile()));
172 }
173
CreateWebContents()174 content::WebContents* PinnedTabsResetTest::CreateWebContents() {
175 return content::WebContents::Create(
176 content::WebContents::CreateParams(profile()));
177 }
178
179
180 // ConfigParserTest -----------------------------------------------------------
181
182 // URLFetcher delegate that simply records the upload data.
183 struct URLFetcherRequestListener : net::URLFetcherDelegate {
184 URLFetcherRequestListener();
185 virtual ~URLFetcherRequestListener();
186
187 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
188
189 std::string upload_data;
190 net::URLFetcherDelegate* real_delegate;
191 };
192
URLFetcherRequestListener()193 URLFetcherRequestListener::URLFetcherRequestListener()
194 : real_delegate(NULL) {
195 }
196
~URLFetcherRequestListener()197 URLFetcherRequestListener::~URLFetcherRequestListener() {
198 }
199
OnURLFetchComplete(const net::URLFetcher * source)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);
207 }
208
209 class ConfigParserTest : public testing::Test {
210 protected:
211 ConfigParserTest();
212 virtual ~ConfigParserTest();
213
214 scoped_ptr<BrandcodeConfigFetcher> WaitForRequest(const GURL& url);
215
factory()216 net::FakeURLFetcherFactory& factory() { return factory_; }
217
218 private:
219 scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
220 const GURL& url,
221 net::URLFetcherDelegate* fetcher_delegate,
222 const std::string& response_data,
223 net::HttpStatusCode response_code,
224 net::URLRequestStatus::Status status);
225
226 MOCK_METHOD0(Callback, void(void));
227
228 base::MessageLoopForIO loop_;
229 content::TestBrowserThread ui_thread_;
230 content::TestBrowserThread io_thread_;
231 URLFetcherRequestListener request_listener_;
232 net::FakeURLFetcherFactory factory_;
233 };
234
ConfigParserTest()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))) {
240 }
241
~ConfigParserTest()242 ConfigParserTest::~ConfigParserTest() {}
243
WaitForRequest(const GURL & url)244 scoped_ptr<BrandcodeConfigFetcher> ConfigParserTest::WaitForRequest(
245 const GURL& url) {
246 EXPECT_CALL(*this, Callback());
247 scoped_ptr<BrandcodeConfigFetcher> fetcher(
248 new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback,
249 base::Unretained(this)),
250 url,
251 "ABCD"));
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();
257 }
258
CreateFakeURLFetcher(const GURL & url,net::URLFetcherDelegate * fetcher_delegate,const std::string & response_data,net::HttpStatusCode response_code,net::URLRequestStatus::Status status)259 scoped_ptr<net::FakeURLFetcher> ConfigParserTest::CreateFakeURLFetcher(
260 const GURL& url,
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();
274 }
275
276 // A helper class to create/delete/check a Chrome desktop shortcut on Windows.
277 class ShortcutHandler {
278 public:
279 ShortcutHandler();
280 ~ShortcutHandler();
281
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;
286 void Delete();
287
288 private:
289 #if defined(OS_WIN)
290 base::FilePath shortcut_path_;
291 #endif
292 DISALLOW_COPY_AND_ASSIGN(ShortcutHandler);
293 };
294
295 #if defined(OS_WIN)
ShortcutHandler()296 ShortcutHandler::ShortcutHandler() {
297 }
298
~ShortcutHandler()299 ShortcutHandler::~ShortcutHandler() {
300 if (!shortcut_path_.empty())
301 Delete();
302 }
303
304 // static
IsSupported()305 bool ShortcutHandler::IsSupported() {
306 return true;
307 }
308
CreateWithArguments(const base::string16 & name,const base::string16 & args)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();
317
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);
328 }
329
CheckShortcutHasArguments(const base::string16 & desired_args) const330 void ShortcutHandler::CheckShortcutHasArguments(
331 const base::string16& desired_args) const {
332 EXPECT_FALSE(shortcut_path_.empty());
333 base::string16 args;
334 EXPECT_TRUE(base::win::ResolveShortcut(shortcut_path_, NULL, &args));
335 EXPECT_EQ(desired_args, args);
336 }
337
Delete()338 void ShortcutHandler::Delete() {
339 EXPECT_FALSE(shortcut_path_.empty());
340 EXPECT_TRUE(base::DeleteFile(shortcut_path_, false));
341 shortcut_path_.clear();
342 }
343 #else
ShortcutHandler()344 ShortcutHandler::ShortcutHandler() {}
345
~ShortcutHandler()346 ShortcutHandler::~ShortcutHandler() {}
347
348 // static
IsSupported()349 bool ShortcutHandler::IsSupported() {
350 return false;
351 }
352
CreateWithArguments(const base::string16 & name,const base::string16 & args)353 ShortcutCommand ShortcutHandler::CreateWithArguments(
354 const base::string16& name,
355 const base::string16& args) {
356 return ShortcutCommand();
357 }
358
CheckShortcutHasArguments(const base::string16 & desired_args) const359 void ShortcutHandler::CheckShortcutHasArguments(
360 const base::string16& desired_args) const {
361 }
362
Delete()363 void ShortcutHandler::Delete() {
364 }
365 #endif // defined(OS_WIN)
366
367
368 // helper functions -----------------------------------------------------------
369
CreateExtension(const base::string16 & name,const base::FilePath & path,Manifest::Location location,extensions::Manifest::Type type,bool installed_by_default)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);
378 switch (type) {
379 case extensions::Manifest::TYPE_THEME:
380 manifest.Set(extensions::manifest_keys::kTheme,
381 new base::DictionaryValue);
382 break;
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");
388 break;
389 case extensions::Manifest::TYPE_EXTENSION:
390 // do nothing
391 break;
392 default:
393 NOTREACHED();
394 }
395 manifest.SetString(extensions::manifest_keys::kOmniboxKeyword, name);
396 std::string error;
397 scoped_refptr<Extension> extension = Extension::Create(
398 path,
399 location,
400 manifest,
401 installed_by_default ? Extension::WAS_INSTALLED_BY_DEFAULT
402 : Extension::NO_FLAGS,
403 &error);
404 EXPECT_TRUE(extension.get() != NULL) << error;
405 return extension;
406 }
407
ReplaceString(std::string * str,const std::string & placeholder,const std::string & substitution)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);
415 }
416
417
418 /********************* Tests *********************/
419
TEST_F(ProfileResetterTest,ResetNothing)420 TEST_F(ProfileResetterTest, ResetNothing) {
421 // The callback should be called even if there is nothing to reset.
422 ResetAndWait(0);
423 }
424
TEST_F(ProfileResetterTest,ResetDefaultSearchEngineNonOrganic)425 TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) {
426 PrefService* prefs = profile()->GetPrefs();
427 DCHECK(prefs);
428 prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/");
429
430 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE, kDistributionConfig);
431
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());
439
440 EXPECT_EQ("", prefs->GetString(prefs::kLastPromptedGoogleURL));
441 }
442
TEST_F(ProfileResetterTest,ResetDefaultSearchEnginePartially)443 TEST_F(ProfileResetterTest, ResetDefaultSearchEnginePartially) {
444 // Search engine's logic is tested by
445 // TemplateURLServiceTest.RepairPrepopulatedSearchEngines.
446 PrefService* prefs = profile()->GetPrefs();
447 DCHECK(prefs);
448 prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/");
449
450 // Make sure TemplateURLService has loaded.
451 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);
452
453 TemplateURLService* model =
454 TemplateURLServiceFactory::GetForProfile(profile());
455 TemplateURLService::TemplateURLVector urls = model->GetTemplateURLs();
456
457 // The second call should produce no effect.
458 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);
459
460 EXPECT_EQ(urls, model->GetTemplateURLs());
461 EXPECT_EQ(std::string(), prefs->GetString(prefs::kLastPromptedGoogleURL));
462 }
463
TEST_F(ProfileResetterTest,ResetHomepageNonOrganic)464 TEST_F(ProfileResetterTest, ResetHomepageNonOrganic) {
465 PrefService* prefs = profile()->GetPrefs();
466 DCHECK(prefs);
467 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, true);
468 prefs->SetString(prefs::kHomePage, "http://google.com");
469 prefs->SetBoolean(prefs::kShowHomeButton, false);
470
471 ResetAndWait(ProfileResetter::HOMEPAGE, kDistributionConfig);
472
473 EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
474 EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
475 EXPECT_TRUE(prefs->GetBoolean(prefs::kShowHomeButton));
476 }
477
TEST_F(ProfileResetterTest,ResetHomepagePartially)478 TEST_F(ProfileResetterTest, ResetHomepagePartially) {
479 PrefService* prefs = profile()->GetPrefs();
480 DCHECK(prefs);
481 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
482 prefs->SetString(prefs::kHomePage, "http://www.foo.com");
483 prefs->SetBoolean(prefs::kShowHomeButton, true);
484
485 ResetAndWait(ProfileResetter::HOMEPAGE);
486
487 EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
488 EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
489 EXPECT_FALSE(prefs->GetBoolean(prefs::kShowHomeButton));
490 }
491
TEST_F(ProfileResetterTest,ResetContentSettings)492 TEST_F(ProfileResetterTest, ResetContentSettings) {
493 HostContentSettingsMap* host_content_settings_map =
494 profile()->GetHostContentSettingsMap();
495 ContentSettingsPattern pattern =
496 ContentSettingsPattern::FromString("[*.]example.org");
497 std::map<ContentSettingsType, ContentSetting> default_settings;
498
499 for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
500 if (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
501 type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
502 type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
503 // These types are excluded because one can't call
504 // GetDefaultContentSetting() for them.
505 } else {
506 ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
507 ContentSetting default_setting =
508 host_content_settings_map->GetDefaultContentSetting(content_type,
509 NULL);
510 default_settings[content_type] = default_setting;
511 ContentSetting wildcard_setting =
512 default_setting == CONTENT_SETTING_BLOCK ? CONTENT_SETTING_ALLOW
513 : CONTENT_SETTING_BLOCK;
514 ContentSetting site_setting =
515 default_setting == CONTENT_SETTING_ALLOW ? CONTENT_SETTING_ALLOW
516 : CONTENT_SETTING_BLOCK;
517 if (HostContentSettingsMap::IsSettingAllowedForType(
518 profile()->GetPrefs(),
519 wildcard_setting,
520 content_type)) {
521 host_content_settings_map->SetDefaultContentSetting(
522 content_type,
523 wildcard_setting);
524 }
525 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) &&
526 HostContentSettingsMap::IsSettingAllowedForType(
527 profile()->GetPrefs(),
528 site_setting,
529 content_type)) {
530 host_content_settings_map->SetContentSetting(
531 pattern,
532 ContentSettingsPattern::Wildcard(),
533 content_type,
534 std::string(),
535 site_setting);
536 ContentSettingsForOneType host_settings;
537 host_content_settings_map->GetSettingsForOneType(
538 content_type, std::string(), &host_settings);
539 EXPECT_EQ(2U, host_settings.size());
540 }
541 }
542 }
543
544 ResetAndWait(ProfileResetter::CONTENT_SETTINGS);
545
546 for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
547 ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
548 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) ||
549 type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
550 content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
551 content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS)
552 continue;
553 ContentSetting default_setting =
554 host_content_settings_map->GetDefaultContentSetting(content_type,
555 NULL);
556 EXPECT_TRUE(default_settings.count(content_type));
557 EXPECT_EQ(default_settings[content_type], default_setting);
558 if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
559 ContentSetting site_setting =
560 host_content_settings_map->GetContentSetting(
561 GURL("example.org"),
562 GURL(),
563 content_type,
564 std::string());
565 EXPECT_EQ(default_setting, site_setting);
566 }
567
568 ContentSettingsForOneType host_settings;
569 host_content_settings_map->GetSettingsForOneType(
570 content_type, std::string(), &host_settings);
571 EXPECT_EQ(1U, host_settings.size());
572 }
573 }
574
TEST_F(ProfileResetterTest,ResetExtensionsByDisabling)575 TEST_F(ProfileResetterTest, ResetExtensionsByDisabling) {
576 service_->Init();
577
578 base::ScopedTempDir temp_dir;
579 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
580
581 scoped_refptr<Extension> theme =
582 CreateExtension(base::ASCIIToUTF16("example1"),
583 temp_dir.path(),
584 Manifest::INVALID_LOCATION,
585 extensions::Manifest::TYPE_THEME,
586 false);
587 service_->FinishInstallationForTest(theme.get());
588 // Let ThemeService finish creating the theme pack.
589 base::MessageLoop::current()->RunUntilIdle();
590
591 ThemeService* theme_service =
592 ThemeServiceFactory::GetForProfile(profile());
593 EXPECT_FALSE(theme_service->UsingDefaultTheme());
594
595 scoped_refptr<Extension> ext2 = CreateExtension(
596 base::ASCIIToUTF16("example2"),
597 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
598 Manifest::INVALID_LOCATION,
599 extensions::Manifest::TYPE_EXTENSION,
600 false);
601 service_->AddExtension(ext2.get());
602 // Component extensions and policy-managed extensions shouldn't be disabled.
603 scoped_refptr<Extension> ext3 = CreateExtension(
604 base::ASCIIToUTF16("example3"),
605 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
606 Manifest::COMPONENT,
607 extensions::Manifest::TYPE_EXTENSION,
608 false);
609 service_->AddExtension(ext3.get());
610 scoped_refptr<Extension> ext4 =
611 CreateExtension(base::ASCIIToUTF16("example4"),
612 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
613 Manifest::EXTERNAL_POLICY_DOWNLOAD,
614 extensions::Manifest::TYPE_EXTENSION,
615 false);
616 service_->AddExtension(ext4.get());
617 scoped_refptr<Extension> ext5 = CreateExtension(
618 base::ASCIIToUTF16("example5"),
619 base::FilePath(FILE_PATH_LITERAL("//nonexistent4")),
620 Manifest::EXTERNAL_COMPONENT,
621 extensions::Manifest::TYPE_EXTENSION,
622 false);
623 service_->AddExtension(ext5.get());
624 scoped_refptr<Extension> ext6 = CreateExtension(
625 base::ASCIIToUTF16("example6"),
626 base::FilePath(FILE_PATH_LITERAL("//nonexistent5")),
627 Manifest::EXTERNAL_POLICY,
628 extensions::Manifest::TYPE_EXTENSION,
629 false);
630 service_->AddExtension(ext6.get());
631 EXPECT_EQ(6u, service_->extensions()->size());
632
633 ResetAndWait(ProfileResetter::EXTENSIONS);
634 EXPECT_EQ(4u, service_->extensions()->size());
635 EXPECT_FALSE(service_->extensions()->Contains(theme->id()));
636 EXPECT_FALSE(service_->extensions()->Contains(ext2->id()));
637 EXPECT_TRUE(service_->extensions()->Contains(ext3->id()));
638 EXPECT_TRUE(service_->extensions()->Contains(ext4->id()));
639 EXPECT_TRUE(service_->extensions()->Contains(ext5->id()));
640 EXPECT_TRUE(service_->extensions()->Contains(ext6->id()));
641 EXPECT_TRUE(theme_service->UsingDefaultTheme());
642 }
643
TEST_F(ProfileResetterTest,ResetExtensionsByDisablingNonOrganic)644 TEST_F(ProfileResetterTest, ResetExtensionsByDisablingNonOrganic) {
645 scoped_refptr<Extension> ext2 = CreateExtension(
646 base::ASCIIToUTF16("example2"),
647 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
648 Manifest::INVALID_LOCATION,
649 extensions::Manifest::TYPE_EXTENSION,
650 false);
651 service_->AddExtension(ext2.get());
652 // Components and external policy extensions shouldn't be deleted.
653 scoped_refptr<Extension> ext3 = CreateExtension(
654 base::ASCIIToUTF16("example3"),
655 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
656 Manifest::INVALID_LOCATION,
657 extensions::Manifest::TYPE_EXTENSION,
658 false);
659 service_->AddExtension(ext3.get());
660 EXPECT_EQ(2u, service_->extensions()->size());
661
662 std::string master_prefs(kDistributionConfig);
663 ReplaceString(&master_prefs, "placeholder_for_id", ext3->id());
664
665 ResetAndWait(ProfileResetter::EXTENSIONS, master_prefs);
666
667 EXPECT_EQ(1u, service_->extensions()->size());
668 EXPECT_TRUE(service_->extensions()->Contains(ext3->id()));
669 }
670
TEST_F(ProfileResetterTest,ResetExtensionsAndDefaultApps)671 TEST_F(ProfileResetterTest, ResetExtensionsAndDefaultApps) {
672 service_->Init();
673
674 base::ScopedTempDir temp_dir;
675 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
676
677 scoped_refptr<Extension> ext1 =
678 CreateExtension(base::ASCIIToUTF16("example1"),
679 temp_dir.path(),
680 Manifest::INVALID_LOCATION,
681 extensions::Manifest::TYPE_THEME,
682 false);
683 service_->FinishInstallationForTest(ext1.get());
684 // Let ThemeService finish creating the theme pack.
685 base::MessageLoop::current()->RunUntilIdle();
686
687 ThemeService* theme_service =
688 ThemeServiceFactory::GetForProfile(profile());
689 EXPECT_FALSE(theme_service->UsingDefaultTheme());
690
691 scoped_refptr<Extension> ext2 =
692 CreateExtension(base::ASCIIToUTF16("example2"),
693 base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
694 Manifest::INVALID_LOCATION,
695 extensions::Manifest::TYPE_EXTENSION,
696 false);
697 service_->AddExtension(ext2.get());
698
699 scoped_refptr<Extension> ext3 =
700 CreateExtension(base::ASCIIToUTF16("example2"),
701 base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
702 Manifest::INVALID_LOCATION,
703 extensions::Manifest::TYPE_HOSTED_APP,
704 true);
705 service_->AddExtension(ext3.get());
706 EXPECT_EQ(3u, service_->extensions()->size());
707
708 ResetAndWait(ProfileResetter::EXTENSIONS);
709
710 EXPECT_EQ(1u, service_->extensions()->size());
711 EXPECT_FALSE(service_->extensions()->Contains(ext1->id()));
712 EXPECT_FALSE(service_->extensions()->Contains(ext2->id()));
713 EXPECT_TRUE(service_->extensions()->Contains(ext3->id()));
714 EXPECT_TRUE(theme_service->UsingDefaultTheme());
715 }
716
TEST_F(ProfileResetterTest,ResetStartPageNonOrganic)717 TEST_F(ProfileResetterTest, ResetStartPageNonOrganic) {
718 PrefService* prefs = profile()->GetPrefs();
719 DCHECK(prefs);
720
721 SessionStartupPref startup_pref(SessionStartupPref::LAST);
722 SessionStartupPref::SetStartupPref(prefs, startup_pref);
723
724 ResetAndWait(ProfileResetter::STARTUP_PAGES, kDistributionConfig);
725
726 startup_pref = SessionStartupPref::GetStartupPref(prefs);
727 EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type);
728 const GURL urls[] = {GURL("http://goo.gl"), GURL("http://foo.de")};
729 EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls);
730 }
731
732
TEST_F(ProfileResetterTest,ResetStartPagePartially)733 TEST_F(ProfileResetterTest, ResetStartPagePartially) {
734 PrefService* prefs = profile()->GetPrefs();
735 DCHECK(prefs);
736
737 const GURL urls[] = {GURL("http://foo"), GURL("http://bar")};
738 SessionStartupPref startup_pref(SessionStartupPref::URLS);
739 startup_pref.urls.assign(urls, urls + arraysize(urls));
740 SessionStartupPref::SetStartupPref(prefs, startup_pref);
741
742 ResetAndWait(ProfileResetter::STARTUP_PAGES, std::string());
743
744 startup_pref = SessionStartupPref::GetStartupPref(prefs);
745 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref.type);
746 EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls);
747 }
748
TEST_F(PinnedTabsResetTest,ResetPinnedTabs)749 TEST_F(PinnedTabsResetTest, ResetPinnedTabs) {
750 scoped_refptr<Extension> extension_app = CreateExtension(
751 base::ASCIIToUTF16("hello!"),
752 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
753 Manifest::INVALID_LOCATION,
754 extensions::Manifest::TYPE_HOSTED_APP,
755 false);
756 scoped_ptr<content::WebContents> contents1(CreateWebContents());
757 extensions::TabHelper::CreateForWebContents(contents1.get());
758 extensions::TabHelper::FromWebContents(contents1.get())->
759 SetExtensionApp(extension_app.get());
760 scoped_ptr<content::WebContents> contents2(CreateWebContents());
761 scoped_ptr<content::WebContents> contents3(CreateWebContents());
762 scoped_ptr<content::WebContents> contents4(CreateWebContents());
763 TabStripModel* tab_strip_model = browser()->tab_strip_model();
764
765 tab_strip_model->AppendWebContents(contents4.get(), true);
766 tab_strip_model->AppendWebContents(contents3.get(), true);
767 tab_strip_model->AppendWebContents(contents2.get(), true);
768 tab_strip_model->SetTabPinned(2, true);
769 tab_strip_model->AppendWebContents(contents1.get(), true);
770 tab_strip_model->SetTabPinned(3, true);
771
772 EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(0));
773 EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(1));
774 EXPECT_EQ(contents3, tab_strip_model->GetWebContentsAt(2));
775 EXPECT_EQ(contents4, tab_strip_model->GetWebContentsAt(3));
776 EXPECT_EQ(3, tab_strip_model->IndexOfFirstNonMiniTab());
777
778 ResetAndWait(ProfileResetter::PINNED_TABS);
779
780 EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(0));
781 EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(1));
782 EXPECT_EQ(contents3, tab_strip_model->GetWebContentsAt(2));
783 EXPECT_EQ(contents4, tab_strip_model->GetWebContentsAt(3));
784 EXPECT_EQ(1, tab_strip_model->IndexOfFirstNonMiniTab());
785 }
786
TEST_F(ProfileResetterTest,ResetShortcuts)787 TEST_F(ProfileResetterTest, ResetShortcuts) {
788 ShortcutHandler shortcut;
789 ShortcutCommand command_line = shortcut.CreateWithArguments(
790 base::ASCIIToUTF16("chrome.lnk"),
791 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
792 shortcut.CheckShortcutHasArguments(base::ASCIIToUTF16(
793 "--profile-directory=Default foo.com"));
794
795 ResetAndWait(ProfileResetter::SHORTCUTS);
796
797 shortcut.CheckShortcutHasArguments(base::ASCIIToUTF16(
798 "--profile-directory=Default"));
799 }
800
TEST_F(ProfileResetterTest,ResetFewFlags)801 TEST_F(ProfileResetterTest, ResetFewFlags) {
802 // mock_object_ is a StrictMock, so we verify that it is called only once.
803 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
804 ProfileResetter::HOMEPAGE |
805 ProfileResetter::CONTENT_SETTINGS);
806 }
807
808 // Tries to load unavailable config file.
TEST_F(ConfigParserTest,NoConnectivity)809 TEST_F(ConfigParserTest, NoConnectivity) {
810 const GURL url("http://test");
811 factory().SetFakeResponse(url, "", net::HTTP_INTERNAL_SERVER_ERROR,
812 net::URLRequestStatus::FAILED);
813
814 scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
815 EXPECT_FALSE(fetcher->GetSettings());
816 }
817
818 // Tries to load available config file.
TEST_F(ConfigParserTest,ParseConfig)819 TEST_F(ConfigParserTest, ParseConfig) {
820 const GURL url("http://test");
821 std::string xml_config(kXmlConfig);
822 ReplaceString(&xml_config, "placeholder_for_data", kDistributionConfig);
823 ReplaceString(&xml_config,
824 "placeholder_for_id",
825 "abbaabbaabbaabbaabbaabbaabbaabba");
826 factory().SetFakeResponse(url, xml_config, net::HTTP_OK,
827 net::URLRequestStatus::SUCCESS);
828
829 scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
830 scoped_ptr<BrandcodedDefaultSettings> settings = fetcher->GetSettings();
831 ASSERT_TRUE(settings);
832
833 std::vector<std::string> extension_ids;
834 EXPECT_TRUE(settings->GetExtensions(&extension_ids));
835 EXPECT_EQ(1u, extension_ids.size());
836 EXPECT_EQ("abbaabbaabbaabbaabbaabbaabbaabba", extension_ids[0]);
837
838 std::string homepage;
839 EXPECT_TRUE(settings->GetHomepage(&homepage));
840 EXPECT_EQ("http://www.foo.com", homepage);
841
842 scoped_ptr<base::ListValue> startup_list(
843 settings->GetUrlsToRestoreOnStartup());
844 EXPECT_TRUE(startup_list);
845 std::vector<std::string> startup_pages;
846 for (base::ListValue::iterator i = startup_list->begin();
847 i != startup_list->end(); ++i) {
848 std::string url;
849 EXPECT_TRUE((*i)->GetAsString(&url));
850 startup_pages.push_back(url);
851 }
852 ASSERT_EQ(2u, startup_pages.size());
853 EXPECT_EQ("http://goo.gl", startup_pages[0]);
854 EXPECT_EQ("http://foo.de", startup_pages[1]);
855 }
856
TEST_F(ProfileResetterTest,CheckSnapshots)857 TEST_F(ProfileResetterTest, CheckSnapshots) {
858 ResettableSettingsSnapshot empty_snap(profile());
859 EXPECT_EQ(0, empty_snap.FindDifferentFields(empty_snap));
860
861 scoped_refptr<Extension> ext = CreateExtension(
862 base::ASCIIToUTF16("example"),
863 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
864 Manifest::INVALID_LOCATION,
865 extensions::Manifest::TYPE_EXTENSION,
866 false);
867 ASSERT_TRUE(ext.get());
868 service_->AddExtension(ext.get());
869
870 std::string master_prefs(kDistributionConfig);
871 std::string ext_id = ext->id();
872 ReplaceString(&master_prefs, "placeholder_for_id", ext_id);
873
874 // Reset to non organic defaults.
875 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
876 ProfileResetter::HOMEPAGE |
877 ProfileResetter::STARTUP_PAGES,
878 master_prefs);
879 ShortcutHandler shortcut_hijacked;
880 ShortcutCommand command_line = shortcut_hijacked.CreateWithArguments(
881 base::ASCIIToUTF16("chrome1.lnk"),
882 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
883 shortcut_hijacked.CheckShortcutHasArguments(
884 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
885 ShortcutHandler shortcut_ok;
886 shortcut_ok.CreateWithArguments(
887 base::ASCIIToUTF16("chrome2.lnk"),
888 base::ASCIIToUTF16("--profile-directory=Default1"));
889
890 ResettableSettingsSnapshot nonorganic_snap(profile());
891 nonorganic_snap.RequestShortcuts(base::Closure());
892 // Let it enumerate shortcuts on the FILE thread.
893 base::MessageLoop::current()->RunUntilIdle();
894 int diff_fields = ResettableSettingsSnapshot::ALL_FIELDS;
895 if (!ShortcutHandler::IsSupported())
896 diff_fields &= ~ResettableSettingsSnapshot::SHORTCUTS;
897 EXPECT_EQ(diff_fields,
898 empty_snap.FindDifferentFields(nonorganic_snap));
899 empty_snap.Subtract(nonorganic_snap);
900 EXPECT_TRUE(empty_snap.startup_urls().empty());
901 EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
902 empty_snap.startup_type());
903 EXPECT_TRUE(empty_snap.homepage().empty());
904 EXPECT_TRUE(empty_snap.homepage_is_ntp());
905 EXPECT_FALSE(empty_snap.show_home_button());
906 EXPECT_NE(std::string::npos, empty_snap.dse_url().find("{google:baseURL}"));
907 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(),
908 empty_snap.enabled_extensions());
909 EXPECT_EQ(std::vector<ShortcutCommand>(), empty_snap.shortcuts());
910
911 // Reset to organic defaults.
912 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
913 ProfileResetter::HOMEPAGE |
914 ProfileResetter::STARTUP_PAGES |
915 ProfileResetter::EXTENSIONS |
916 ProfileResetter::SHORTCUTS);
917
918 ResettableSettingsSnapshot organic_snap(profile());
919 organic_snap.RequestShortcuts(base::Closure());
920 // Let it enumerate shortcuts on the FILE thread.
921 base::MessageLoop::current()->RunUntilIdle();
922 EXPECT_EQ(diff_fields, nonorganic_snap.FindDifferentFields(organic_snap));
923 nonorganic_snap.Subtract(organic_snap);
924 const GURL urls[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
925 EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)),
926 nonorganic_snap.startup_urls());
927 EXPECT_EQ(SessionStartupPref::URLS, nonorganic_snap.startup_type());
928 EXPECT_EQ("http://www.foo.com", nonorganic_snap.homepage());
929 EXPECT_FALSE(nonorganic_snap.homepage_is_ntp());
930 EXPECT_TRUE(nonorganic_snap.show_home_button());
931 EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap.dse_url());
932 EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(
933 1, std::make_pair(ext_id, "example")),
934 nonorganic_snap.enabled_extensions());
935 if (ShortcutHandler::IsSupported()) {
936 std::vector<ShortcutCommand> shortcuts = nonorganic_snap.shortcuts();
937 ASSERT_EQ(1u, shortcuts.size());
938 EXPECT_EQ(command_line.first.value(), shortcuts[0].first.value());
939 EXPECT_EQ(command_line.second, shortcuts[0].second);
940 }
941 }
942
TEST_F(ProfileResetterTest,FeedbackSerializationTest)943 TEST_F(ProfileResetterTest, FeedbackSerializationTest) {
944 // Reset to non organic defaults.
945 ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
946 ProfileResetter::HOMEPAGE |
947 ProfileResetter::STARTUP_PAGES,
948 kDistributionConfig);
949
950 scoped_refptr<Extension> ext = CreateExtension(
951 base::ASCIIToUTF16("example"),
952 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
953 Manifest::INVALID_LOCATION,
954 extensions::Manifest::TYPE_EXTENSION,
955 false);
956 ASSERT_TRUE(ext.get());
957 service_->AddExtension(ext.get());
958
959 ShortcutHandler shortcut;
960 ShortcutCommand command_line = shortcut.CreateWithArguments(
961 base::ASCIIToUTF16("chrome.lnk"),
962 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
963
964 ResettableSettingsSnapshot nonorganic_snap(profile());
965 nonorganic_snap.RequestShortcuts(base::Closure());
966 // Let it enumerate shortcuts on the FILE thread.
967 base::MessageLoop::current()->RunUntilIdle();
968
969 COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
970 expand_this_test);
971 for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS;
972 ++field_mask) {
973 std::string report = SerializeSettingsReport(nonorganic_snap, field_mask);
974 JSONStringValueSerializer json(report);
975 std::string error;
976 scoped_ptr<base::Value> root(json.Deserialize(NULL, &error));
977 ASSERT_TRUE(root) << error;
978 ASSERT_TRUE(root->IsType(base::Value::TYPE_DICTIONARY)) << error;
979
980 base::DictionaryValue* dict =
981 static_cast<base::DictionaryValue*>(root.get());
982
983 base::ListValue* startup_urls = NULL;
984 int startup_type = 0;
985 std::string homepage;
986 bool homepage_is_ntp = true;
987 bool show_home_button = true;
988 std::string default_search_engine;
989 base::ListValue* extensions = NULL;
990 base::ListValue* shortcuts = NULL;
991
992 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
993 dict->GetList("startup_urls", &startup_urls));
994 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
995 dict->GetInteger("startup_type", &startup_type));
996 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
997 dict->GetString("homepage", &homepage));
998 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
999 dict->GetBoolean("homepage_is_ntp", &homepage_is_ntp));
1000 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
1001 dict->GetBoolean("show_home_button", &show_home_button));
1002 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL),
1003 dict->GetString("default_search_engine", &default_search_engine));
1004 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::EXTENSIONS),
1005 dict->GetList("enabled_extensions", &extensions));
1006 EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::SHORTCUTS),
1007 dict->GetList("shortcuts", &shortcuts));
1008 }
1009 }
1010
1011 struct FeedbackCapture {
SetFeedback__anon13f0dbe00111::FeedbackCapture1012 void SetFeedback(Profile* profile,
1013 const ResettableSettingsSnapshot& snapshot) {
1014 list_ = GetReadableFeedbackForSnapshot(profile, snapshot).Pass();
1015 OnUpdatedList();
1016 }
1017
Fail__anon13f0dbe00111::FeedbackCapture1018 void Fail() {
1019 ADD_FAILURE() << "This method shouldn't be called.";
1020 }
1021
1022 MOCK_METHOD0(OnUpdatedList, void(void));
1023
1024 scoped_ptr<base::ListValue> list_;
1025 };
1026
1027 // Make sure GetReadableFeedback handles non-ascii letters.
TEST_F(ProfileResetterTest,GetReadableFeedback)1028 TEST_F(ProfileResetterTest, GetReadableFeedback) {
1029 scoped_refptr<Extension> ext = CreateExtension(
1030 base::WideToUTF16(L"Tiësto"),
1031 base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
1032 Manifest::INVALID_LOCATION,
1033 extensions::Manifest::TYPE_EXTENSION,
1034 false);
1035 ASSERT_TRUE(ext.get());
1036 service_->AddExtension(ext.get());
1037
1038 PrefService* prefs = profile()->GetPrefs();
1039 DCHECK(prefs);
1040 // The URL is "http://россия.рф".
1041 std::wstring url(L"http://"
1042 L"\u0440\u043e\u0441\u0441\u0438\u044f.\u0440\u0444");
1043 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
1044 prefs->SetString(prefs::kHomePage, base::WideToUTF8(url));
1045
1046 SessionStartupPref startup_pref(SessionStartupPref::URLS);
1047 startup_pref.urls.push_back(GURL(base::WideToUTF8(url)));
1048 SessionStartupPref::SetStartupPref(prefs, startup_pref);
1049
1050 ShortcutHandler shortcut;
1051 ShortcutCommand command_line = shortcut.CreateWithArguments(
1052 base::ASCIIToUTF16("chrome.lnk"),
1053 base::ASCIIToUTF16("--profile-directory=Default foo.com"));
1054
1055 FeedbackCapture capture;
1056 EXPECT_CALL(capture, OnUpdatedList());
1057 ResettableSettingsSnapshot snapshot(profile());
1058 snapshot.RequestShortcuts(base::Bind(&FeedbackCapture::SetFeedback,
1059 base::Unretained(&capture),
1060 profile(),
1061 base::ConstRef(snapshot)));
1062 // Let it enumerate shortcuts on the FILE thread.
1063 base::MessageLoop::current()->RunUntilIdle();
1064 ::testing::Mock::VerifyAndClearExpectations(&capture);
1065 // The homepage and the startup page are in punycode. They are unreadable.
1066 // Trying to find the extension name.
1067 scoped_ptr<base::ListValue> list = capture.list_.Pass();
1068 ASSERT_TRUE(list);
1069 bool checked_extensions = false;
1070 bool checked_shortcuts = false;
1071 for (size_t i = 0; i < list->GetSize(); ++i) {
1072 base::DictionaryValue* dict = NULL;
1073 ASSERT_TRUE(list->GetDictionary(i, &dict));
1074 std::string value;
1075 ASSERT_TRUE(dict->GetString("key", &value));
1076 if (value == "Extensions") {
1077 base::string16 extensions;
1078 EXPECT_TRUE(dict->GetString("value", &extensions));
1079 EXPECT_EQ(base::WideToUTF16(L"Tiësto"), extensions);
1080 checked_extensions = true;
1081 } else if (value == "Shortcut targets") {
1082 base::string16 targets;
1083 EXPECT_TRUE(dict->GetString("value", &targets));
1084 EXPECT_NE(base::string16::npos,
1085 targets.find(base::ASCIIToUTF16("foo.com"))) << targets;
1086 checked_shortcuts = true;
1087 }
1088 }
1089 EXPECT_TRUE(checked_extensions);
1090 EXPECT_EQ(ShortcutHandler::IsSupported(), checked_shortcuts);
1091 }
1092
TEST_F(ProfileResetterTest,DestroySnapshotFast)1093 TEST_F(ProfileResetterTest, DestroySnapshotFast) {
1094 FeedbackCapture capture;
1095 scoped_ptr<ResettableSettingsSnapshot> deleted_snapshot(
1096 new ResettableSettingsSnapshot(profile()));
1097 deleted_snapshot->RequestShortcuts(base::Bind(&FeedbackCapture::Fail,
1098 base::Unretained(&capture)));
1099 deleted_snapshot.reset();
1100 // Running remaining tasks shouldn't trigger the callback to be called as
1101 // |deleted_snapshot| was deleted before it could run.
1102 base::MessageLoop::current()->RunUntilIdle();
1103 }
1104
1105 } // namespace
1106