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.
5 #include "chrome/browser/chromeos/customization_document.h"
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/system/mock_statistics_provider.h"
23 #include "components/user_prefs/pref_registry_syncable.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "extensions/common/extension.h"
26 #include "extensions/common/manifest.h"
27 #include "net/http/http_response_headers.h"
28 #include "net/http/http_status_code.h"
29 #include "net/url_request/test_url_fetcher_factory.h"
30 #include "net/url_request/url_request_status.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
34 using ::testing::Exactly;
35 using ::testing::Invoke;
36 using ::testing::Mock;
41 const char kGoodStartupManifest[] =
43 " \"version\": \"1.0\","
44 " \"initial_locale\" : \"en-US\","
45 " \"initial_timezone\" : \"US/Pacific\","
46 " \"keyboard_layout\" : \"xkb:us::eng\","
47 " \"setup_content\" : {"
49 " \"eula_page\" : \"file:///opt/oem/eula/en-US/eula.html\","
52 " \"eula_page\" : \"file:///opt/oem/eula/ru-RU/eula.html\","
55 " \"eula_page\" : \"file:///opt/oem/eula/en/eula.html\","
60 " \"hwid_mask\": \"ZGA*34\","
61 " \"initial_locale\" : \"ja\","
62 " \"initial_timezone\" : \"Asia/Tokyo\","
63 " \"keyboard_layout\" : \"mozc-jp\","
66 " \"hwid_mask\": \"Mario 1?3*\","
67 " \"initial_locale\" : \"ru-RU\","
68 " \"initial_timezone\" : \"Europe/Moscow\","
69 " \"keyboard_layout\" : \"xkb:ru::rus\","
74 const char kBadManifest[] = "{\"version\": \"1\"}";
76 const char kGoodServicesManifest[] =
78 " \"version\": \"1.0\","
79 " \"default_wallpaper\": \"http://somedomain.com/image.png\",\n"
80 " \"default_apps\": [\n"
81 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n"
82 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n"
84 " \"localized_content\": {\n"
86 " \"default_apps_folder_name\": \"EN-US OEM Name\"\n"
89 " \"default_apps_folder_name\": \"EN OEM Name\"\n"
92 " \"default_apps_folder_name\": \"Default OEM Name\"\n"
97 const char kDummyCustomizationID[] = "test-dummy";
99 // Note the path name must be the same as in shill stub.
100 const char kStubEthernetServicePath[] = "eth1";
102 } // anonymous namespace
107 using ::testing::DoAll;
108 using ::testing::NotNull;
109 using ::testing::Return;
110 using ::testing::SetArgumentPointee;
112 TEST(StartupCustomizationDocumentTest, Basic) {
113 system::MockStatisticsProvider mock_statistics_provider;
114 EXPECT_CALL(mock_statistics_provider, GetMachineStatistic(_, NotNull()))
115 .WillRepeatedly(Return(false));
116 EXPECT_CALL(mock_statistics_provider,
117 GetMachineStatistic(std::string("hardware_class"), NotNull()))
118 .WillOnce(DoAll(SetArgumentPointee<1>(std::string("Mario 12345")),
120 StartupCustomizationDocument customization(&mock_statistics_provider,
121 kGoodStartupManifest);
122 EXPECT_EQ("ru-RU", customization.initial_locale());
123 EXPECT_EQ("Europe/Moscow", customization.initial_timezone());
124 EXPECT_EQ("xkb:ru::rus", customization.keyboard_layout());
126 EXPECT_EQ("file:///opt/oem/eula/en-US/eula.html",
127 customization.GetEULAPage("en-US"));
128 EXPECT_EQ("file:///opt/oem/eula/ru-RU/eula.html",
129 customization.GetEULAPage("ru-RU"));
130 EXPECT_EQ("file:///opt/oem/eula/en/eula.html",
131 customization.GetEULAPage("ja"));
134 TEST(StartupCustomizationDocumentTest, VPD) {
135 system::MockStatisticsProvider mock_statistics_provider;
136 EXPECT_CALL(mock_statistics_provider,
137 GetMachineStatistic(std::string("hardware_class"), NotNull()))
138 .WillOnce(DoAll(SetArgumentPointee<1>(std::string("Mario 12345")),
140 EXPECT_CALL(mock_statistics_provider,
141 GetMachineStatistic(std::string("initial_locale"), NotNull()))
142 .WillOnce(DoAll(SetArgumentPointee<1>(std::string("ja")),
144 EXPECT_CALL(mock_statistics_provider,
145 GetMachineStatistic(std::string("initial_timezone"), NotNull()))
146 .WillOnce(DoAll(SetArgumentPointee<1>(std::string("Asia/Tokyo")),
148 EXPECT_CALL(mock_statistics_provider,
149 GetMachineStatistic(std::string("keyboard_layout"), NotNull()))
150 .WillOnce(DoAll(SetArgumentPointee<1>(std::string("mozc-jp")),
152 StartupCustomizationDocument customization(&mock_statistics_provider,
153 kGoodStartupManifest);
154 EXPECT_TRUE(customization.IsReady());
155 EXPECT_EQ("ja", customization.initial_locale());
156 EXPECT_EQ("Asia/Tokyo", customization.initial_timezone());
157 EXPECT_EQ("mozc-jp", customization.keyboard_layout());
160 TEST(StartupCustomizationDocumentTest, BadManifest) {
161 system::MockStatisticsProvider mock_statistics_provider;
162 StartupCustomizationDocument customization(&mock_statistics_provider,
164 EXPECT_FALSE(customization.IsReady());
167 class TestURLFetcherCallback {
169 scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
171 net::URLFetcherDelegate* d,
172 const std::string& response_data,
173 net::HttpStatusCode response_code,
174 net::URLRequestStatus::Status status) {
175 scoped_ptr<net::FakeURLFetcher> fetcher(
176 new net::FakeURLFetcher(url, d, response_data, response_code, status));
177 OnRequestCreate(url, fetcher.get());
178 return fetcher.Pass();
180 MOCK_METHOD2(OnRequestCreate,
181 void(const GURL&, net::FakeURLFetcher*));
184 void AddMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher) {
185 scoped_refptr<net::HttpResponseHeaders> download_headers =
186 new net::HttpResponseHeaders("");
187 download_headers->AddHeader("Content-Type: application/json");
188 fetcher->set_response_headers(download_headers);
191 class MockExternalProviderVisitor
192 : public extensions::ExternalProviderInterface::VisitorInterface {
194 MockExternalProviderVisitor() {}
196 MOCK_METHOD6(OnExternalExtensionFileFound,
197 bool(const std::string&,
198 const base::Version*,
199 const base::FilePath&,
200 extensions::Manifest::Location,
203 MOCK_METHOD6(OnExternalExtensionUpdateUrlFound,
204 bool(const std::string&,
207 extensions::Manifest::Location,
210 MOCK_METHOD1(OnExternalProviderReady,
211 void(const extensions::ExternalProviderInterface* provider));
214 class ServicesCustomizationDocumentTest : public testing::Test {
216 ServicesCustomizationDocumentTest()
218 base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
219 base::Unretained(&url_callback_))) {
223 virtual void SetUp() OVERRIDE {
224 ServicesCustomizationDocument::InitializeForTesting();
226 EXPECT_CALL(mock_statistics_provider_, GetMachineStatistic(_, NotNull()))
227 .WillRepeatedly(Return(false));
228 chromeos::system::StatisticsProvider::SetTestProvider(
229 &mock_statistics_provider_);
231 DBusThreadManager::InitializeWithStub();
232 NetworkHandler::Initialize();
234 NetworkPortalDetector::InitializeForTesting(&network_portal_detector_);
235 NetworkPortalDetector::CaptivePortalState online_state;
236 online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
237 online_state.response_code = 204;
238 network_portal_detector_.SetDefaultNetworkPathForTesting(
239 kStubEthernetServicePath);
240 network_portal_detector_.SetDetectionResultsForTesting(
241 kStubEthernetServicePath, online_state);
243 TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
244 ServicesCustomizationDocument::RegisterPrefs(local_state_.registry());
247 virtual void TearDown() OVERRIDE {
248 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
249 NetworkHandler::Shutdown();
250 DBusThreadManager::Shutdown();
251 NetworkPortalDetector::InitializeForTesting(NULL);
252 chromeos::system::StatisticsProvider::SetTestProvider(NULL);
254 ServicesCustomizationDocument::ShutdownForTesting();
257 void RunUntilIdle() {
258 base::RunLoop().RunUntilIdle();
261 void AddCustomizationIdToVp(const std::string& id) {
262 EXPECT_CALL(mock_statistics_provider_,
263 GetMachineStatistic(system::kCustomizationIdKey, NotNull()))
264 .WillOnce(DoAll(SetArgumentPointee<1>(id),
268 void AddExpectedManifest(const std::string& id,
269 const std::string& manifest) {
270 GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
272 factory_.SetFakeResponse(url,
275 net::URLRequestStatus::SUCCESS);
276 EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
278 .WillRepeatedly(Invoke(AddMimeHeader));
281 void AddManifestNotFound(const std::string& id) {
282 GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
284 factory_.SetFakeResponse(url,
287 net::URLRequestStatus::SUCCESS);
288 EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
290 .WillRepeatedly(Invoke(AddMimeHeader));
293 scoped_ptr<TestingProfile> CreateProfile() {
294 TestingProfile::Builder profile_builder;
295 PrefServiceMockFactory factory;
296 scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
297 new user_prefs::PrefRegistrySyncable);
298 scoped_ptr<PrefServiceSyncable> prefs(
299 factory.CreateSyncable(registry.get()));
300 chrome::RegisterUserProfilePrefs(registry.get());
301 profile_builder.SetPrefService(prefs.Pass());
302 return profile_builder.Build();
306 system::MockStatisticsProvider mock_statistics_provider_;
307 content::TestBrowserThreadBundle thread_bundle_;
308 TestingPrefServiceSimple local_state_;
309 TestURLFetcherCallback url_callback_;
310 net::FakeURLFetcherFactory factory_;
311 NetworkPortalDetectorTestImpl network_portal_detector_;
314 TEST_F(ServicesCustomizationDocumentTest, Basic) {
315 AddCustomizationIdToVp(kDummyCustomizationID);
316 AddExpectedManifest(kDummyCustomizationID, kGoodServicesManifest);
318 ServicesCustomizationDocument* doc =
319 ServicesCustomizationDocument::GetInstance();
320 EXPECT_FALSE(doc->IsReady());
322 doc->StartFetching();
324 EXPECT_TRUE(doc->IsReady());
326 EXPECT_EQ(doc->GetDefaultWallpaperUrl().spec(),
327 "http://somedomain.com/image.png");
329 std::vector<std::string> default_apps;
330 EXPECT_TRUE(doc->GetDefaultApps(&default_apps));
331 ASSERT_EQ(default_apps.size(), 2u);
333 EXPECT_EQ(default_apps[0], "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
334 EXPECT_EQ(default_apps[1], "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
336 EXPECT_EQ(doc->GetOemAppsFolderName("en-US"), "EN-US OEM Name");
337 EXPECT_EQ(doc->GetOemAppsFolderName("en"), "EN OEM Name");
338 EXPECT_EQ(doc->GetOemAppsFolderName("ru"), "Default OEM Name");
341 TEST_F(ServicesCustomizationDocumentTest, NoCustomizationIdInVpd) {
342 ServicesCustomizationDocument* doc =
343 ServicesCustomizationDocument::GetInstance();
344 EXPECT_FALSE(doc->IsReady());
346 scoped_ptr<TestingProfile> profile = CreateProfile();
347 extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
350 MockExternalProviderVisitor visitor;
351 scoped_ptr<extensions::ExternalProviderImpl> provider(
352 new extensions::ExternalProviderImpl(
356 extensions::Manifest::EXTERNAL_PREF,
357 extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
358 extensions::Extension::FROM_WEBSTORE |
359 extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
361 EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
363 EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
365 EXPECT_CALL(visitor, OnExternalProviderReady(_))
368 // Manually request a load.
370 loader->StartLoading();
371 Mock::VerifyAndClearExpectations(&visitor);
374 EXPECT_FALSE(doc->IsReady());
377 TEST_F(ServicesCustomizationDocumentTest, DefaultApps) {
378 AddCustomizationIdToVp(kDummyCustomizationID);
379 AddExpectedManifest(kDummyCustomizationID, kGoodServicesManifest);
381 ServicesCustomizationDocument* doc =
382 ServicesCustomizationDocument::GetInstance();
383 EXPECT_FALSE(doc->IsReady());
385 scoped_ptr<TestingProfile> profile = CreateProfile();
386 extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
389 app_list::AppListSyncableServiceFactory::GetInstance()->
390 SetTestingFactoryAndUse(
392 &app_list::AppListSyncableServiceFactory::BuildInstanceFor);
394 MockExternalProviderVisitor visitor;
395 scoped_ptr<extensions::ExternalProviderImpl> provider(
396 new extensions::ExternalProviderImpl(
400 extensions::Manifest::EXTERNAL_PREF,
401 extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
402 extensions::Extension::FROM_WEBSTORE |
403 extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
405 EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
407 EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
409 EXPECT_CALL(visitor, OnExternalProviderReady(_))
412 // Manually request a load.
413 loader->StartLoading();
414 Mock::VerifyAndClearExpectations(&visitor);
416 EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
418 EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
420 EXPECT_CALL(visitor, OnExternalProviderReady(_))
424 EXPECT_TRUE(doc->IsReady());
426 app_list::AppListSyncableService* service =
427 app_list::AppListSyncableServiceFactory::GetForProfile(profile.get());
428 ASSERT_TRUE(service);
429 EXPECT_EQ(service->GetOemFolderNameForTest(), "EN OEM Name");
432 TEST_F(ServicesCustomizationDocumentTest, CustomizationManifestNotFound) {
433 AddCustomizationIdToVp(kDummyCustomizationID);
434 AddManifestNotFound(kDummyCustomizationID);
436 ServicesCustomizationDocument* doc =
437 ServicesCustomizationDocument::GetInstance();
438 EXPECT_FALSE(doc->IsReady());
440 scoped_ptr<TestingProfile> profile = CreateProfile();
441 extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
444 MockExternalProviderVisitor visitor;
445 scoped_ptr<extensions::ExternalProviderImpl> provider(
446 new extensions::ExternalProviderImpl(
450 extensions::Manifest::EXTERNAL_PREF,
451 extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
452 extensions::Extension::FROM_WEBSTORE |
453 extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
455 EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
457 EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
459 EXPECT_CALL(visitor, OnExternalProviderReady(_))
462 // Manually request a load.
463 loader->StartLoading();
464 Mock::VerifyAndClearExpectations(&visitor);
466 EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
468 EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
470 EXPECT_CALL(visitor, OnExternalProviderReady(_))
474 EXPECT_TRUE(doc->IsReady());
477 } // namespace chromeos