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

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: responded to review comments 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
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 update_client_ = new FakeUpdateClient();
126 extensions_browser_client()->set_update_client(update_client_);
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 // Helper function that creates a file at |relative_path| within |directory|
136 // and fills it with |content|.
137 bool AddFileToDirectory(const base::FilePath& directory,
138 const base::FilePath& relative_path,
139 const std::string& content) {
140 base::FilePath full_path = directory.Append(relative_path);
141 if (!CreateDirectory(full_path.DirName()))
142 return false;
143 int result = base::WriteFile(full_path, content.data(), content.size());
144 return (static_cast<size_t>(result) == content.size());
145 }
146
147 FakeExtensionSystem* extension_system() {
148 return static_cast<FakeExtensionSystem*>(
149 fake_extension_system_factory_.GetForBrowserContext(browser_context()));
150 }
151
152 private:
153 UpdateService* update_service_;
154 scoped_refptr<FakeUpdateClient> update_client_;
155 scoped_ptr<content::TestBrowserThreadBundle> browser_threads_;
156 MockExtensionSystemFactory<FakeExtensionSystem>
157 fake_extension_system_factory_;
158 };
159
160 TEST_F(UpdateServiceTest, BasicUpdateOperations) {
161 // Create a temporary directory that a fake extension will live in and fill
162 // it with some test files.
163 base::ScopedTempDir temp_dir;
164 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
165 base::FilePath foo_js(FILE_PATH_LITERAL("foo.js"));
166 base::FilePath bar_html(FILE_PATH_LITERAL("bar/bar.html"));
167 ASSERT_TRUE(AddFileToDirectory(temp_dir.path(), foo_js, "hello"))
168 << "Failed to write " << temp_dir.path().value() << "/" << foo_js.value();
169 ASSERT_TRUE(AddFileToDirectory(temp_dir.path(), bar_html, "world"));
170
171 ExtensionBuilder builder;
172 builder.SetManifest(DictionaryBuilder()
173 .Set("name", "Foo")
174 .Set("version", "1.0")
175 .Set("manifest_version", 2));
176 builder.SetID(crx_file::id_util::GenerateId("whatever"));
177 builder.SetPath(temp_dir.path());
178
179 scoped_refptr<Extension> extension1(builder.Build());
180
181 ExtensionRegistry::Get(browser_context())->AddEnabled(extension1);
182 std::vector<std::string> ids;
183 ids.push_back(extension1->id());
184
185 // Start an update check and verify that the UpdateClient was sent the right
186 // data.
187 update_service()->StartUpdateCheck(ids);
188 std::vector<update_client::CrxComponent>* data = update_client()->data();
189 ASSERT_NE(nullptr, data);
190 ASSERT_EQ(1u, data->size());
191
192 ASSERT_TRUE(data->at(0).version.Equals(*extension1->version()));
193 update_client::CrxInstaller* installer = data->at(0).installer.get();
194 ASSERT_NE(installer, nullptr);
195
196 // The GetInstalledFile method is used when processing differential updates
197 // to get a path to an existing file in an extension. We want to test a
198 // number of scenarios to be user we handle invalid relative paths, don't
199 // accidentally return paths outside the extension's dir, etc.
200 base::FilePath tmp;
201 EXPECT_TRUE(installer->GetInstalledFile(foo_js.MaybeAsASCII(), &tmp));
202 EXPECT_EQ(temp_dir.path().Append(foo_js), tmp) << tmp.value();
203
204 EXPECT_TRUE(installer->GetInstalledFile(bar_html.MaybeAsASCII(), &tmp));
205 EXPECT_EQ(temp_dir.path().Append(bar_html), tmp) << tmp.value();
206
207 EXPECT_FALSE(installer->GetInstalledFile("does_not_exist", &tmp));
208 EXPECT_FALSE(installer->GetInstalledFile("does/not/exist", &tmp));
209 EXPECT_FALSE(installer->GetInstalledFile("/does/not/exist", &tmp));
210 EXPECT_FALSE(installer->GetInstalledFile("C:\\tmp", &tmp));
211
212 base::FilePath system_temp_dir;
213 ASSERT_TRUE(base::GetTempDir(&system_temp_dir));
214 EXPECT_FALSE(
215 installer->GetInstalledFile(system_temp_dir.MaybeAsASCII(), &tmp));
216
217 // Test the install callback.
218 base::ScopedTempDir new_version_dir;
219 ASSERT_TRUE(new_version_dir.CreateUniqueTempDir());
220 scoped_ptr<base::DictionaryValue> new_manifest(
221 extension1->manifest()->value()->DeepCopy());
222 new_manifest->SetString("version", "2.0");
223
224 installer->Install(*new_manifest, new_version_dir.path());
225
226 scoped_refptr<content::MessageLoopRunner> loop_runner =
227 new content::MessageLoopRunner();
228 extension_system()->set_install_callback(loop_runner->QuitClosure());
229 loop_runner->Run();
230
231 std::vector<FakeExtensionSystem::InstallUpdateRequest>* requests =
232 extension_system()->install_requests();
233 ASSERT_EQ(1u, requests->size());
234 EXPECT_EQ(requests->at(0).extension_id, extension1->id());
235 EXPECT_NE(requests->at(0).temp_dir.value(), new_version_dir.path().value());
236 }
237
238 } // namespace
239
240 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698