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 "base/path_service.h"
6#include "base/prefs/pref_service.h"
7#include "base/prefs/scoped_user_pref_update.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/chrome_notification_types.h"
10#include "chrome/browser/extensions/extension_service_unittest.h"
11#include "chrome/browser/extensions/unpacked_installer.h"
12#include "chrome/browser/managed_mode/custodian_profile_downloader_service.h"
13#include "chrome/browser/managed_mode/custodian_profile_downloader_service_factory.h"
14#include "chrome/browser/managed_mode/managed_user_service.h"
15#include "chrome/browser/managed_mode/managed_user_service_factory.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
18#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
19#include "chrome/browser/ui/browser_list.h"
20#include "chrome/common/chrome_paths.h"
21#include "chrome/common/extensions/features/feature_channel.h"
22#include "chrome/common/pref_names.h"
23#include "chrome/test/base/testing_profile.h"
24#include "content/public/test/test_browser_thread_bundle.h"
25#include "content/public/test/test_utils.h"
26#include "extensions/common/extension.h"
27#include "extensions/common/extension_builder.h"
28#include "extensions/common/manifest_constants.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
31using content::MessageLoopRunner;
32
33namespace {
34
35void OnProfileDownloadedFail(const base::string16& full_name) {
36  ASSERT_TRUE(false) << "Profile download should not have succeeded.";
37}
38
39class ManagedModeURLFilterObserver : public ManagedModeURLFilter::Observer {
40 public:
41  explicit ManagedModeURLFilterObserver(ManagedModeURLFilter* url_filter)
42      : url_filter_(url_filter) {
43    Reset();
44    url_filter_->AddObserver(this);
45  }
46
47  ~ManagedModeURLFilterObserver() {
48    url_filter_->RemoveObserver(this);
49  }
50
51  void Wait() {
52    message_loop_runner_->Run();
53    Reset();
54  }
55
56  // ManagedModeURLFilter::Observer
57  virtual void OnSiteListUpdated() OVERRIDE {
58    message_loop_runner_->Quit();
59  }
60
61 private:
62  void Reset() {
63    message_loop_runner_ = new MessageLoopRunner;
64  }
65
66  ManagedModeURLFilter* url_filter_;
67  scoped_refptr<MessageLoopRunner> message_loop_runner_;
68};
69
70class ManagedUserServiceTest : public ::testing::Test {
71 public:
72  ManagedUserServiceTest() {}
73
74  virtual void SetUp() OVERRIDE {
75    TestingProfile::Builder builder;
76    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
77                              FakeProfileOAuth2TokenService::Build);
78    profile_ = builder.Build();
79    managed_user_service_ =
80        ManagedUserServiceFactory::GetForProfile(profile_.get());
81  }
82
83  virtual void TearDown() OVERRIDE {
84    profile_.reset();
85  }
86
87  virtual ~ManagedUserServiceTest() {}
88
89 protected:
90  content::TestBrowserThreadBundle thread_bundle_;
91  scoped_ptr<TestingProfile> profile_;
92  ManagedUserService* managed_user_service_;
93};
94
95}  // namespace
96
97TEST_F(ManagedUserServiceTest, GetManualExceptionsForHost) {
98  GURL kExampleFooURL("http://www.example.com/foo");
99  GURL kExampleBarURL("http://www.example.com/bar");
100  GURL kExampleFooNoWWWURL("http://example.com/foo");
101  GURL kBlurpURL("http://blurp.net/bla");
102  GURL kMooseURL("http://moose.org/baz");
103  {
104    DictionaryPrefUpdate update(profile_->GetPrefs(),
105                                prefs::kManagedModeManualURLs);
106    base::DictionaryValue* dict = update.Get();
107    dict->SetBooleanWithoutPathExpansion(kExampleFooURL.spec(), true);
108    dict->SetBooleanWithoutPathExpansion(kExampleBarURL.spec(), false);
109    dict->SetBooleanWithoutPathExpansion(kExampleFooNoWWWURL.spec(), true);
110    dict->SetBooleanWithoutPathExpansion(kBlurpURL.spec(), true);
111  }
112
113  EXPECT_EQ(ManagedUserService::MANUAL_ALLOW,
114            managed_user_service_->GetManualBehaviorForURL(kExampleFooURL));
115  EXPECT_EQ(ManagedUserService::MANUAL_BLOCK,
116            managed_user_service_->GetManualBehaviorForURL(kExampleBarURL));
117  EXPECT_EQ(ManagedUserService::MANUAL_ALLOW,
118            managed_user_service_->GetManualBehaviorForURL(
119                kExampleFooNoWWWURL));
120  EXPECT_EQ(ManagedUserService::MANUAL_ALLOW,
121            managed_user_service_->GetManualBehaviorForURL(kBlurpURL));
122  EXPECT_EQ(ManagedUserService::MANUAL_NONE,
123            managed_user_service_->GetManualBehaviorForURL(kMooseURL));
124  std::vector<GURL> exceptions;
125  managed_user_service_->GetManualExceptionsForHost("www.example.com",
126                                                    &exceptions);
127  ASSERT_EQ(2u, exceptions.size());
128  EXPECT_EQ(kExampleBarURL, exceptions[0]);
129  EXPECT_EQ(kExampleFooURL, exceptions[1]);
130
131  {
132    DictionaryPrefUpdate update(profile_->GetPrefs(),
133                                prefs::kManagedModeManualURLs);
134    base::DictionaryValue* dict = update.Get();
135    for (std::vector<GURL>::iterator it = exceptions.begin();
136         it != exceptions.end(); ++it) {
137      dict->RemoveWithoutPathExpansion(it->spec(), NULL);
138    }
139  }
140
141  EXPECT_EQ(ManagedUserService::MANUAL_NONE,
142            managed_user_service_->GetManualBehaviorForURL(kExampleFooURL));
143  EXPECT_EQ(ManagedUserService::MANUAL_NONE,
144            managed_user_service_->GetManualBehaviorForURL(kExampleBarURL));
145  EXPECT_EQ(ManagedUserService::MANUAL_ALLOW,
146            managed_user_service_->GetManualBehaviorForURL(
147                kExampleFooNoWWWURL));
148  EXPECT_EQ(ManagedUserService::MANUAL_ALLOW,
149            managed_user_service_->GetManualBehaviorForURL(kBlurpURL));
150  EXPECT_EQ(ManagedUserService::MANUAL_NONE,
151            managed_user_service_->GetManualBehaviorForURL(kMooseURL));
152}
153
154// Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
155// DCHECK is hit when the service is destroyed, this test passed.
156TEST_F(ManagedUserServiceTest, ShutDownCustodianProfileDownloader) {
157  CustodianProfileDownloaderService* downloader_service =
158      CustodianProfileDownloaderServiceFactory::GetForProfile(profile_.get());
159
160  // Emulate being logged in, then start to download a profile so a
161  // ProfileDownloader gets created.
162  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "Logged In");
163  downloader_service->DownloadProfile(base::Bind(&OnProfileDownloadedFail));
164}
165
166#if !defined(OS_ANDROID)
167class ManagedUserServiceExtensionTestBase : public ExtensionServiceTestBase {
168 public:
169  explicit ManagedUserServiceExtensionTestBase(bool is_managed)
170      : is_managed_(is_managed),
171        channel_(chrome::VersionInfo::CHANNEL_DEV) {}
172  virtual ~ManagedUserServiceExtensionTestBase() {}
173
174  virtual void SetUp() OVERRIDE {
175    ExtensionServiceTestBase::SetUp();
176    ExtensionServiceTestBase::ExtensionServiceInitParams params =
177        CreateDefaultInitParams();
178    params.profile_is_managed = is_managed_;
179    InitializeExtensionService(params);
180    ManagedUserServiceFactory::GetForProfile(profile_.get())->Init();
181  }
182
183 protected:
184  ScopedVector<ManagedModeSiteList> GetActiveSiteLists(
185      ManagedUserService* managed_user_service) {
186    return managed_user_service->GetActiveSiteLists();
187  }
188
189  scoped_refptr<extensions::Extension> MakeThemeExtension() {
190    scoped_ptr<DictionaryValue> source(new DictionaryValue());
191    source->SetString(extensions::manifest_keys::kName, "Theme");
192    source->Set(extensions::manifest_keys::kTheme, new DictionaryValue());
193    source->SetString(extensions::manifest_keys::kVersion, "1.0");
194    extensions::ExtensionBuilder builder;
195    scoped_refptr<extensions::Extension> extension =
196        builder.SetManifest(source.Pass()).Build();
197    return extension;
198  }
199
200  scoped_refptr<extensions::Extension> MakeExtension() {
201    scoped_ptr<DictionaryValue> manifest = extensions::DictionaryBuilder()
202      .Set(extensions::manifest_keys::kName, "Extension")
203      .Set(extensions::manifest_keys::kVersion, "1.0")
204      .Build();
205    extensions::ExtensionBuilder builder;
206    scoped_refptr<extensions::Extension> extension =
207        builder.SetManifest(manifest.Pass()).Build();
208    return extension;
209  }
210
211  bool is_managed_;
212  extensions::ScopedCurrentChannel channel_;
213};
214
215class ManagedUserServiceExtensionTestUnmanaged
216    : public ManagedUserServiceExtensionTestBase {
217 public:
218  ManagedUserServiceExtensionTestUnmanaged()
219      : ManagedUserServiceExtensionTestBase(false) {}
220};
221
222class ManagedUserServiceExtensionTest
223    : public ManagedUserServiceExtensionTestBase {
224 public:
225  ManagedUserServiceExtensionTest()
226      : ManagedUserServiceExtensionTestBase(true) {}
227};
228
229TEST_F(ManagedUserServiceExtensionTestUnmanaged,
230       ExtensionManagementPolicyProvider) {
231  ManagedUserService* managed_user_service =
232      ManagedUserServiceFactory::GetForProfile(profile_.get());
233  EXPECT_FALSE(profile_->IsManaged());
234
235  scoped_refptr<extensions::Extension> extension = MakeExtension();
236  base::string16 error_1;
237  EXPECT_TRUE(managed_user_service->UserMayLoad(extension.get(), &error_1));
238  EXPECT_EQ(base::string16(), error_1);
239
240  base::string16 error_2;
241  EXPECT_TRUE(
242      managed_user_service->UserMayModifySettings(extension.get(), &error_2));
243  EXPECT_EQ(base::string16(), error_2);
244}
245
246TEST_F(ManagedUserServiceExtensionTest, ExtensionManagementPolicyProvider) {
247  ManagedUserService* managed_user_service =
248      ManagedUserServiceFactory::GetForProfile(profile_.get());
249  ManagedModeURLFilterObserver observer(
250      managed_user_service->GetURLFilterForUIThread());
251  ASSERT_TRUE(profile_->IsManaged());
252  // Wait for the initial update to finish (otherwise we'll get leaks).
253  observer.Wait();
254
255  // Check that a supervised user can install a theme.
256  scoped_refptr<extensions::Extension> theme = MakeThemeExtension();
257  base::string16 error_1;
258  EXPECT_TRUE(managed_user_service->UserMayLoad(theme.get(), &error_1));
259  EXPECT_TRUE(error_1.empty());
260  EXPECT_TRUE(
261      managed_user_service->UserMayModifySettings(theme.get(), &error_1));
262  EXPECT_TRUE(error_1.empty());
263
264  // Now check a different kind of extension.
265  scoped_refptr<extensions::Extension> extension = MakeExtension();
266  EXPECT_FALSE(managed_user_service->UserMayLoad(extension.get(), &error_1));
267  EXPECT_FALSE(error_1.empty());
268
269  base::string16 error_2;
270  EXPECT_FALSE(
271      managed_user_service->UserMayModifySettings(extension.get(), &error_2));
272  EXPECT_FALSE(error_2.empty());
273
274#ifndef NDEBUG
275  EXPECT_FALSE(managed_user_service->GetDebugPolicyProviderName().empty());
276#endif
277}
278
279TEST_F(ManagedUserServiceExtensionTest, NoContentPacks) {
280  ManagedUserService* managed_user_service =
281      ManagedUserServiceFactory::GetForProfile(profile_.get());
282  ManagedModeURLFilter* url_filter =
283      managed_user_service->GetURLFilterForUIThread();
284
285  GURL url("http://youtube.com");
286  ScopedVector<ManagedModeSiteList> site_lists =
287      GetActiveSiteLists(managed_user_service);
288  ASSERT_EQ(0u, site_lists.size());
289  EXPECT_EQ(ManagedModeURLFilter::ALLOW,
290            url_filter->GetFilteringBehaviorForURL(url));
291}
292
293TEST_F(ManagedUserServiceExtensionTest, InstallContentPacks) {
294  ManagedUserService* managed_user_service =
295      ManagedUserServiceFactory::GetForProfile(profile_.get());
296  ManagedModeURLFilter* url_filter =
297      managed_user_service->GetURLFilterForUIThread();
298  ManagedModeURLFilterObserver observer(url_filter);
299  observer.Wait();
300
301  GURL example_url("http://example.com");
302  GURL moose_url("http://moose.org");
303  EXPECT_EQ(ManagedModeURLFilter::ALLOW,
304            url_filter->GetFilteringBehaviorForURL(example_url));
305
306  profile_->GetPrefs()->SetInteger(prefs::kDefaultManagedModeFilteringBehavior,
307                                   ManagedModeURLFilter::BLOCK);
308  EXPECT_EQ(ManagedModeURLFilter::BLOCK,
309            url_filter->GetFilteringBehaviorForURL(example_url));
310
311  profile_->GetPrefs()->SetInteger(prefs::kDefaultManagedModeFilteringBehavior,
312                                   ManagedModeURLFilter::WARN);
313  EXPECT_EQ(ManagedModeURLFilter::WARN,
314            url_filter->GetFilteringBehaviorForURL(example_url));
315
316  managed_user_service->set_elevated_for_testing(true);
317
318  // Load a content pack.
319  scoped_refptr<extensions::UnpackedInstaller> installer(
320      extensions::UnpackedInstaller::Create(service_));
321  installer->set_prompt_for_plugins(false);
322  base::FilePath test_data_dir;
323  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
324  base::FilePath extension_path =
325      test_data_dir.AppendASCII("extensions/managed_mode/content_pack");
326  content::WindowedNotificationObserver extension_load_observer(
327      chrome::NOTIFICATION_EXTENSION_LOADED,
328      content::Source<Profile>(profile_.get()));
329  installer->Load(extension_path);
330  extension_load_observer.Wait();
331  observer.Wait();
332  content::Details<extensions::Extension> details =
333      extension_load_observer.details();
334  scoped_refptr<extensions::Extension> extension =
335      make_scoped_refptr(details.ptr());
336  ASSERT_TRUE(extension.get());
337
338  ScopedVector<ManagedModeSiteList> site_lists =
339      GetActiveSiteLists(managed_user_service);
340  ASSERT_EQ(1u, site_lists.size());
341  std::vector<ManagedModeSiteList::Site> sites;
342  site_lists[0]->GetSites(&sites);
343  ASSERT_EQ(3u, sites.size());
344  EXPECT_EQ(ASCIIToUTF16("YouTube"), sites[0].name);
345  EXPECT_EQ(ASCIIToUTF16("Homestar Runner"), sites[1].name);
346  EXPECT_EQ(base::string16(), sites[2].name);
347
348  EXPECT_EQ(ManagedModeURLFilter::ALLOW,
349            url_filter->GetFilteringBehaviorForURL(example_url));
350  EXPECT_EQ(ManagedModeURLFilter::WARN,
351            url_filter->GetFilteringBehaviorForURL(moose_url));
352
353  // Load a second content pack.
354  installer = extensions::UnpackedInstaller::Create(service_);
355  extension_path =
356      test_data_dir.AppendASCII("extensions/managed_mode/content_pack_2");
357  installer->Load(extension_path);
358  observer.Wait();
359
360  site_lists = GetActiveSiteLists(managed_user_service);
361  ASSERT_EQ(2u, site_lists.size());
362  sites.clear();
363  site_lists[0]->GetSites(&sites);
364  site_lists[1]->GetSites(&sites);
365  ASSERT_EQ(4u, sites.size());
366  // The site lists might be returned in any order, so we put them into a set.
367  std::set<std::string> site_names;
368  for (std::vector<ManagedModeSiteList::Site>::const_iterator it =
369      sites.begin(); it != sites.end(); ++it) {
370    site_names.insert(UTF16ToUTF8(it->name));
371  }
372  EXPECT_TRUE(site_names.count("YouTube") == 1u);
373  EXPECT_TRUE(site_names.count("Homestar Runner") == 1u);
374  EXPECT_TRUE(site_names.count(std::string()) == 1u);
375  EXPECT_TRUE(site_names.count("Moose") == 1u);
376
377  EXPECT_EQ(ManagedModeURLFilter::ALLOW,
378            url_filter->GetFilteringBehaviorForURL(example_url));
379  EXPECT_EQ(ManagedModeURLFilter::ALLOW,
380            url_filter->GetFilteringBehaviorForURL(moose_url));
381
382  // Disable the first content pack.
383  service_->DisableExtension(extension->id(),
384                             extensions::Extension::DISABLE_USER_ACTION);
385  observer.Wait();
386
387  site_lists = GetActiveSiteLists(managed_user_service);
388  ASSERT_EQ(1u, site_lists.size());
389  sites.clear();
390  site_lists[0]->GetSites(&sites);
391  ASSERT_EQ(1u, sites.size());
392  EXPECT_EQ(ASCIIToUTF16("Moose"), sites[0].name);
393
394  EXPECT_EQ(ManagedModeURLFilter::WARN,
395            url_filter->GetFilteringBehaviorForURL(example_url));
396  EXPECT_EQ(ManagedModeURLFilter::ALLOW,
397            url_filter->GetFilteringBehaviorForURL(moose_url));
398}
399#endif  // !defined(OS_ANDROID)
400