• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(StartupCustomizationDocumentTest,Basic)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 
TEST(StartupCustomizationDocumentTest,VPD)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 
TEST(StartupCustomizationDocumentTest,BadManifest)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:
CreateURLFetcher(const GURL & url,net::URLFetcherDelegate * d,const std::string & response_data,net::HttpStatusCode response_code,net::URLRequestStatus::Status status)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 
AddMimeHeader(const GURL & url,net::FakeURLFetcher * fetcher)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:
MockExternalProviderVisitor()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:
ServicesCustomizationDocumentTest()214   ServicesCustomizationDocumentTest()
215     : factory_(NULL,
216                base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
217                base::Unretained(&url_callback_))) {
218   }
219 
220   // testing::Test:
SetUp()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::Initialize();
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     std::string guid =
242         default_network ? default_network->guid() : std::string();
243     network_portal_detector_.SetDefaultNetworkForTesting(guid);
244     if (!guid.empty()) {
245       network_portal_detector_.SetDetectionResultsForTesting(
246           guid, online_state);
247     }
248 
249     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
250     ServicesCustomizationDocument::RegisterPrefs(local_state_.registry());
251   }
252 
TearDown()253   virtual void TearDown() OVERRIDE {
254     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
255     NetworkHandler::Shutdown();
256     DBusThreadManager::Shutdown();
257     NetworkPortalDetector::InitializeForTesting(NULL);
258     chromeos::system::StatisticsProvider::SetTestProvider(NULL);
259 
260     ServicesCustomizationDocument::ShutdownForTesting();
261   }
262 
RunUntilIdle()263   void RunUntilIdle() {
264     base::RunLoop().RunUntilIdle();
265   }
266 
AddCustomizationIdToVp(const std::string & id)267   void AddCustomizationIdToVp(const std::string& id) {
268     EXPECT_CALL(mock_statistics_provider_,
269         GetMachineStatistic(system::kCustomizationIdKey, NotNull()))
270             .WillOnce(DoAll(SetArgumentPointee<1>(id),
271                             Return(true)));
272   }
273 
AddExpectedManifest(const std::string & id,const std::string & manifest)274   void AddExpectedManifest(const std::string& id,
275                            const std::string& manifest) {
276     GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
277                                 id.c_str()));
278     factory_.SetFakeResponse(url,
279                              manifest,
280                              net::HTTP_OK,
281                              net::URLRequestStatus::SUCCESS);
282     EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
283       .Times(Exactly(1))
284       .WillRepeatedly(Invoke(AddMimeHeader));
285   }
286 
AddManifestNotFound(const std::string & id)287   void AddManifestNotFound(const std::string& id) {
288     GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
289                                 id.c_str()));
290     factory_.SetFakeResponse(url,
291                              std::string(),
292                              net::HTTP_NOT_FOUND,
293                              net::URLRequestStatus::SUCCESS);
294     EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
295       .Times(Exactly(1))
296       .WillRepeatedly(Invoke(AddMimeHeader));
297   }
298 
CreateProfile()299   scoped_ptr<TestingProfile> CreateProfile() {
300     TestingProfile::Builder profile_builder;
301     PrefServiceMockFactory factory;
302     scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
303         new user_prefs::PrefRegistrySyncable);
304     scoped_ptr<PrefServiceSyncable> prefs(
305         factory.CreateSyncable(registry.get()));
306     chrome::RegisterUserProfilePrefs(registry.get());
307     profile_builder.SetPrefService(prefs.Pass());
308     return profile_builder.Build();
309   }
310 
311  private:
312   system::MockStatisticsProvider mock_statistics_provider_;
313   content::TestBrowserThreadBundle thread_bundle_;
314   TestingPrefServiceSimple local_state_;
315   TestURLFetcherCallback url_callback_;
316   net::FakeURLFetcherFactory factory_;
317   NetworkPortalDetectorTestImpl network_portal_detector_;
318 };
319 
TEST_F(ServicesCustomizationDocumentTest,Basic)320 TEST_F(ServicesCustomizationDocumentTest, Basic) {
321   AddCustomizationIdToVp(kDummyCustomizationID);
322   AddExpectedManifest(kDummyCustomizationID, kGoodServicesManifest);
323 
324   ServicesCustomizationDocument* doc =
325       ServicesCustomizationDocument::GetInstance();
326   EXPECT_FALSE(doc->IsReady());
327 
328   doc->StartFetching();
329   RunUntilIdle();
330   EXPECT_TRUE(doc->IsReady());
331 
332   GURL wallpaper_url;
333   EXPECT_FALSE(doc->GetDefaultWallpaperUrl(&wallpaper_url));
334   EXPECT_EQ("", wallpaper_url.spec());
335 
336   std::vector<std::string> default_apps;
337   EXPECT_TRUE(doc->GetDefaultApps(&default_apps));
338   ASSERT_EQ(default_apps.size(), 2u);
339 
340   EXPECT_EQ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", default_apps[0]);
341   EXPECT_EQ("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", default_apps[1]);
342 
343   EXPECT_EQ("EN-US OEM Name", doc->GetOemAppsFolderName("en-US"));
344   EXPECT_EQ("EN OEM Name", doc->GetOemAppsFolderName("en"));
345   EXPECT_EQ("Default OEM Name", doc->GetOemAppsFolderName("ru"));
346 }
347 
TEST_F(ServicesCustomizationDocumentTest,NoCustomizationIdInVpd)348 TEST_F(ServicesCustomizationDocumentTest, NoCustomizationIdInVpd) {
349   ServicesCustomizationDocument* doc =
350       ServicesCustomizationDocument::GetInstance();
351   EXPECT_FALSE(doc->IsReady());
352 
353   scoped_ptr<TestingProfile> profile = CreateProfile();
354   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
355   EXPECT_TRUE(loader);
356 
357   MockExternalProviderVisitor visitor;
358   scoped_ptr<extensions::ExternalProviderImpl> provider(
359       new extensions::ExternalProviderImpl(
360           &visitor,
361           loader,
362           profile.get(),
363           extensions::Manifest::EXTERNAL_PREF,
364           extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
365           extensions::Extension::FROM_WEBSTORE |
366               extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
367 
368   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
369       .Times(0);
370   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
371       .Times(0);
372   EXPECT_CALL(visitor, OnExternalProviderReady(_))
373       .Times(1);
374 
375   // Manually request a load.
376   RunUntilIdle();
377   loader->StartLoading();
378   Mock::VerifyAndClearExpectations(&visitor);
379 
380   RunUntilIdle();
381   // Empty customization is used when there is no customization ID in VPD.
382   EXPECT_TRUE(doc->IsReady());
383 }
384 
TEST_F(ServicesCustomizationDocumentTest,DefaultApps)385 TEST_F(ServicesCustomizationDocumentTest, DefaultApps) {
386   AddCustomizationIdToVp(kDummyCustomizationID);
387   AddExpectedManifest(kDummyCustomizationID, kGoodServicesManifest);
388 
389   ServicesCustomizationDocument* doc =
390       ServicesCustomizationDocument::GetInstance();
391   EXPECT_FALSE(doc->IsReady());
392 
393   scoped_ptr<TestingProfile> profile = CreateProfile();
394   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
395   EXPECT_TRUE(loader);
396 
397   app_list::AppListSyncableServiceFactory::GetInstance()->
398       SetTestingFactoryAndUse(
399           profile.get(),
400           &app_list::AppListSyncableServiceFactory::BuildInstanceFor);
401 
402   MockExternalProviderVisitor visitor;
403   scoped_ptr<extensions::ExternalProviderImpl> provider(
404       new extensions::ExternalProviderImpl(
405           &visitor,
406           loader,
407           profile.get(),
408           extensions::Manifest::EXTERNAL_PREF,
409           extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
410           extensions::Extension::FROM_WEBSTORE |
411               extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
412 
413   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
414       .Times(0);
415   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
416       .Times(0);
417   EXPECT_CALL(visitor, OnExternalProviderReady(_))
418       .Times(1);
419 
420   // Manually request a load.
421   loader->StartLoading();
422   Mock::VerifyAndClearExpectations(&visitor);
423 
424   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
425       .Times(0);
426   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
427       .Times(2);
428   EXPECT_CALL(visitor, OnExternalProviderReady(_))
429       .Times(1);
430 
431   RunUntilIdle();
432   EXPECT_TRUE(doc->IsReady());
433 
434   app_list::AppListSyncableService* service =
435       app_list::AppListSyncableServiceFactory::GetForProfile(profile.get());
436   ASSERT_TRUE(service);
437   EXPECT_EQ("EN OEM Name", service->GetOemFolderNameForTest());
438 }
439 
TEST_F(ServicesCustomizationDocumentTest,CustomizationManifestNotFound)440 TEST_F(ServicesCustomizationDocumentTest, CustomizationManifestNotFound) {
441   AddCustomizationIdToVp(kDummyCustomizationID);
442   AddManifestNotFound(kDummyCustomizationID);
443 
444   ServicesCustomizationDocument* doc =
445       ServicesCustomizationDocument::GetInstance();
446   EXPECT_FALSE(doc->IsReady());
447 
448   scoped_ptr<TestingProfile> profile = CreateProfile();
449   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
450   EXPECT_TRUE(loader);
451 
452   MockExternalProviderVisitor visitor;
453   scoped_ptr<extensions::ExternalProviderImpl> provider(
454       new extensions::ExternalProviderImpl(
455           &visitor,
456           loader,
457           profile.get(),
458           extensions::Manifest::EXTERNAL_PREF,
459           extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
460           extensions::Extension::FROM_WEBSTORE |
461               extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
462 
463   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
464       .Times(0);
465   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
466       .Times(0);
467   EXPECT_CALL(visitor, OnExternalProviderReady(_))
468       .Times(1);
469 
470   // Manually request a load.
471   loader->StartLoading();
472   Mock::VerifyAndClearExpectations(&visitor);
473 
474   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
475       .Times(0);
476   EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
477       .Times(0);
478   EXPECT_CALL(visitor, OnExternalProviderReady(_))
479       .Times(1);
480 
481   RunUntilIdle();
482   EXPECT_TRUE(doc->IsReady());
483 }
484 
485 }  // namespace chromeos
486