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/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/ui/app_list/app_list_syncable_service.h"
15 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
16 #include "chrome/test/base/testing_browser_process.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "chromeos/network/network_handler.h"
20 #include "chromeos/network/network_state.h"
21 #include "chromeos/network/network_state_handler.h"
22 #include "chromeos/system/fake_statistics_provider.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "components/syncable_prefs/pref_service_mock_factory.h"
25 #include "components/syncable_prefs/pref_service_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"
36 using ::testing::Exactly
;
37 using ::testing::Invoke
;
38 using ::testing::Mock
;
43 const char kGoodStartupManifest
[] =
45 " \"version\": \"1.0\","
46 " \"initial_locale\" : \"en-US\","
47 " \"initial_timezone\" : \"US/Pacific\","
48 " \"keyboard_layout\" : \"xkb:us::eng\","
49 " \"setup_content\" : {"
51 " \"eula_page\" : \"file:///opt/oem/eula/en-US/eula.html\","
54 " \"eula_page\" : \"file:///opt/oem/eula/ru-RU/eula.html\","
57 " \"eula_page\" : \"file:///opt/oem/eula/en/eula.html\","
62 " \"hwid_mask\": \"ZGA*34\","
63 " \"initial_locale\" : \"ja\","
64 " \"initial_timezone\" : \"Asia/Tokyo\","
65 " \"keyboard_layout\" : \"mozc-jp\","
68 " \"hwid_mask\": \"Mario 1?3*\","
69 " \"initial_locale\" : \"ru-RU\","
70 " \"initial_timezone\" : \"Europe/Moscow\","
71 " \"keyboard_layout\" : \"xkb:ru::rus\","
76 const char kBadManifest
[] = "{\"version\": \"1\"}";
78 const char kGoodServicesManifest
[] =
80 " \"version\": \"1.0\","
81 " \"default_apps\": [\n"
82 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n"
84 " \"id\": \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\n"
85 " \"do_not_install_for_enterprise\": true\n"
88 " \"localized_content\": {\n"
90 " \"default_apps_folder_name\": \"EN-US OEM Name\"\n"
93 " \"default_apps_folder_name\": \"EN OEM Name\"\n"
96 " \"default_apps_folder_name\": \"Default OEM Name\"\n"
101 const char kDummyCustomizationID
[] = "test-dummy";
103 } // anonymous namespace
107 using ::testing::DoAll
;
108 using ::testing::NotNull
;
109 using ::testing::Return
;
110 using ::testing::SetArgumentPointee
;
113 TEST(StartupCustomizationDocumentTest
, Basic
) {
114 system::ScopedFakeStatisticsProvider fake_statistics_provider
;
116 // hardware_class selects the appropriate entry in hwid_map in the manifest.
117 fake_statistics_provider
.SetMachineStatistic("hardware_class", "Mario 12345");
118 StartupCustomizationDocument
customization(&fake_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());
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"));
132 TEST(StartupCustomizationDocumentTest
, VPD
) {
133 system::ScopedFakeStatisticsProvider fake_statistics_provider
;
135 // hardware_class selects the appropriate entry in hwid_map in the manifest.
136 fake_statistics_provider
.SetMachineStatistic("hardware_class", "Mario 12345");
137 fake_statistics_provider
.SetMachineStatistic("initial_locale", "ja");
138 fake_statistics_provider
.SetMachineStatistic("initial_timezone",
140 fake_statistics_provider
.SetMachineStatistic("keyboard_layout", "mozc-jp");
141 StartupCustomizationDocument
customization(&fake_statistics_provider
,
142 kGoodStartupManifest
);
143 EXPECT_TRUE(customization
.IsReady());
144 EXPECT_EQ("ja", customization
.initial_locale());
145 EXPECT_EQ("Asia/Tokyo", customization
.initial_timezone());
146 EXPECT_EQ("mozc-jp", customization
.keyboard_layout());
149 TEST(StartupCustomizationDocumentTest
, BadManifest
) {
150 system::ScopedFakeStatisticsProvider fake_statistics_provider
;
151 StartupCustomizationDocument
customization(&fake_statistics_provider
,
153 EXPECT_FALSE(customization
.IsReady());
156 class TestURLFetcherCallback
{
158 scoped_ptr
<net::FakeURLFetcher
> CreateURLFetcher(
160 net::URLFetcherDelegate
* d
,
161 const std::string
& response_data
,
162 net::HttpStatusCode response_code
,
163 net::URLRequestStatus::Status status
) {
164 scoped_ptr
<net::FakeURLFetcher
> fetcher(
165 new net::FakeURLFetcher(url
, d
, response_data
, response_code
, status
));
166 OnRequestCreate(url
, fetcher
.get());
167 return fetcher
.Pass();
169 MOCK_METHOD2(OnRequestCreate
,
170 void(const GURL
&, net::FakeURLFetcher
*));
173 void AddMimeHeader(const GURL
& url
, net::FakeURLFetcher
* fetcher
) {
174 scoped_refptr
<net::HttpResponseHeaders
> download_headers
=
175 new net::HttpResponseHeaders("");
176 download_headers
->AddHeader("Content-Type: application/json");
177 fetcher
->set_response_headers(download_headers
);
180 class MockExternalProviderVisitor
181 : public extensions::ExternalProviderInterface::VisitorInterface
{
183 MockExternalProviderVisitor() {}
185 MOCK_METHOD7(OnExternalExtensionFileFound
,
186 bool(const std::string
&,
187 const base::Version
*,
188 const base::FilePath
&,
189 extensions::Manifest::Location
,
193 MOCK_METHOD6(OnExternalExtensionUpdateUrlFound
,
194 bool(const std::string
&,
197 extensions::Manifest::Location
,
200 MOCK_METHOD1(OnExternalProviderReady
,
201 void(const extensions::ExternalProviderInterface
* provider
));
204 class ServicesCustomizationDocumentTest
: public testing::Test
{
206 ServicesCustomizationDocumentTest()
208 base::Bind(&TestURLFetcherCallback::CreateURLFetcher
,
209 base::Unretained(&url_callback_
))) {
213 void SetUp() override
{
214 ServicesCustomizationDocument::InitializeForTesting();
216 DBusThreadManager::Initialize();
217 NetworkHandler::Initialize();
219 const NetworkState
* default_network
=
220 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
221 std::string default_network_path
=
222 default_network
? default_network
->path() : "";
224 NetworkPortalDetector::InitializeForTesting(&network_portal_detector_
);
225 NetworkPortalDetector::CaptivePortalState online_state
;
226 online_state
.status
= NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE
;
227 online_state
.response_code
= 204;
229 default_network
? default_network
->guid() : std::string();
230 network_portal_detector_
.SetDefaultNetworkForTesting(guid
);
232 network_portal_detector_
.SetDetectionResultsForTesting(
236 TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_
);
237 ServicesCustomizationDocument::RegisterPrefs(local_state_
.registry());
240 void TearDown() override
{
241 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL
);
242 NetworkHandler::Shutdown();
243 DBusThreadManager::Shutdown();
244 NetworkPortalDetector::InitializeForTesting(NULL
);
246 ServicesCustomizationDocument::ShutdownForTesting();
249 void RunUntilIdle() {
250 base::RunLoop().RunUntilIdle();
253 void AddCustomizationIdToVp(const std::string
& id
) {
254 fake_statistics_provider_
.SetMachineStatistic(system::kCustomizationIdKey
,
258 void AddExpectedManifest(const std::string
& id
,
259 const std::string
& manifest
) {
260 GURL
url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl
,
262 factory_
.SetFakeResponse(url
,
265 net::URLRequestStatus::SUCCESS
);
266 EXPECT_CALL(url_callback_
, OnRequestCreate(url
, _
))
268 .WillRepeatedly(Invoke(AddMimeHeader
));
271 void AddManifestNotFound(const std::string
& id
) {
272 GURL
url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl
,
274 factory_
.SetFakeResponse(url
,
277 net::URLRequestStatus::SUCCESS
);
278 EXPECT_CALL(url_callback_
, OnRequestCreate(url
, _
))
280 .WillRepeatedly(Invoke(AddMimeHeader
));
283 scoped_ptr
<TestingProfile
> CreateProfile() {
284 TestingProfile::Builder profile_builder
;
285 syncable_prefs::PrefServiceMockFactory factory
;
286 scoped_refptr
<user_prefs::PrefRegistrySyncable
> registry(
287 new user_prefs::PrefRegistrySyncable
);
288 scoped_ptr
<syncable_prefs::PrefServiceSyncable
> prefs(
289 factory
.CreateSyncable(registry
.get()));
290 chrome::RegisterUserProfilePrefs(registry
.get());
291 profile_builder
.SetPrefService(prefs
.Pass());
292 return profile_builder
.Build();
296 system::ScopedFakeStatisticsProvider fake_statistics_provider_
;
297 content::TestBrowserThreadBundle thread_bundle_
;
298 TestingPrefServiceSimple local_state_
;
299 TestURLFetcherCallback url_callback_
;
300 net::FakeURLFetcherFactory factory_
;
301 NetworkPortalDetectorTestImpl network_portal_detector_
;
304 TEST_F(ServicesCustomizationDocumentTest
, Basic
) {
305 AddCustomizationIdToVp(kDummyCustomizationID
);
306 AddExpectedManifest(kDummyCustomizationID
, kGoodServicesManifest
);
308 ServicesCustomizationDocument
* doc
=
309 ServicesCustomizationDocument::GetInstance();
310 EXPECT_FALSE(doc
->IsReady());
312 doc
->StartFetching();
314 EXPECT_TRUE(doc
->IsReady());
317 EXPECT_FALSE(doc
->GetDefaultWallpaperUrl(&wallpaper_url
));
318 EXPECT_EQ("", wallpaper_url
.spec());
320 scoped_ptr
<base::DictionaryValue
> default_apps(doc
->GetDefaultApps());
321 ASSERT_TRUE(default_apps
);
322 EXPECT_EQ(default_apps
->size(), 2u);
324 const base::DictionaryValue
* app_entry
= nullptr;
325 ASSERT_TRUE(default_apps
->GetDictionary("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
327 EXPECT_EQ(app_entry
->size(), 1u);
329 app_entry
->HasKey(extensions::ExternalProviderImpl::kExternalUpdateUrl
));
331 ASSERT_TRUE(default_apps
->GetDictionary("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
333 EXPECT_EQ(app_entry
->size(), 2u);
335 app_entry
->HasKey(extensions::ExternalProviderImpl::kExternalUpdateUrl
));
336 EXPECT_TRUE(app_entry
->HasKey(
337 extensions::ExternalProviderImpl::kDoNotInstallForEnterprise
));
339 EXPECT_EQ("EN-US OEM Name", doc
->GetOemAppsFolderName("en-US"));
340 EXPECT_EQ("EN OEM Name", doc
->GetOemAppsFolderName("en"));
341 EXPECT_EQ("Default OEM Name", doc
->GetOemAppsFolderName("ru"));
344 TEST_F(ServicesCustomizationDocumentTest
, NoCustomizationIdInVpd
) {
345 ServicesCustomizationDocument
* doc
=
346 ServicesCustomizationDocument::GetInstance();
347 EXPECT_FALSE(doc
->IsReady());
349 scoped_ptr
<TestingProfile
> profile
= CreateProfile();
350 extensions::ExternalLoader
* loader
= doc
->CreateExternalLoader(profile
.get());
353 MockExternalProviderVisitor visitor
;
354 scoped_ptr
<extensions::ExternalProviderImpl
> provider(
355 new extensions::ExternalProviderImpl(
359 extensions::Manifest::EXTERNAL_PREF
,
360 extensions::Manifest::EXTERNAL_PREF_DOWNLOAD
,
361 extensions::Extension::FROM_WEBSTORE
|
362 extensions::Extension::WAS_INSTALLED_BY_DEFAULT
));
364 EXPECT_CALL(visitor
, OnExternalExtensionFileFound(_
, _
, _
, _
, _
, _
, _
))
366 EXPECT_CALL(visitor
, OnExternalExtensionUpdateUrlFound(_
, _
, _
, _
, _
, _
))
368 EXPECT_CALL(visitor
, OnExternalProviderReady(_
))
371 // Manually request a load.
373 loader
->StartLoading();
374 Mock::VerifyAndClearExpectations(&visitor
);
377 // Empty customization is used when there is no customization ID in VPD.
378 EXPECT_TRUE(doc
->IsReady());
381 TEST_F(ServicesCustomizationDocumentTest
, DefaultApps
) {
382 AddCustomizationIdToVp(kDummyCustomizationID
);
383 AddExpectedManifest(kDummyCustomizationID
, kGoodServicesManifest
);
385 ServicesCustomizationDocument
* doc
=
386 ServicesCustomizationDocument::GetInstance();
387 EXPECT_FALSE(doc
->IsReady());
389 scoped_ptr
<TestingProfile
> profile
= CreateProfile();
390 extensions::ExternalLoader
* loader
= doc
->CreateExternalLoader(profile
.get());
393 app_list::AppListSyncableServiceFactory::GetInstance()->
394 SetTestingFactoryAndUse(
396 &app_list::AppListSyncableServiceFactory::BuildInstanceFor
);
398 MockExternalProviderVisitor visitor
;
399 scoped_ptr
<extensions::ExternalProviderImpl
> provider(
400 new extensions::ExternalProviderImpl(
404 extensions::Manifest::EXTERNAL_PREF
,
405 extensions::Manifest::EXTERNAL_PREF_DOWNLOAD
,
406 extensions::Extension::FROM_WEBSTORE
|
407 extensions::Extension::WAS_INSTALLED_BY_DEFAULT
));
409 EXPECT_CALL(visitor
, OnExternalExtensionFileFound(_
, _
, _
, _
, _
, _
, _
))
411 EXPECT_CALL(visitor
, OnExternalExtensionUpdateUrlFound(_
, _
, _
, _
, _
, _
))
413 EXPECT_CALL(visitor
, OnExternalProviderReady(_
))
416 // Manually request a load.
417 loader
->StartLoading();
418 Mock::VerifyAndClearExpectations(&visitor
);
420 EXPECT_CALL(visitor
, OnExternalExtensionFileFound(_
, _
, _
, _
, _
, _
, _
))
422 EXPECT_CALL(visitor
, OnExternalExtensionUpdateUrlFound(_
, _
, _
, _
, _
, _
))
424 EXPECT_CALL(visitor
, OnExternalProviderReady(_
))
428 EXPECT_TRUE(doc
->IsReady());
430 app_list::AppListSyncableService
* service
=
431 app_list::AppListSyncableServiceFactory::GetForProfile(profile
.get());
432 ASSERT_TRUE(service
);
433 EXPECT_EQ("EN OEM Name", service
->GetOemFolderNameForTest());
436 TEST_F(ServicesCustomizationDocumentTest
, CustomizationManifestNotFound
) {
437 AddCustomizationIdToVp(kDummyCustomizationID
);
438 AddManifestNotFound(kDummyCustomizationID
);
440 ServicesCustomizationDocument
* doc
=
441 ServicesCustomizationDocument::GetInstance();
442 EXPECT_FALSE(doc
->IsReady());
444 scoped_ptr
<TestingProfile
> profile
= CreateProfile();
445 extensions::ExternalLoader
* loader
= doc
->CreateExternalLoader(profile
.get());
448 MockExternalProviderVisitor visitor
;
449 scoped_ptr
<extensions::ExternalProviderImpl
> provider(
450 new extensions::ExternalProviderImpl(
454 extensions::Manifest::EXTERNAL_PREF
,
455 extensions::Manifest::EXTERNAL_PREF_DOWNLOAD
,
456 extensions::Extension::FROM_WEBSTORE
|
457 extensions::Extension::WAS_INSTALLED_BY_DEFAULT
));
459 EXPECT_CALL(visitor
, OnExternalExtensionFileFound(_
, _
, _
, _
, _
, _
, _
))
461 EXPECT_CALL(visitor
, OnExternalExtensionUpdateUrlFound(_
, _
, _
, _
, _
, _
))
463 EXPECT_CALL(visitor
, OnExternalProviderReady(_
))
466 // Manually request a load.
467 loader
->StartLoading();
468 Mock::VerifyAndClearExpectations(&visitor
);
470 EXPECT_CALL(visitor
, OnExternalExtensionFileFound(_
, _
, _
, _
, _
, _
, _
))
472 EXPECT_CALL(visitor
, OnExternalExtensionUpdateUrlFound(_
, _
, _
, _
, _
, _
))
474 EXPECT_CALL(visitor
, OnExternalProviderReady(_
))
478 EXPECT_TRUE(doc
->IsReady());
481 } // namespace chromeos