1// Copyright (c) 2012 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 <set>
6#include <string>
7
8#include "base/logging.h"
9#include "base/message_loop/message_loop.h"
10#include "base/values.h"
11#include "base/version.h"
12#include "chrome/browser/extensions/extension_management.h"
13#include "chrome/browser/extensions/external_policy_loader.h"
14#include "chrome/browser/extensions/external_provider_impl.h"
15#include "chrome/common/pref_names.h"
16#include "chrome/test/base/testing_pref_service_syncable.h"
17#include "chrome/test/base/testing_profile.h"
18#include "content/public/test/test_browser_thread.h"
19#include "extensions/browser/external_provider_interface.h"
20#include "extensions/browser/pref_names.h"
21#include "extensions/common/extension.h"
22#include "extensions/common/manifest.h"
23#include "testing/gtest/include/gtest/gtest.h"
24
25using content::BrowserThread;
26
27namespace extensions {
28
29class ExternalPolicyLoaderTest : public testing::Test {
30 public:
31  ExternalPolicyLoaderTest() : ui_thread_(BrowserThread::UI, &loop_) {
32  }
33
34  virtual ~ExternalPolicyLoaderTest() {}
35
36 private:
37  // We need these to satisfy BrowserThread::CurrentlyOn(BrowserThread::UI)
38  // checks in ExternalProviderImpl.
39  base::MessageLoopForIO loop_;
40  content::TestBrowserThread ui_thread_;
41};
42
43class MockExternalPolicyProviderVisitor
44    : public ExternalProviderInterface::VisitorInterface {
45 public:
46  MockExternalPolicyProviderVisitor() {
47  }
48
49  // Initialize a provider with |policy_forcelist|, and check that it installs
50  // exactly the extensions specified in |expected_extensions|.
51  void Visit(const base::DictionaryValue& policy_forcelist,
52             const std::set<std::string>& expected_extensions) {
53    profile_.reset(new TestingProfile);
54    profile_->GetTestingPrefService()->SetManagedPref(
55        pref_names::kInstallForceList, policy_forcelist.DeepCopy());
56    provider_.reset(new ExternalProviderImpl(
57        this,
58        new ExternalPolicyLoader(
59            ExtensionManagementFactory::GetForBrowserContext(profile_.get())),
60        profile_.get(),
61        Manifest::INVALID_LOCATION,
62        Manifest::EXTERNAL_POLICY_DOWNLOAD,
63        Extension::NO_FLAGS));
64
65    // Extensions will be removed from this list as they visited,
66    // so it should be emptied by the end.
67    expected_extensions_ = expected_extensions;
68    provider_->VisitRegisteredExtension();
69    EXPECT_TRUE(expected_extensions_.empty());
70  }
71
72  virtual bool OnExternalExtensionFileFound(const std::string& id,
73                                            const Version* version,
74                                            const base::FilePath& path,
75                                            Manifest::Location unused,
76                                            int unused2,
77                                            bool unused3) OVERRIDE {
78    ADD_FAILURE() << "There should be no external extensions from files.";
79    return false;
80  }
81
82  virtual bool OnExternalExtensionUpdateUrlFound(
83      const std::string& id,
84      const std::string& install_parameter,
85      const GURL& update_url,
86      Manifest::Location location,
87      int unused1,
88      bool unused2) OVERRIDE {
89    // Extension has the correct location.
90    EXPECT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD, location);
91
92    // Provider returns the correct location when asked.
93    Manifest::Location location1;
94    scoped_ptr<Version> version1;
95    provider_->GetExtensionDetails(id, &location1, &version1);
96    EXPECT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD, location1);
97    EXPECT_FALSE(version1.get());
98
99    // Remove the extension from our list.
100    EXPECT_EQ(1U, expected_extensions_.erase(id));
101    return true;
102  }
103
104  virtual void OnExternalProviderReady(
105      const ExternalProviderInterface* provider) OVERRIDE {
106    EXPECT_EQ(provider, provider_.get());
107    EXPECT_TRUE(provider->IsReady());
108  }
109
110 private:
111  std::set<std::string> expected_extensions_;
112
113  scoped_ptr<TestingProfile> profile_;
114
115  scoped_ptr<ExternalProviderImpl> provider_;
116
117  DISALLOW_COPY_AND_ASSIGN(MockExternalPolicyProviderVisitor);
118};
119
120TEST_F(ExternalPolicyLoaderTest, PolicyIsParsed) {
121  base::DictionaryValue forced_extensions;
122  std::set<std::string> expected_extensions;
123  extensions::ExternalPolicyLoader::AddExtension(
124      &forced_extensions, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
125      "http://www.example.com/crx?a=5;b=6");
126  expected_extensions.insert("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
127  extensions::ExternalPolicyLoader::AddExtension(
128      &forced_extensions, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
129      "https://clients2.google.com/service/update2/crx");
130  expected_extensions.insert("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
131
132  MockExternalPolicyProviderVisitor mv;
133  mv.Visit(forced_extensions, expected_extensions);
134}
135
136TEST_F(ExternalPolicyLoaderTest, InvalidEntriesIgnored) {
137  base::DictionaryValue forced_extensions;
138  std::set<std::string> expected_extensions;
139
140  extensions::ExternalPolicyLoader::AddExtension(
141      &forced_extensions, "cccccccccccccccccccccccccccccccc",
142      "http://www.example.com/crx");
143  expected_extensions.insert("cccccccccccccccccccccccccccccccc");
144
145  // Add invalid entries.
146  forced_extensions.SetString("invalid", "http://www.example.com/crx");
147  forced_extensions.SetString("dddddddddddddddddddddddddddddddd",
148                              std::string());
149  forced_extensions.SetString("invalid", "bad");
150
151  MockExternalPolicyProviderVisitor mv;
152  mv.Visit(forced_extensions, expected_extensions);
153}
154
155}  // namespace extensions
156