Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: extensions/browser/updater/update_service_unittest.cc

Issue 1362043005: Add extensions code to use common updater in components/update_client/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merged latest origin/master Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « extensions/browser/updater/update_service_factory.cc ('k') | extensions/extensions.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 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 <vector>
6
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/run_loop.h"
10 #include "base/values.h"
11 #include "components/crx_file/id_util.h"
12 #include "components/update_client/update_client.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "content/public/test/test_utils.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/browser/extensions_test.h"
17 #include "extensions/browser/mock_extension_system.h"
18 #include "extensions/browser/test_extensions_browser_client.h"
19 #include "extensions/browser/updater/update_service.h"
20 #include "extensions/common/extension_builder.h"
21 #include "extensions/common/value_builder.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 namespace {
25
26 class FakeUpdateClient : public update_client::UpdateClient {
27 public:
28 FakeUpdateClient();
29
30 // Returns the data we've gotten from the CrxDataCallback for ids passed to
31 // the Update function.
32 std::vector<update_client::CrxComponent>* data() { return &data_; }
33
34 // update_client::UpdateClient
35 void AddObserver(Observer* observer) override {}
36 void RemoveObserver(Observer* observer) override {}
37 void Install(const std::string& id,
38 const CrxDataCallback& crx_data_callback,
39 const CompletionCallback& completion_callback) override {}
40 void Update(const std::vector<std::string>& ids,
41 const CrxDataCallback& crx_data_callback,
42 const CompletionCallback& completion_callback) override;
43 bool GetCrxUpdateState(
44 const std::string& id,
45 update_client::CrxUpdateItem* update_item) const override {
46 return false;
47 }
48 bool IsUpdating(const std::string& id) const override { return false; }
49
50 protected:
51 friend class base::RefCounted<FakeUpdateClient>;
52 ~FakeUpdateClient() override {}
53
54 std::vector<update_client::CrxComponent> data_;
55 };
56
57 FakeUpdateClient::FakeUpdateClient() {}
58
59 void FakeUpdateClient::Update(const std::vector<std::string>& ids,
60 const CrxDataCallback& crx_data_callback,
61 const CompletionCallback& completion_callback) {
62 crx_data_callback.Run(ids, &data_);
63 }
64
65 } // namespace
66
67 namespace extensions {
68
69 namespace {
70
71 // A fake ExtensionSystem that lets us intercept calls to install new
72 // versions of an extension.
73 class FakeExtensionSystem : public MockExtensionSystem {
74 public:
75 explicit FakeExtensionSystem(content::BrowserContext* context)
76 : MockExtensionSystem(context) {}
77 ~FakeExtensionSystem() override {}
78
79 struct InstallUpdateRequest {
80 std::string extension_id;
81 base::FilePath temp_dir;
82 };
83
84 std::vector<InstallUpdateRequest>* install_requests() {
85 return &install_requests_;
86 }
87
88 void set_install_callback(const base::Closure& callback) {
89 next_install_callback_ = callback;
90 }
91
92 // ExtensionSystem override
93 void InstallUpdate(const std::string& extension_id,
94 const base::FilePath& temp_dir) override {
95 base::DeleteFile(temp_dir, true /*recursive*/);
96 InstallUpdateRequest request;
97 request.extension_id = extension_id;
98 request.temp_dir = temp_dir;
99 install_requests_.push_back(request);
100 if (!next_install_callback_.is_null()) {
101 base::Closure tmp = next_install_callback_;
102 next_install_callback_.Reset();
103 tmp.Run();
104 }
105 }
106
107 private:
108 std::vector<InstallUpdateRequest> install_requests_;
109 base::Closure next_install_callback_;
110 };
111
112 class UpdateServiceTest : public ExtensionsTest {
113 public:
114 UpdateServiceTest() {
115 extensions_browser_client()->set_extension_system_factory(
116 &fake_extension_system_factory_);
117 }
118 ~UpdateServiceTest() override {}
119
120 void SetUp() override {
121 ExtensionsTest::SetUp();
122 browser_threads_.reset(new content::TestBrowserThreadBundle(
123 content::TestBrowserThreadBundle::DEFAULT));
124
125 extensions_browser_client()->SetUpdateClientFactory(base::Bind(
126 &UpdateServiceTest::CreateUpdateClient, base::Unretained(this)));
127
128 update_service_ = UpdateService::Get(browser_context());
129 }
130
131 protected:
132 UpdateService* update_service() const { return update_service_; }
133 FakeUpdateClient* update_client() const { return update_client_.get(); }
134
135 update_client::UpdateClient* CreateUpdateClient() {
136 // We only expect that this will get called once, so consider it an error
137 // if our update_client_ is already non-null.
138 EXPECT_EQ(nullptr, update_client_.get());
139 update_client_ = new FakeUpdateClient();
140 return update_client_.get();
141 }
142
143 // Helper function that creates a file at |relative_path| within |directory|
144 // and fills it with |content|.
145 bool AddFileToDirectory(const base::FilePath& directory,
146 const base::FilePath& relative_path,
147 const std::string& content) {
148 base::FilePath full_path = directory.Append(relative_path);
149 if (!CreateDirectory(full_path.DirName()))
150 return false;
151 int result = base::WriteFile(full_path, content.data(), content.size());
152 return (static_cast<size_t>(result) == content.size());
153 }
154
155 FakeExtensionSystem* extension_system() {
156 return static_cast<FakeExtensionSystem*>(
157 fake_extension_system_factory_.GetForBrowserContext(browser_context()));
158 }
159
160 private:
161 UpdateService* update_service_;
162 scoped_refptr<FakeUpdateClient> update_client_;
163 scoped_ptr<content::TestBrowserThreadBundle> browser_threads_;
164 MockExtensionSystemFactory<FakeExtensionSystem>
165 fake_extension_system_factory_;
166 };
167
168 TEST_F(UpdateServiceTest, BasicUpdateOperations) {
169 // Create a temporary directory that a fake extension will live in and fill
170 // it with some test files.
171 base::ScopedTempDir temp_dir;
172 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
173 base::FilePath foo_js(FILE_PATH_LITERAL("foo.js"));
174 base::FilePath bar_html(FILE_PATH_LITERAL("bar/bar.html"));
175 ASSERT_TRUE(AddFileToDirectory(temp_dir.path(), foo_js, "hello"))
176 << "Failed to write " << temp_dir.path().value() << "/" << foo_js.value();
177 ASSERT_TRUE(AddFileToDirectory(temp_dir.path(), bar_html, "world"));
178
179 ExtensionBuilder builder;
180 builder.SetManifest(DictionaryBuilder()
181 .Set("name", "Foo")
182 .Set("version", "1.0")
183 .Set("manifest_version", 2));
184 builder.SetID(crx_file::id_util::GenerateId("whatever"));
185 builder.SetPath(temp_dir.path());
186
187 scoped_refptr<Extension> extension1(builder.Build());
188
189 ExtensionRegistry::Get(browser_context())->AddEnabled(extension1);
190 std::vector<std::string> ids;
191 ids.push_back(extension1->id());
192
193 // Start an update check and verify that the UpdateClient was sent the right
194 // data.
195 update_service()->StartUpdateCheck(ids);
196 std::vector<update_client::CrxComponent>* data = update_client()->data();
197 ASSERT_NE(nullptr, data);
198 ASSERT_EQ(1u, data->size());
199
200 ASSERT_TRUE(data->at(0).version.Equals(*extension1->version()));
201 update_client::CrxInstaller* installer = data->at(0).installer.get();
202 ASSERT_NE(installer, nullptr);
203
204 // The GetInstalledFile method is used when processing differential updates
205 // to get a path to an existing file in an extension. We want to test a
206 // number of scenarios to be user we handle invalid relative paths, don't
207 // accidentally return paths outside the extension's dir, etc.
208 base::FilePath tmp;
209 EXPECT_TRUE(installer->GetInstalledFile(foo_js.MaybeAsASCII(), &tmp));
210 EXPECT_EQ(temp_dir.path().Append(foo_js), tmp) << tmp.value();
211
212 EXPECT_TRUE(installer->GetInstalledFile(bar_html.MaybeAsASCII(), &tmp));
213 EXPECT_EQ(temp_dir.path().Append(bar_html), tmp) << tmp.value();
214
215 EXPECT_FALSE(installer->GetInstalledFile("does_not_exist", &tmp));
216 EXPECT_FALSE(installer->GetInstalledFile("does/not/exist", &tmp));
217 EXPECT_FALSE(installer->GetInstalledFile("/does/not/exist", &tmp));
218 EXPECT_FALSE(installer->GetInstalledFile("C:\\tmp", &tmp));
219
220 base::FilePath system_temp_dir;
221 ASSERT_TRUE(base::GetTempDir(&system_temp_dir));
222 EXPECT_FALSE(
223 installer->GetInstalledFile(system_temp_dir.MaybeAsASCII(), &tmp));
224
225 // Test the install callback.
226 base::ScopedTempDir new_version_dir;
227 ASSERT_TRUE(new_version_dir.CreateUniqueTempDir());
228 scoped_ptr<base::DictionaryValue> new_manifest(
229 extension1->manifest()->value()->DeepCopy());
230 new_manifest->SetString("version", "2.0");
231
232 installer->Install(*new_manifest, new_version_dir.path());
233
234 scoped_refptr<content::MessageLoopRunner> loop_runner =
235 new content::MessageLoopRunner();
236 extension_system()->set_install_callback(loop_runner->QuitClosure());
237 loop_runner->Run();
238
239 std::vector<FakeExtensionSystem::InstallUpdateRequest>* requests =
240 extension_system()->install_requests();
241 ASSERT_EQ(1u, requests->size());
242 EXPECT_EQ(requests->at(0).extension_id, extension1->id());
243 EXPECT_NE(requests->at(0).temp_dir.value(), new_version_dir.path().value());
244 }
245
246 } // namespace
247
248 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/updater/update_service_factory.cc ('k') | extensions/extensions.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698