Home | History | Annotate | Download | only in profile_resetter
      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 "chrome/browser/content_settings/host_content_settings_map.h"
     11 #include "chrome/browser/extensions/extension_service_unittest.h"
     12 #include "chrome/browser/extensions/tab_helper.h"
     13 #include "chrome/browser/notifications/desktop_notification_service.h"
     14 #include "chrome/browser/notifications/desktop_notification_service_factory.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.h"
     20 #include "chrome/browser/search_engines/template_url_service_factory.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/common/pref_names.h"
     25 #include "chrome/test/base/browser_with_test_window_test.h"
     26 #include "content/public/browser/web_contents.h"
     27 #include "content/public/test/test_browser_thread.h"
     28 #include "extensions/common/extension.h"
     29 #include "extensions/common/manifest_constants.h"
     30 #include "net/http/http_response_headers.h"
     31 #include "net/http/http_status_code.h"
     32 #include "net/url_request/test_url_fetcher_factory.h"
     33 #include "net/url_request/url_request_status.h"
     34 #include "url/gurl.h"
     35 
     36 
     37 namespace {
     38 
     39 const char kDistributionConfig[] = "{"
     40     " \"homepage\" : \"http://www.foo.com\","
     41     " \"homepage_is_newtabpage\" : false,"
     42     " \"browser\" : {"
     43     "   \"show_home_button\" : true"
     44     "  },"
     45     " \"session\" : {"
     46     "   \"restore_on_startup\" : 4,"
     47     "   \"startup_urls\" : [\"http://goo.gl\", \"http://foo.de\"]"
     48     "  },"
     49     " \"search_provider_overrides\" : ["
     50     "    {"
     51     "      \"name\" : \"first\","
     52     "      \"keyword\" : \"firstkey\","
     53     "      \"search_url\" : \"http://www.foo.com/s?q={searchTerms}\","
     54     "      \"favicon_url\" : \"http://www.foo.com/favicon.ico\","
     55     "      \"suggest_url\" : \"http://www.foo.com/s?q={searchTerms}\","
     56     "      \"encoding\" : \"UTF-8\","
     57     "      \"id\" : 1001"
     58     "    }"
     59     "  ],"
     60     " \"extensions\" : {"
     61     "   \"settings\" : {"
     62     "     \"placeholder_for_id\": {"
     63     "      }"
     64     "    }"
     65     "  }"
     66     "}";
     67 
     68 const char kXmlConfig[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
     69     "<response protocol=\"3.0\" server=\"prod\">"
     70       "<app appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\" status=\"ok\">"
     71         "<data index=\"skipfirstrunui-importsearch-defaultbrowser\" "
     72           "name=\"install\" status=\"ok\">"
     73           "placeholder_for_data"
     74         "</data>"
     75       "</app>"
     76     "</response>";
     77 
     78 using extensions::Extension;
     79 using extensions::Manifest;
     80 
     81 
     82 // ProfileResetterTest --------------------------------------------------------
     83 
     84 // ProfileResetterTest sets up the extension, WebData and TemplateURL services.
     85 class ProfileResetterTest : public ExtensionServiceTestBase,
     86                             public ProfileResetterTestBase {
     87  protected:
     88   virtual void SetUp() OVERRIDE;
     89 
     90   TestingProfile* profile() { return profile_.get(); }
     91 
     92   static BrowserContextKeyedService* CreateTemplateURLService(
     93       content::BrowserContext* context);
     94 };
     95 
     96 void ProfileResetterTest::SetUp() {
     97   ExtensionServiceTestBase::SetUp();
     98   InitializeEmptyExtensionService();
     99 
    100   profile()->CreateWebDataService();
    101   TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
    102       profile(),
    103       &ProfileResetterTest::CreateTemplateURLService);
    104   resetter_.reset(new ProfileResetter(profile()));
    105 }
    106 
    107 // static
    108 BrowserContextKeyedService* ProfileResetterTest::CreateTemplateURLService(
    109     content::BrowserContext* context) {
    110   return new TemplateURLService(static_cast<Profile*>(context));
    111 }
    112 
    113 
    114 // PinnedTabsResetTest --------------------------------------------------------
    115 
    116 class PinnedTabsResetTest : public BrowserWithTestWindowTest,
    117                             public ProfileResetterTestBase {
    118  protected:
    119   virtual void SetUp() OVERRIDE;
    120 
    121   content::WebContents* CreateWebContents();
    122 };
    123 
    124 void PinnedTabsResetTest::SetUp() {
    125   BrowserWithTestWindowTest::SetUp();
    126   resetter_.reset(new ProfileResetter(profile()));
    127 }
    128 
    129 content::WebContents* PinnedTabsResetTest::CreateWebContents() {
    130   return content::WebContents::Create(
    131       content::WebContents::CreateParams(profile()));
    132 }
    133 
    134 
    135 // ConfigParserTest -----------------------------------------------------------
    136 
    137 // URLFetcher delegate that simply records the upload data.
    138 struct URLFetcherRequestListener : net::URLFetcherDelegate {
    139   URLFetcherRequestListener();
    140   virtual ~URLFetcherRequestListener();
    141 
    142   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
    143 
    144   std::string upload_data;
    145   net::URLFetcherDelegate* real_delegate;
    146 };
    147 
    148 URLFetcherRequestListener::URLFetcherRequestListener()
    149     : real_delegate(NULL) {
    150 }
    151 
    152 URLFetcherRequestListener::~URLFetcherRequestListener() {
    153 }
    154 
    155 void URLFetcherRequestListener::OnURLFetchComplete(
    156     const net::URLFetcher* source) {
    157   const net::TestURLFetcher* test_fetcher =
    158       static_cast<const net::TestURLFetcher*>(source);
    159   upload_data = test_fetcher->upload_data();
    160   DCHECK(real_delegate);
    161   real_delegate->OnURLFetchComplete(source);
    162 }
    163 
    164 class ConfigParserTest : public testing::Test {
    165  protected:
    166   ConfigParserTest();
    167   virtual ~ConfigParserTest();
    168 
    169   scoped_ptr<BrandcodeConfigFetcher> WaitForRequest(const GURL& url);
    170 
    171   net::FakeURLFetcherFactory& factory() { return factory_; }
    172 
    173  private:
    174   scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
    175       const GURL& url,
    176       net::URLFetcherDelegate* fetcher_delegate,
    177       const std::string& response_data,
    178       net::HttpStatusCode response_code,
    179       net::URLRequestStatus::Status status);
    180 
    181   MOCK_METHOD0(Callback, void(void));
    182 
    183   base::MessageLoop loop_;
    184   content::TestBrowserThread ui_thread_;
    185   content::TestBrowserThread io_thread_;
    186   URLFetcherRequestListener request_listener_;
    187   net::FakeURLFetcherFactory factory_;
    188 };
    189 
    190 ConfigParserTest::ConfigParserTest()
    191     : loop_(base::MessageLoop::TYPE_IO),
    192       ui_thread_(content::BrowserThread::UI, &loop_),
    193       io_thread_(content::BrowserThread::IO, &loop_),
    194       factory_(NULL, base::Bind(&ConfigParserTest::CreateFakeURLFetcher,
    195                                 base::Unretained(this))) {
    196 }
    197 
    198 ConfigParserTest::~ConfigParserTest() {}
    199 
    200 scoped_ptr<BrandcodeConfigFetcher> ConfigParserTest::WaitForRequest(
    201     const GURL& url) {
    202   EXPECT_CALL(*this, Callback());
    203   scoped_ptr<BrandcodeConfigFetcher> fetcher(
    204       new BrandcodeConfigFetcher(base::Bind(&ConfigParserTest::Callback,
    205                                             base::Unretained(this)),
    206                                  url,
    207                                  "ABCD"));
    208   base::MessageLoop::current()->RunUntilIdle();
    209   EXPECT_FALSE(fetcher->IsActive());
    210   // Look for the brand code in the request.
    211   EXPECT_NE(std::string::npos, request_listener_.upload_data.find("ABCD"));
    212   return fetcher.Pass();
    213 }
    214 
    215 scoped_ptr<net::FakeURLFetcher> ConfigParserTest::CreateFakeURLFetcher(
    216     const GURL& url,
    217     net::URLFetcherDelegate* fetcher_delegate,
    218     const std::string& response_data,
    219     net::HttpStatusCode response_code,
    220     net::URLRequestStatus::Status status) {
    221   request_listener_.real_delegate = fetcher_delegate;
    222   scoped_ptr<net::FakeURLFetcher> fetcher(
    223       new net::FakeURLFetcher(
    224           url, &request_listener_, response_data, response_code, status));
    225   scoped_refptr<net::HttpResponseHeaders> download_headers =
    226       new net::HttpResponseHeaders("");
    227   download_headers->AddHeader("Content-Type: text/xml");
    228   fetcher->set_response_headers(download_headers);
    229   return fetcher.Pass();
    230 }
    231 
    232 
    233 // helper functions -----------------------------------------------------------
    234 
    235 scoped_refptr<Extension> CreateExtension(const base::string16& name,
    236                                          const base::FilePath& path,
    237                                          Manifest::Location location,
    238                                          extensions::Manifest::Type type,
    239                                          bool installed_by_default) {
    240   DictionaryValue manifest;
    241   manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
    242   manifest.SetString(extensions::manifest_keys::kName, name);
    243   switch (type) {
    244     case extensions::Manifest::TYPE_THEME:
    245       manifest.Set(extensions::manifest_keys::kTheme, new DictionaryValue);
    246       break;
    247     case extensions::Manifest::TYPE_HOSTED_APP:
    248       manifest.SetString(extensions::manifest_keys::kLaunchWebURL,
    249                          "http://www.google.com");
    250       manifest.SetString(extensions::manifest_keys::kUpdateURL,
    251                          "http://clients2.google.com/service/update2/crx");
    252       break;
    253     case extensions::Manifest::TYPE_EXTENSION:
    254       // do nothing
    255       break;
    256     default:
    257       NOTREACHED();
    258   }
    259   manifest.SetString(extensions::manifest_keys::kOmniboxKeyword, name);
    260   std::string error;
    261   scoped_refptr<Extension> extension = Extension::Create(
    262       path,
    263       location,
    264       manifest,
    265       installed_by_default ? Extension::WAS_INSTALLED_BY_DEFAULT
    266                            : Extension::NO_FLAGS,
    267       &error);
    268   EXPECT_TRUE(extension.get() != NULL) << error;
    269   return extension;
    270 }
    271 
    272 void ReplaceString(std::string* str,
    273                    const std::string& placeholder,
    274                    const std::string& substitution) {
    275   ASSERT_NE(static_cast<std::string*>(NULL), str);
    276   size_t placeholder_pos = str->find(placeholder);
    277   ASSERT_NE(std::string::npos, placeholder_pos);
    278   str->replace(placeholder_pos, placeholder.size(), substitution);
    279 }
    280 
    281 
    282 /********************* Tests *********************/
    283 
    284 TEST_F(ProfileResetterTest, ResetNothing) {
    285   // The callback should be called even if there is nothing to reset.
    286   ResetAndWait(0);
    287 }
    288 
    289 TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) {
    290   PrefService* prefs = profile()->GetPrefs();
    291   DCHECK(prefs);
    292   prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/");
    293 
    294   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE, kDistributionConfig);
    295 
    296   TemplateURLService* model =
    297       TemplateURLServiceFactory::GetForProfile(profile());
    298   TemplateURL* default_engine = model->GetDefaultSearchProvider();
    299   ASSERT_NE(static_cast<TemplateURL*>(NULL), default_engine);
    300   EXPECT_EQ(ASCIIToUTF16("first"), default_engine->short_name());
    301   EXPECT_EQ(ASCIIToUTF16("firstkey"), default_engine->keyword());
    302   EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", default_engine->url());
    303 
    304   EXPECT_EQ("", prefs->GetString(prefs::kLastPromptedGoogleURL));
    305 }
    306 
    307 TEST_F(ProfileResetterTest, ResetDefaultSearchEnginePartially) {
    308   // Search engine's logic is tested by
    309   // TemplateURLServiceTest.RepairPrepopulatedSearchEngines.
    310   PrefService* prefs = profile()->GetPrefs();
    311   DCHECK(prefs);
    312   prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/");
    313 
    314   // Make sure TemplateURLService has loaded.
    315   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);
    316 
    317   TemplateURLService* model =
    318       TemplateURLServiceFactory::GetForProfile(profile());
    319   TemplateURLService::TemplateURLVector urls = model->GetTemplateURLs();
    320 
    321   // The second call should produce no effect.
    322   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);
    323 
    324   EXPECT_EQ(urls, model->GetTemplateURLs());
    325   EXPECT_EQ(std::string(), prefs->GetString(prefs::kLastPromptedGoogleURL));
    326 }
    327 
    328 TEST_F(ProfileResetterTest, ResetHomepageNonOrganic) {
    329   PrefService* prefs = profile()->GetPrefs();
    330   DCHECK(prefs);
    331   prefs->SetBoolean(prefs::kHomePageIsNewTabPage, true);
    332   prefs->SetString(prefs::kHomePage, "http://google.com");
    333   prefs->SetBoolean(prefs::kShowHomeButton, false);
    334 
    335   ResetAndWait(ProfileResetter::HOMEPAGE, kDistributionConfig);
    336 
    337   EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
    338   EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
    339   EXPECT_TRUE(prefs->GetBoolean(prefs::kShowHomeButton));
    340 }
    341 
    342 TEST_F(ProfileResetterTest, ResetHomepagePartially) {
    343   PrefService* prefs = profile()->GetPrefs();
    344   DCHECK(prefs);
    345   prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
    346   prefs->SetString(prefs::kHomePage, "http://www.foo.com");
    347   prefs->SetBoolean(prefs::kShowHomeButton, true);
    348 
    349   ResetAndWait(ProfileResetter::HOMEPAGE);
    350 
    351   EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
    352   EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
    353   EXPECT_FALSE(prefs->GetBoolean(prefs::kShowHomeButton));
    354 }
    355 
    356 TEST_F(ProfileResetterTest, ResetContentSettings) {
    357   HostContentSettingsMap* host_content_settings_map =
    358       profile()->GetHostContentSettingsMap();
    359   DesktopNotificationService* notification_service =
    360       DesktopNotificationServiceFactory::GetForProfile(profile());
    361   ContentSettingsPattern pattern =
    362       ContentSettingsPattern::FromString("[*.]example.org");
    363   std::map<ContentSettingsType, ContentSetting> default_settings;
    364 
    365   for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
    366     if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
    367       notification_service->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
    368       notification_service->GrantPermission(GURL("http://foo.de"));
    369     } else if (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
    370                type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
    371                type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
    372       // These types are excluded because one can't call
    373       // GetDefaultContentSetting() for them.
    374     } else {
    375       ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
    376       ContentSetting default_setting =
    377           host_content_settings_map->GetDefaultContentSetting(content_type,
    378                                                               NULL);
    379       default_settings[content_type] = default_setting;
    380       ContentSetting wildcard_setting =
    381           default_setting == CONTENT_SETTING_BLOCK ? CONTENT_SETTING_ALLOW
    382                                                    : CONTENT_SETTING_BLOCK;
    383       ContentSetting site_setting =
    384           default_setting == CONTENT_SETTING_ALLOW ? CONTENT_SETTING_ALLOW
    385                                                    : CONTENT_SETTING_BLOCK;
    386       if (HostContentSettingsMap::IsSettingAllowedForType(
    387               profile()->GetPrefs(),
    388               wildcard_setting,
    389               content_type)) {
    390         host_content_settings_map->SetDefaultContentSetting(
    391             content_type,
    392             wildcard_setting);
    393       }
    394       if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) &&
    395           HostContentSettingsMap::IsSettingAllowedForType(
    396               profile()->GetPrefs(),
    397               site_setting,
    398               content_type)) {
    399         host_content_settings_map->SetContentSetting(
    400             pattern,
    401             ContentSettingsPattern::Wildcard(),
    402             content_type,
    403             std::string(),
    404             site_setting);
    405         ContentSettingsForOneType host_settings;
    406         host_content_settings_map->GetSettingsForOneType(
    407             content_type, std::string(), &host_settings);
    408         EXPECT_EQ(2U, host_settings.size());
    409       }
    410     }
    411   }
    412 
    413   ResetAndWait(ProfileResetter::CONTENT_SETTINGS);
    414 
    415   for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
    416     if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
    417       EXPECT_EQ(CONTENT_SETTING_ASK,
    418                 notification_service->GetDefaultContentSetting(NULL));
    419       EXPECT_EQ(CONTENT_SETTING_ASK,
    420                 notification_service->GetContentSetting(GURL("http://foo.de")));
    421     } else {
    422       ContentSettingsType content_type = static_cast<ContentSettingsType>(type);
    423       if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) ||
    424           type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
    425           content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
    426           content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS)
    427         continue;
    428       ContentSetting default_setting =
    429           host_content_settings_map->GetDefaultContentSetting(content_type,
    430                                                               NULL);
    431       EXPECT_TRUE(default_settings.count(content_type));
    432       EXPECT_EQ(default_settings[content_type], default_setting);
    433       if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
    434         ContentSetting site_setting =
    435             host_content_settings_map->GetContentSetting(
    436                 GURL("example.org"),
    437                 GURL(),
    438                 content_type,
    439                 std::string());
    440         EXPECT_EQ(default_setting, site_setting);
    441       }
    442 
    443       ContentSettingsForOneType host_settings;
    444       host_content_settings_map->GetSettingsForOneType(
    445           content_type, std::string(), &host_settings);
    446       EXPECT_EQ(1U, host_settings.size());
    447     }
    448   }
    449 }
    450 
    451 TEST_F(ProfileResetterTest, ResetExtensionsByDisabling) {
    452   service_->Init();
    453 
    454   base::ScopedTempDir temp_dir;
    455   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    456 
    457   scoped_refptr<Extension> theme =
    458       CreateExtension(ASCIIToUTF16("example1"),
    459                       temp_dir.path(),
    460                       Manifest::INVALID_LOCATION,
    461                       extensions::Manifest::TYPE_THEME,
    462                       false);
    463   service_->FinishInstallationForTest(theme.get());
    464   // Let ThemeService finish creating the theme pack.
    465   base::MessageLoop::current()->RunUntilIdle();
    466 
    467   ThemeService* theme_service =
    468       ThemeServiceFactory::GetForProfile(profile());
    469   EXPECT_FALSE(theme_service->UsingDefaultTheme());
    470 
    471   scoped_refptr<Extension> ext2 = CreateExtension(
    472       ASCIIToUTF16("example2"),
    473       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
    474       Manifest::INVALID_LOCATION,
    475       extensions::Manifest::TYPE_EXTENSION,
    476       false);
    477   service_->AddExtension(ext2.get());
    478   // Components and external policy extensions shouldn't be deleted.
    479   scoped_refptr<Extension> ext3 = CreateExtension(
    480       ASCIIToUTF16("example3"),
    481       base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
    482       Manifest::COMPONENT,
    483       extensions::Manifest::TYPE_EXTENSION,
    484       false);
    485   service_->AddExtension(ext3.get());
    486   scoped_refptr<Extension> ext4 =
    487       CreateExtension(ASCIIToUTF16("example4"),
    488                       base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
    489                       Manifest::EXTERNAL_POLICY_DOWNLOAD,
    490                       extensions::Manifest::TYPE_EXTENSION,
    491                       false);
    492   service_->AddExtension(ext4.get());
    493   EXPECT_EQ(4u, service_->extensions()->size());
    494 
    495   ResetAndWait(ProfileResetter::EXTENSIONS);
    496   EXPECT_EQ(2u, service_->extensions()->size());
    497   EXPECT_FALSE(service_->extensions()->Contains(theme->id()));
    498   EXPECT_FALSE(service_->extensions()->Contains(ext2->id()));
    499   EXPECT_TRUE(service_->extensions()->Contains(ext3->id()));
    500   EXPECT_TRUE(service_->extensions()->Contains(ext4->id()));
    501   EXPECT_TRUE(theme_service->UsingDefaultTheme());
    502 }
    503 
    504 TEST_F(ProfileResetterTest, ResetExtensionsByDisablingNonOrganic) {
    505   scoped_refptr<Extension> ext2 = CreateExtension(
    506       ASCIIToUTF16("example2"),
    507       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
    508       Manifest::INVALID_LOCATION,
    509       extensions::Manifest::TYPE_EXTENSION,
    510       false);
    511   service_->AddExtension(ext2.get());
    512   // Components and external policy extensions shouldn't be deleted.
    513   scoped_refptr<Extension> ext3 = CreateExtension(
    514       ASCIIToUTF16("example3"),
    515       base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
    516       Manifest::INVALID_LOCATION,
    517       extensions::Manifest::TYPE_EXTENSION,
    518       false);
    519   service_->AddExtension(ext3.get());
    520   EXPECT_EQ(2u, service_->extensions()->size());
    521 
    522   std::string master_prefs(kDistributionConfig);
    523   ReplaceString(&master_prefs, "placeholder_for_id", ext3->id());
    524 
    525   ResetAndWait(ProfileResetter::EXTENSIONS, master_prefs);
    526 
    527   EXPECT_EQ(1u, service_->extensions()->size());
    528   EXPECT_TRUE(service_->extensions()->Contains(ext3->id()));
    529 }
    530 
    531 TEST_F(ProfileResetterTest, ResetExtensionsAndDefaultApps) {
    532   service_->Init();
    533 
    534   base::ScopedTempDir temp_dir;
    535   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    536 
    537   scoped_refptr<Extension> ext1 =
    538       CreateExtension(ASCIIToUTF16("example1"),
    539                       temp_dir.path(),
    540                       Manifest::INVALID_LOCATION,
    541                       extensions::Manifest::TYPE_THEME,
    542                       false);
    543   service_->FinishInstallationForTest(ext1.get());
    544   // Let ThemeService finish creating the theme pack.
    545   base::MessageLoop::current()->RunUntilIdle();
    546 
    547   ThemeService* theme_service =
    548       ThemeServiceFactory::GetForProfile(profile());
    549   EXPECT_FALSE(theme_service->UsingDefaultTheme());
    550 
    551   scoped_refptr<Extension> ext2 =
    552       CreateExtension(ASCIIToUTF16("example2"),
    553                       base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
    554                       Manifest::INVALID_LOCATION,
    555                       extensions::Manifest::TYPE_EXTENSION,
    556                       false);
    557   service_->AddExtension(ext2.get());
    558 
    559   scoped_refptr<Extension> ext3 =
    560       CreateExtension(ASCIIToUTF16("example2"),
    561                       base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
    562                       Manifest::INVALID_LOCATION,
    563                       extensions::Manifest::TYPE_HOSTED_APP,
    564                       true);
    565   service_->AddExtension(ext3.get());
    566   EXPECT_EQ(3u, service_->extensions()->size());
    567 
    568   ResetAndWait(ProfileResetter::EXTENSIONS);
    569 
    570   EXPECT_EQ(1u, service_->extensions()->size());
    571   EXPECT_FALSE(service_->extensions()->Contains(ext1->id()));
    572   EXPECT_FALSE(service_->extensions()->Contains(ext2->id()));
    573   EXPECT_TRUE(service_->extensions()->Contains(ext3->id()));
    574   EXPECT_TRUE(theme_service->UsingDefaultTheme());
    575 }
    576 
    577 TEST_F(ProfileResetterTest, ResetStartPageNonOrganic) {
    578   PrefService* prefs = profile()->GetPrefs();
    579   DCHECK(prefs);
    580 
    581   SessionStartupPref startup_pref(SessionStartupPref::LAST);
    582   SessionStartupPref::SetStartupPref(prefs, startup_pref);
    583 
    584   ResetAndWait(ProfileResetter::STARTUP_PAGES, kDistributionConfig);
    585 
    586   startup_pref = SessionStartupPref::GetStartupPref(prefs);
    587   EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type);
    588   const GURL urls[] = {GURL("http://goo.gl"), GURL("http://foo.de")};
    589   EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls);
    590 }
    591 
    592 
    593 TEST_F(ProfileResetterTest, ResetStartPagePartially) {
    594   PrefService* prefs = profile()->GetPrefs();
    595   DCHECK(prefs);
    596 
    597   const GURL urls[] = {GURL("http://foo"), GURL("http://bar")};
    598   SessionStartupPref startup_pref(SessionStartupPref::URLS);
    599   startup_pref.urls.assign(urls, urls + arraysize(urls));
    600   SessionStartupPref::SetStartupPref(prefs, startup_pref);
    601 
    602   ResetAndWait(ProfileResetter::STARTUP_PAGES, std::string());
    603 
    604   startup_pref = SessionStartupPref::GetStartupPref(prefs);
    605   EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref.type);
    606   EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls);
    607 }
    608 
    609 TEST_F(PinnedTabsResetTest, ResetPinnedTabs) {
    610   scoped_refptr<Extension> extension_app = CreateExtension(
    611       ASCIIToUTF16("hello!"),
    612       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
    613       Manifest::INVALID_LOCATION,
    614       extensions::Manifest::TYPE_HOSTED_APP,
    615       false);
    616   scoped_ptr<content::WebContents> contents1(CreateWebContents());
    617   extensions::TabHelper::CreateForWebContents(contents1.get());
    618   extensions::TabHelper::FromWebContents(contents1.get())->
    619       SetExtensionApp(extension_app.get());
    620   scoped_ptr<content::WebContents> contents2(CreateWebContents());
    621   scoped_ptr<content::WebContents> contents3(CreateWebContents());
    622   scoped_ptr<content::WebContents> contents4(CreateWebContents());
    623   TabStripModel* tab_strip_model = browser()->tab_strip_model();
    624 
    625   tab_strip_model->AppendWebContents(contents4.get(), true);
    626   tab_strip_model->AppendWebContents(contents3.get(), true);
    627   tab_strip_model->AppendWebContents(contents2.get(), true);
    628   tab_strip_model->SetTabPinned(2, true);
    629   tab_strip_model->AppendWebContents(contents1.get(), true);
    630   tab_strip_model->SetTabPinned(3, true);
    631 
    632   EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(0));
    633   EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(1));
    634   EXPECT_EQ(contents3, tab_strip_model->GetWebContentsAt(2));
    635   EXPECT_EQ(contents4, tab_strip_model->GetWebContentsAt(3));
    636   EXPECT_EQ(3, tab_strip_model->IndexOfFirstNonMiniTab());
    637 
    638   ResetAndWait(ProfileResetter::PINNED_TABS);
    639 
    640   EXPECT_EQ(contents1, tab_strip_model->GetWebContentsAt(0));
    641   EXPECT_EQ(contents2, tab_strip_model->GetWebContentsAt(1));
    642   EXPECT_EQ(contents3, tab_strip_model->GetWebContentsAt(2));
    643   EXPECT_EQ(contents4, tab_strip_model->GetWebContentsAt(3));
    644   EXPECT_EQ(1, tab_strip_model->IndexOfFirstNonMiniTab());
    645 }
    646 
    647 TEST_F(ProfileResetterTest, ResetFewFlags) {
    648   // mock_object_ is a StrictMock, so we verify that it is called only once.
    649   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
    650                ProfileResetter::HOMEPAGE |
    651                ProfileResetter::CONTENT_SETTINGS);
    652 }
    653 
    654 // Tries to load unavailable config file.
    655 TEST_F(ConfigParserTest, NoConnectivity) {
    656   const GURL url("http://test");
    657   factory().SetFakeResponse(url, "", net::HTTP_INTERNAL_SERVER_ERROR,
    658                             net::URLRequestStatus::FAILED);
    659 
    660   scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
    661   EXPECT_FALSE(fetcher->GetSettings());
    662 }
    663 
    664 // Tries to load available config file.
    665 TEST_F(ConfigParserTest, ParseConfig) {
    666   const GURL url("http://test");
    667   std::string xml_config(kXmlConfig);
    668   ReplaceString(&xml_config, "placeholder_for_data", kDistributionConfig);
    669   ReplaceString(&xml_config,
    670                 "placeholder_for_id",
    671                 "abbaabbaabbaabbaabbaabbaabbaabba");
    672   factory().SetFakeResponse(url, xml_config, net::HTTP_OK,
    673                             net::URLRequestStatus::SUCCESS);
    674 
    675   scoped_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
    676   scoped_ptr<BrandcodedDefaultSettings> settings = fetcher->GetSettings();
    677   ASSERT_TRUE(settings);
    678 
    679   std::vector<std::string> extension_ids;
    680   EXPECT_TRUE(settings->GetExtensions(&extension_ids));
    681   EXPECT_EQ(1u, extension_ids.size());
    682   EXPECT_EQ("abbaabbaabbaabbaabbaabbaabbaabba", extension_ids[0]);
    683 
    684   std::string homepage;
    685   EXPECT_TRUE(settings->GetHomepage(&homepage));
    686   EXPECT_EQ("http://www.foo.com", homepage);
    687 
    688   scoped_ptr<base::ListValue> startup_list(
    689       settings->GetUrlsToRestoreOnStartup());
    690   EXPECT_TRUE(startup_list);
    691   std::vector<std::string> startup_pages;
    692   for (base::ListValue::iterator i = startup_list->begin();
    693        i != startup_list->end(); ++i) {
    694     std::string url;
    695     EXPECT_TRUE((*i)->GetAsString(&url));
    696     startup_pages.push_back(url);
    697   }
    698   ASSERT_EQ(2u, startup_pages.size());
    699   EXPECT_EQ("http://goo.gl", startup_pages[0]);
    700   EXPECT_EQ("http://foo.de", startup_pages[1]);
    701 }
    702 
    703 TEST_F(ProfileResetterTest, CheckSnapshots) {
    704   ResettableSettingsSnapshot empty_snap(profile());
    705   EXPECT_EQ(0, empty_snap.FindDifferentFields(empty_snap));
    706 
    707   scoped_refptr<Extension> ext = CreateExtension(
    708       ASCIIToUTF16("example"),
    709       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
    710       Manifest::INVALID_LOCATION,
    711       extensions::Manifest::TYPE_EXTENSION,
    712       false);
    713   ASSERT_TRUE(ext);
    714   service_->AddExtension(ext.get());
    715 
    716   std::string master_prefs(kDistributionConfig);
    717   std::string ext_id = ext->id();
    718   ReplaceString(&master_prefs, "placeholder_for_id", ext_id);
    719 
    720   // Reset to non organic defaults.
    721   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
    722                ProfileResetter::HOMEPAGE |
    723                ProfileResetter::STARTUP_PAGES,
    724                master_prefs);
    725 
    726   ResettableSettingsSnapshot nonorganic_snap(profile());
    727   EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS,
    728             empty_snap.FindDifferentFields(nonorganic_snap));
    729   empty_snap.Subtract(nonorganic_snap);
    730   EXPECT_TRUE(empty_snap.startup_urls().empty());
    731   EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
    732             empty_snap.startup_type());
    733   EXPECT_TRUE(empty_snap.homepage().empty());
    734   EXPECT_TRUE(empty_snap.homepage_is_ntp());
    735   EXPECT_NE(std::string::npos, empty_snap.dse_url().find("{google:baseURL}"));
    736   EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(),
    737             empty_snap.enabled_extensions());
    738 
    739   // Reset to organic defaults.
    740   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
    741                ProfileResetter::HOMEPAGE |
    742                ProfileResetter::STARTUP_PAGES |
    743                ProfileResetter::EXTENSIONS);
    744 
    745   ResettableSettingsSnapshot organic_snap(profile());
    746   EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS,
    747             nonorganic_snap.FindDifferentFields(organic_snap));
    748   nonorganic_snap.Subtract(organic_snap);
    749   const GURL urls[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
    750   EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)),
    751             nonorganic_snap.startup_urls());
    752   EXPECT_EQ(SessionStartupPref::URLS, nonorganic_snap.startup_type());
    753   EXPECT_EQ("http://www.foo.com", nonorganic_snap.homepage());
    754   EXPECT_FALSE(nonorganic_snap.homepage_is_ntp());
    755   EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap.dse_url());
    756   EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(
    757       1, std::make_pair(ext_id, "example")),
    758       nonorganic_snap.enabled_extensions());
    759 }
    760 
    761 TEST_F(ProfileResetterTest, FeedbackSerializtionTest) {
    762   // Reset to non organic defaults.
    763   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
    764                ProfileResetter::HOMEPAGE |
    765                ProfileResetter::STARTUP_PAGES,
    766                kDistributionConfig);
    767 
    768   scoped_refptr<Extension> ext = CreateExtension(
    769       ASCIIToUTF16("example"),
    770       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
    771       Manifest::INVALID_LOCATION,
    772       extensions::Manifest::TYPE_EXTENSION,
    773       false);
    774   ASSERT_TRUE(ext);
    775   service_->AddExtension(ext.get());
    776 
    777   const ResettableSettingsSnapshot nonorganic_snap(profile());
    778 
    779   COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 15,
    780                  expand_this_test);
    781   for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS;
    782        ++field_mask) {
    783     std::string report = SerializeSettingsReport(nonorganic_snap, field_mask);
    784     JSONStringValueSerializer json(report);
    785     std::string error;
    786     scoped_ptr<base::Value> root(json.Deserialize(NULL, &error));
    787     ASSERT_TRUE(root) << error;
    788     ASSERT_TRUE(root->IsType(base::Value::TYPE_DICTIONARY)) << error;
    789 
    790     base::DictionaryValue* dict =
    791         static_cast<base::DictionaryValue*>(root.get());
    792 
    793     ListValue* startup_urls = NULL;
    794     int startup_type = 0;
    795     std::string homepage;
    796     bool homepage_is_ntp = true;
    797     std::string default_search_engine;
    798     ListValue* extensions;
    799 
    800     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
    801               dict->GetList("startup_urls", &startup_urls));
    802     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
    803               dict->GetInteger("startup_type", &startup_type));
    804     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
    805               dict->GetString("homepage", &homepage));
    806     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
    807               dict->GetBoolean("homepage_is_ntp", &homepage_is_ntp));
    808     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL),
    809               dict->GetString("default_search_engine", &default_search_engine));
    810     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::EXTENSIONS),
    811               dict->GetList("enabled_extensions", &extensions));
    812   }
    813 }
    814 
    815 // Make sure GetReadableFeedback handles non-ascii letters.
    816 TEST_F(ProfileResetterTest, GetReadableFeedback) {
    817   scoped_refptr<Extension> ext = CreateExtension(
    818       WideToUTF16(L"Tisto"),
    819       base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
    820       Manifest::INVALID_LOCATION,
    821       extensions::Manifest::TYPE_EXTENSION,
    822       false);
    823   ASSERT_TRUE(ext);
    824   service_->AddExtension(ext.get());
    825 
    826   PrefService* prefs = profile()->GetPrefs();
    827   DCHECK(prefs);
    828   // The URL is "http://.".
    829   std::wstring url(L"http://"
    830     L"\u0440\u043e\u0441\u0441\u0438\u044f.\u0440\u0444");
    831   prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
    832   prefs->SetString(prefs::kHomePage, WideToUTF8(url));
    833 
    834   SessionStartupPref startup_pref(SessionStartupPref::URLS);
    835   startup_pref.urls.push_back(GURL(WideToUTF8(url)));
    836   SessionStartupPref::SetStartupPref(prefs, startup_pref);
    837 
    838   // The homepage and the startup page are in punycode. They are unreadable.
    839   // Trying to find the extension name.
    840   scoped_ptr<base::ListValue> list(GetReadableFeedback(profile()));
    841   ASSERT_TRUE(list);
    842   for (size_t i = 0; i < list->GetSize(); ++i) {
    843     DictionaryValue* dict = NULL;
    844     ASSERT_TRUE(list->GetDictionary(i, &dict));
    845     std::string value;
    846     ASSERT_TRUE(dict->GetString("key", &value));
    847     if (value == "Extensions") {
    848       base::string16 extensions;
    849       EXPECT_TRUE(dict->GetString("value", &extensions));
    850       EXPECT_EQ(WideToUTF16(L"Tisto"), extensions);
    851     }
    852   }
    853 }
    854 
    855 }  // namespace
    856