Home | History | Annotate | Download | only in chromeos
      1 // Copyright (c) 2011 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/chromeos/customization_document.h"
      6 
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/prefs/testing_pref_service.h"
      9 #include "base/run_loop.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
     12 #include "chrome/browser/extensions/external_provider_impl.h"
     13 #include "chrome/browser/prefs/browser_prefs.h"
     14 #include "chrome/browser/prefs/pref_service_mock_factory.h"
     15 #include "chrome/browser/prefs/pref_service_syncable.h"
     16 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
     17 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
     18 #include "chrome/test/base/testing_browser_process.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "chromeos/dbus/dbus_thread_manager.h"
     21 #include "chromeos/network/network_handler.h"
     22 #include "chromeos/network/network_state.h"
     23 #include "chromeos/network/network_state_handler.h"
     24 #include "chromeos/system/mock_statistics_provider.h"
     25 #include "components/pref_registry/pref_registry_syncable.h"
     26 #include "content/public/test/test_browser_thread_bundle.h"
     27 #include "extensions/common/extension.h"
     28 #include "extensions/common/manifest.h"
     29 #include "net/http/http_response_headers.h"
     30 #include "net/http/http_status_code.h"
     31 #include "net/url_request/test_url_fetcher_factory.h"
     32 #include "net/url_request/url_request_status.h"
     33 #include "testing/gmock/include/gmock/gmock.h"
     34 #include "testing/gtest/include/gtest/gtest.h"
     35 
     36 using ::testing::Exactly;
     37 using ::testing::Invoke;
     38 using ::testing::Mock;
     39 using ::testing::_;
     40 
     41 namespace {
     42 
     43 const char kGoodStartupManifest[] =
     44     "{"
     45     "  \"version\": \"1.0\","
     46     "  \"initial_locale\" : \"en-US\","
     47     "  \"initial_timezone\" : \"US/Pacific\","
     48     "  \"keyboard_layout\" : \"xkb:us::eng\","
     49     "  \"setup_content\" : {"
     50     "    \"en-US\" : {"
     51     "      \"eula_page\" : \"file:///opt/oem/eula/en-US/eula.html\","
     52     "    },"
     53     "    \"ru-RU\" : {"
     54     "      \"eula_page\" : \"file:///opt/oem/eula/ru-RU/eula.html\","
     55     "    },"
     56     "    \"default\" : {"
     57     "      \"eula_page\" : \"file:///opt/oem/eula/en/eula.html\","
     58     "    },"
     59     "  },"
     60     "  \"hwid_map\" : ["
     61     "    {"
     62     "      \"hwid_mask\": \"ZGA*34\","
     63     "      \"initial_locale\" : \"ja\","
     64     "      \"initial_timezone\" : \"Asia/Tokyo\","
     65     "      \"keyboard_layout\" : \"mozc-jp\","
     66     "    },"
     67     "    {"
     68     "      \"hwid_mask\": \"Mario 1?3*\","
     69     "      \"initial_locale\" : \"ru-RU\","
     70     "      \"initial_timezone\" : \"Europe/Moscow\","
     71     "      \"keyboard_layout\" : \"xkb:ru::rus\","
     72     "    },"
     73     "  ],"
     74     "}";
     75 
     76 const char kBadManifest[] = "{\"version\": \"1\"}";
     77 
     78 const char kGoodServicesManifest[] =
     79     "{"
     80     "  \"version\": \"1.0\","
     81     "  \"default_apps\": [\n"
     82     "    \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n"
     83     "    \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n"
     84     "  ],\n"
     85     "  \"localized_content\": {\n"
     86     "    \"en-US\": {\n"
     87     "      \"default_apps_folder_name\": \"EN-US OEM Name\"\n"
     88     "    },\n"
     89     "    \"en\": {\n"
     90     "      \"default_apps_folder_name\": \"EN OEM Name\"\n"
     91     "    },\n"
     92     "    \"default\": {\n"
     93     "      \"default_apps_folder_name\": \"Default OEM Name\"\n"
     94     "    }\n"
     95     "  }\n"
     96     "}";
     97 
     98 const char kDummyCustomizationID[] = "test-dummy";
     99 
    100 }  // anonymous namespace
    101 
    102 namespace chromeos {
    103 
    104 using ::testing::_;
    105 using ::testing::DoAll;
    106 using ::testing::NotNull;
    107 using ::testing::Return;
    108 using ::testing::SetArgumentPointee;
    109 
    110 TEST(StartupCustomizationDocumentTest, Basic) {
    111   system::MockStatisticsProvider mock_statistics_provider;
    112   EXPECT_CALL(mock_statistics_provider, GetMachineStatistic(_, NotNull()))
    113       .WillRepeatedly(Return(false));
    114   EXPECT_CALL(mock_statistics_provider,
    115       GetMachineStatistic(std::string("hardware_class"), NotNull()))
    116           .WillOnce(DoAll(SetArgumentPointee<1>(std::string("Mario 12345")),
    117                           Return(true)));
    118   StartupCustomizationDocument customization(&mock_statistics_provider,
    119                                              kGoodStartupManifest);
    120   EXPECT_EQ("ru-RU", customization.initial_locale());
    121   EXPECT_EQ("Europe/Moscow", customization.initial_timezone());
    122   EXPECT_EQ("xkb:ru::rus", customization.keyboard_layout());
    123 
    124   EXPECT_EQ("file:///opt/oem/eula/en-US/eula.html",
    125             customization.GetEULAPage("en-US"));
    126   EXPECT_EQ("file:///opt/oem/eula/ru-RU/eula.html",
    127             customization.GetEULAPage("ru-RU"));
    128   EXPECT_EQ("file:///opt/oem/eula/en/eula.html",
    129             customization.GetEULAPage("ja"));
    130 }
    131 
    132 TEST(StartupCustomizationDocumentTest, VPD) {
    133   system::MockStatisticsProvider mock_statistics_provider;
    134   EXPECT_CALL(mock_statistics_provider,
    135       GetMachineStatistic(std::string("hardware_class"), NotNull()))
    136           .WillOnce(DoAll(SetArgumentPointee<1>(std::string("Mario 12345")),
    137                           Return(true)));
    138   EXPECT_CALL(mock_statistics_provider,
    139       GetMachineStatistic(std::string("initial_locale"), NotNull()))
    140           .WillOnce(DoAll(SetArgumentPointee<1>(std::string("ja")),
    141                           Return(true)));
    142   EXPECT_CALL(mock_statistics_provider,
    143       GetMachineStatistic(std::string("initial_timezone"), NotNull()))
    144           .WillOnce(DoAll(SetArgumentPointee<1>(std::string("Asia/Tokyo")),
    145                           Return(true)));
    146   EXPECT_CALL(mock_statistics_provider,
    147       GetMachineStatistic(std::string("keyboard_layout"), NotNull()))
    148           .WillOnce(DoAll(SetArgumentPointee<1>(std::string("mozc-jp")),
    149                           Return(true)));
    150   StartupCustomizationDocument customization(&mock_statistics_provider,
    151                                              kGoodStartupManifest);
    152   EXPECT_TRUE(customization.IsReady());
    153   EXPECT_EQ("ja", customization.initial_locale());
    154   EXPECT_EQ("Asia/Tokyo", customization.initial_timezone());
    155   EXPECT_EQ("mozc-jp", customization.keyboard_layout());
    156 }
    157 
    158 TEST(StartupCustomizationDocumentTest, BadManifest) {
    159   system::MockStatisticsProvider mock_statistics_provider;
    160   StartupCustomizationDocument customization(&mock_statistics_provider,
    161                                              kBadManifest);
    162   EXPECT_FALSE(customization.IsReady());
    163 }
    164 
    165 class TestURLFetcherCallback {
    166  public:
    167   scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
    168       const GURL& url,
    169       net::URLFetcherDelegate* d,
    170       const std::string& response_data,
    171       net::HttpStatusCode response_code,
    172       net::URLRequestStatus::Status status) {
    173     scoped_ptr<net::FakeURLFetcher> fetcher(
    174         new net::FakeURLFetcher(url, d, response_data, response_code, status));
    175     OnRequestCreate(url, fetcher.get());
    176     return fetcher.Pass();
    177   }
    178   MOCK_METHOD2(OnRequestCreate,
    179                void(const GURL&, net::FakeURLFetcher*));
    180 };
    181 
    182 void AddMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher) {
    183   scoped_refptr<net::HttpResponseHeaders> download_headers =
    184       new net::HttpResponseHeaders("");
    185   download_headers->AddHeader("Content-Type: application/json");
    186   fetcher->set_response_headers(download_headers);
    187 }
    188 
    189 class MockExternalProviderVisitor
    190     : public extensions::ExternalProviderInterface::VisitorInterface {
    191  public:
    192   MockExternalProviderVisitor() {}
    193 
    194   MOCK_METHOD6(OnExternalExtensionFileFound,
    195                bool(const std::string&,
    196                     const base::Version*,
    197                     const base::FilePath&,
    198                     extensions::Manifest::Location,
    199                     int,
    200                     bool));
    201   MOCK_METHOD6(OnExternalExtensionUpdateUrlFound,
    202                bool(const std::string&,
    203                     const std::string&,
    204                     const GURL&,
    205                     extensions::Manifest::Location,
    206                     int,
    207                     bool));
    208   MOCK_METHOD1(OnExternalProviderReady,
    209                void(const extensions::ExternalProviderInterface* provider));
    210 };
    211 
    212 class ServicesCustomizationDocumentTest : public testing::Test {
    213  protected:
    214   ServicesCustomizationDocumentTest()
    215     : factory_(NULL,
    216                base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
    217                base::Unretained(&url_callback_))) {
    218   }
    219 
    220   // testing::Test:
    221   virtual void SetUp() OVERRIDE {
    222     ServicesCustomizationDocument::InitializeForTesting();
    223 
    224     EXPECT_CALL(mock_statistics_provider_, GetMachineStatistic(_, NotNull()))
    225         .WillRepeatedly(Return(false));
    226     chromeos::system::StatisticsProvider::SetTestProvider(
    227         &mock_statistics_provider_);
    228 
    229     DBusThreadManager::InitializeWithStub();
    230     NetworkHandler::Initialize();
    231     RunUntilIdle();
    232     const NetworkState* default_network =
    233         NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
    234     std::string default_network_path =
    235         default_network ? default_network->path() : "";
    236 
    237     NetworkPortalDetector::InitializeForTesting(&network_portal_detector_);
    238     NetworkPortalDetector::CaptivePortalState online_state;
    239     online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
    240     online_state.response_code = 204;
    241     network_portal_detector_.SetDefaultNetworkPathForTesting(
    242         default_network_path,
    243         default_network ? default_network->guid() : "");
    244     network_portal_detector_.SetDetectionResultsForTesting(
    245         default_network_path, online_state);
    246 
    247     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
    248     ServicesCustomizationDocument::RegisterPrefs(local_state_.registry());
    249   }
    250 
    251   virtual void TearDown() OVERRIDE {
    252     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
    253     NetworkHandler::Shutdown();
    254     DBusThreadManager::Shutdown();
    255     NetworkPortalDetector::InitializeForTesting(NULL);
    256     chromeos::system::StatisticsProvider::SetTestProvider(NULL);
    257 
    258     ServicesCustomizationDocument::ShutdownForTesting();
    259   }
    260 
    261   void RunUntilIdle() {
    262     base::RunLoop().RunUntilIdle();
    263   }
    264 
    265   void AddCustomizationIdToVp(const std::string& id) {
    266     EXPECT_CALL(mock_statistics_provider_,
    267         GetMachineStatistic(system::kCustomizationIdKey, NotNull()))
    268             .WillOnce(DoAll(SetArgumentPointee<1>(id),
    269                             Return(true)));
    270   }
    271 
    272   void AddExpectedManifest(const std::string& id,
    273                            const std::string& manifest) {
    274     GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
    275                                 id.c_str()));
    276     factory_.SetFakeResponse(url,
    277                              manifest,
    278                              net::HTTP_OK,
    279                              net::URLRequestStatus::SUCCESS);
    280     EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
    281       .Times(Exactly(1))
    282       .WillRepeatedly(Invoke(AddMimeHeader));
    283   }
    284 
    285   void AddManifestNotFound(const std::string& id) {
    286     GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
    287                                 id.c_str()));
    288     factory_.SetFakeResponse(url,
    289                              std::string(),
    290                              net::HTTP_NOT_FOUND,
    291                              net::URLRequestStatus::SUCCESS);
    292     EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
    293       .Times(Exactly(1))
    294       .WillRepeatedly(Invoke(AddMimeHeader));
    295   }
    296 
    297   scoped_ptr<TestingProfile> CreateProfile() {
    298     TestingProfile::Builder profile_builder;
    299     PrefServiceMockFactory factory;
    300     scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
    301         new user_prefs::PrefRegistrySyncable);
    302     scoped_ptr<PrefServiceSyncable> prefs(
    303         factory.CreateSyncable(registry.get()));
    304     chrome::RegisterUserProfilePrefs(registry.get());
    305     profile_builder.SetPrefService(prefs.Pass());
    306     return profile_builder.Build();
    307   }
    308 
    309  private:
    310   system::MockStatisticsProvider mock_statistics_provider_;
    311   content::TestBrowserThreadBundle thread_bundle_;
    312   TestingPrefServiceSimple local_state_;
    313   TestURLFetcherCallback url_callback_;
    314   net::FakeURLFetcherFactory factory_;
    315   NetworkPortalDetectorTestImpl network_portal_detector_;
    316 };
    317 
    318 TEST_F(ServicesCustomizationDocumentTest, Basic) {
    319   AddCustomizationIdToVp(kDummyCustomizationID);
    320   AddExpectedManifest(kDummyCustomizationID, kGoodServicesManifest);
    321 
    322   ServicesCustomizationDocument* doc =
    323       ServicesCustomizationDocument::GetInstance();
    324   EXPECT_FALSE(doc->IsReady());
    325 
    326   doc->StartFetching();
    327   RunUntilIdle();
    328   EXPECT_TRUE(doc->IsReady());
    329 
    330   GURL wallpaper_url;
    331   EXPECT_FALSE(doc->GetDefaultWallpaperUrl(&wallpaper_url));
    332   EXPECT_EQ("", wallpaper_url.spec());
    333 
    334   std::vector<std::string> default_apps;
    335   EXPECT_TRUE(doc->GetDefaultApps(&default_apps));
    336   ASSERT_EQ(default_apps.size(), 2u);
    337 
    338   EXPECT_EQ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", default_apps[0]);
    339   EXPECT_EQ("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", default_apps[1]);
    340 
    341   EXPECT_EQ("EN-US OEM Name", doc->GetOemAppsFolderName("en-US"));
    342   EXPECT_EQ("EN OEM Name", doc->GetOemAppsFolderName("en"));
    343   EXPECT_EQ("Default OEM Name", doc->GetOemAppsFolderName("ru"));
    344 }
    345 
    346 TEST_F(ServicesCustomizationDocumentTest, NoCustomizationIdInVpd) {
    347   ServicesCustomizationDocument* doc =
    348       ServicesCustomizationDocument::GetInstance();
    349   EXPECT_FALSE(doc->IsReady());
    350 
    351   scoped_ptr<TestingProfile> profile = CreateProfile();
    352   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
    353   EXPECT_TRUE(loader);
    354 
    355   MockExternalProviderVisitor visitor;
    356   scoped_ptr<extensions::ExternalProviderImpl> provider(
    357       new extensions::ExternalProviderImpl(
    358           &visitor,
    359           loader,
    360           profile.get(),
    361           extensions::Manifest::EXTERNAL_PREF,
    362           extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
    363           extensions::Extension::FROM_WEBSTORE |
    364               extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
    365 
    366   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
    367       .Times(0);
    368   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
    369       .Times(0);
    370   EXPECT_CALL(visitor, OnExternalProviderReady(_))
    371       .Times(1);
    372 
    373   // Manually request a load.
    374   RunUntilIdle();
    375   loader->StartLoading();
    376   Mock::VerifyAndClearExpectations(&visitor);
    377 
    378   RunUntilIdle();
    379   // Empty customization is used when there is no customization ID in VPD.
    380   EXPECT_TRUE(doc->IsReady());
    381 }
    382 
    383 TEST_F(ServicesCustomizationDocumentTest, DefaultApps) {
    384   AddCustomizationIdToVp(kDummyCustomizationID);
    385   AddExpectedManifest(kDummyCustomizationID, kGoodServicesManifest);
    386 
    387   ServicesCustomizationDocument* doc =
    388       ServicesCustomizationDocument::GetInstance();
    389   EXPECT_FALSE(doc->IsReady());
    390 
    391   scoped_ptr<TestingProfile> profile = CreateProfile();
    392   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
    393   EXPECT_TRUE(loader);
    394 
    395   app_list::AppListSyncableServiceFactory::GetInstance()->
    396       SetTestingFactoryAndUse(
    397           profile.get(),
    398           &app_list::AppListSyncableServiceFactory::BuildInstanceFor);
    399 
    400   MockExternalProviderVisitor visitor;
    401   scoped_ptr<extensions::ExternalProviderImpl> provider(
    402       new extensions::ExternalProviderImpl(
    403           &visitor,
    404           loader,
    405           profile.get(),
    406           extensions::Manifest::EXTERNAL_PREF,
    407           extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
    408           extensions::Extension::FROM_WEBSTORE |
    409               extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
    410 
    411   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
    412       .Times(0);
    413   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
    414       .Times(0);
    415   EXPECT_CALL(visitor, OnExternalProviderReady(_))
    416       .Times(1);
    417 
    418   // Manually request a load.
    419   loader->StartLoading();
    420   Mock::VerifyAndClearExpectations(&visitor);
    421 
    422   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
    423       .Times(0);
    424   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
    425       .Times(2);
    426   EXPECT_CALL(visitor, OnExternalProviderReady(_))
    427       .Times(1);
    428 
    429   RunUntilIdle();
    430   EXPECT_TRUE(doc->IsReady());
    431 
    432   app_list::AppListSyncableService* service =
    433       app_list::AppListSyncableServiceFactory::GetForProfile(profile.get());
    434   ASSERT_TRUE(service);
    435   EXPECT_EQ("EN OEM Name", service->GetOemFolderNameForTest());
    436 }
    437 
    438 TEST_F(ServicesCustomizationDocumentTest, CustomizationManifestNotFound) {
    439   AddCustomizationIdToVp(kDummyCustomizationID);
    440   AddManifestNotFound(kDummyCustomizationID);
    441 
    442   ServicesCustomizationDocument* doc =
    443       ServicesCustomizationDocument::GetInstance();
    444   EXPECT_FALSE(doc->IsReady());
    445 
    446   scoped_ptr<TestingProfile> profile = CreateProfile();
    447   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
    448   EXPECT_TRUE(loader);
    449 
    450   MockExternalProviderVisitor visitor;
    451   scoped_ptr<extensions::ExternalProviderImpl> provider(
    452       new extensions::ExternalProviderImpl(
    453           &visitor,
    454           loader,
    455           profile.get(),
    456           extensions::Manifest::EXTERNAL_PREF,
    457           extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
    458           extensions::Extension::FROM_WEBSTORE |
    459               extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
    460 
    461   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
    462       .Times(0);
    463   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
    464       .Times(0);
    465   EXPECT_CALL(visitor, OnExternalProviderReady(_))
    466       .Times(1);
    467 
    468   // Manually request a load.
    469   loader->StartLoading();
    470   Mock::VerifyAndClearExpectations(&visitor);
    471 
    472   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
    473       .Times(0);
    474   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
    475       .Times(0);
    476   EXPECT_CALL(visitor, OnExternalProviderReady(_))
    477       .Times(1);
    478 
    479   RunUntilIdle();
    480   EXPECT_TRUE(doc->IsReady());
    481 }
    482 
    483 }  // namespace chromeos
    484