MacViews: Get c/b/ui/views/tabs to build on Mac
[chromium-blink-merge.git] / chrome / browser / extensions / content_verifier_browsertest.cc
blob6dc2f46d7868e3184705955ca0566a7e94eb59b4
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.
5 #include "base/scoped_observer.h"
6 #include "chrome/browser/extensions/extension_browsertest.h"
7 #include "chrome/common/chrome_switches.h"
8 #include "content/public/test/test_utils.h"
9 #include "extensions/browser/content_verify_job.h"
10 #include "extensions/browser/extension_prefs.h"
11 #include "extensions/browser/extension_registry.h"
12 #include "extensions/browser/extension_registry_observer.h"
14 namespace extensions {
16 namespace {
18 // Helper for observing extension unloads.
19 class UnloadObserver : public ExtensionRegistryObserver {
20 public:
21 explicit UnloadObserver(ExtensionRegistry* registry) : observer_(this) {
22 observer_.Add(registry);
24 ~UnloadObserver() override {}
26 void WaitForUnload(const ExtensionId& id) {
27 if (ContainsKey(observed_, id))
28 return;
30 ASSERT_TRUE(loop_runner_.get() == NULL);
31 awaited_id_ = id;
32 loop_runner_ = new content::MessageLoopRunner();
33 loop_runner_->Run();
36 void OnExtensionUnloaded(content::BrowserContext* browser_context,
37 const Extension* extension,
38 UnloadedExtensionInfo::Reason reason) override {
39 observed_.insert(extension->id());
40 if (awaited_id_ == extension->id())
41 loop_runner_->Quit();
44 private:
45 ExtensionId awaited_id_;
46 std::set<ExtensionId> observed_;
47 scoped_refptr<content::MessageLoopRunner> loop_runner_;
48 ScopedObserver<ExtensionRegistry, UnloadObserver> observer_;
51 // Helper for forcing ContentVerifyJob's to return an error.
52 class JobDelegate : public ContentVerifyJob::TestDelegate {
53 public:
54 JobDelegate() : fail_next_read_(false), fail_next_done_(false) {}
56 virtual ~JobDelegate() {}
58 void set_id(const ExtensionId& id) { id_ = id; }
59 void fail_next_read() { fail_next_read_ = true; }
60 void fail_next_done() { fail_next_done_ = true; }
62 ContentVerifyJob::FailureReason BytesRead(const ExtensionId& id,
63 int count,
64 const char* data) override {
65 if (id == id_ && fail_next_read_) {
66 fail_next_read_ = false;
67 return ContentVerifyJob::HASH_MISMATCH;
69 return ContentVerifyJob::NONE;
72 ContentVerifyJob::FailureReason DoneReading(const ExtensionId& id) override {
73 if (id == id_ && fail_next_done_) {
74 fail_next_done_ = false;
75 return ContentVerifyJob::HASH_MISMATCH;
77 return ContentVerifyJob::NONE;
80 private:
81 DISALLOW_COPY_AND_ASSIGN(JobDelegate);
83 ExtensionId id_;
84 bool fail_next_read_;
85 bool fail_next_done_;
88 class JobObserver : public ContentVerifyJob::TestObserver {
89 public:
90 JobObserver();
91 virtual ~JobObserver();
93 // Call this to add an expected job result.
94 void ExpectJobResult(const std::string& extension_id,
95 const base::FilePath& relative_path,
96 bool expected_to_fail);
98 // Wait to see expected jobs. Returns true if we saw all jobs finish as
99 // expected, or false if any job completed with non-expected success/failure
100 // status.
101 bool WaitForExpectedJobs();
103 // ContentVerifyJob::TestObserver interface
104 void JobStarted(const std::string& extension_id,
105 const base::FilePath& relative_path) override;
107 void JobFinished(const std::string& extension_id,
108 const base::FilePath& relative_path,
109 bool failed) override;
111 private:
112 typedef std::pair<std::string, base::FilePath> ExtensionFile;
113 typedef std::map<ExtensionFile, bool> ExpectedJobs;
114 ExpectedJobs expected_jobs_;
115 scoped_refptr<content::MessageLoopRunner> loop_runner_;
116 bool saw_expected_job_results_;
119 void JobObserver::ExpectJobResult(const std::string& extension_id,
120 const base::FilePath& relative_path,
121 bool expected_to_fail) {
122 expected_jobs_.insert(std::make_pair(
123 ExtensionFile(extension_id, relative_path), expected_to_fail));
126 JobObserver::JobObserver() : saw_expected_job_results_(false) {
129 JobObserver::~JobObserver() {
132 bool JobObserver::WaitForExpectedJobs() {
133 if (!expected_jobs_.empty()) {
134 loop_runner_ = new content::MessageLoopRunner();
135 loop_runner_->Run();
137 return saw_expected_job_results_;
140 void JobObserver::JobStarted(const std::string& extension_id,
141 const base::FilePath& relative_path) {
144 void JobObserver::JobFinished(const std::string& extension_id,
145 const base::FilePath& relative_path,
146 bool failed) {
147 ExpectedJobs::iterator i = expected_jobs_.find(ExtensionFile(
148 extension_id, relative_path.NormalizePathSeparatorsTo('/')));
149 if (i != expected_jobs_.end()) {
150 if (failed != i->second) {
151 saw_expected_job_results_ = false;
152 if (loop_runner_.get())
153 loop_runner_->Quit();
155 expected_jobs_.erase(i);
156 if (expected_jobs_.empty()) {
157 saw_expected_job_results_ = true;
158 if (loop_runner_.get())
159 loop_runner_->Quit();
164 } // namespace
166 class ContentVerifierTest : public ExtensionBrowserTest {
167 public:
168 ContentVerifierTest() {}
169 virtual ~ContentVerifierTest() {}
171 void SetUpCommandLine(base::CommandLine* command_line) override {
172 ExtensionBrowserTest::SetUpCommandLine(command_line);
173 command_line->AppendSwitchASCII(
174 switches::kExtensionContentVerification,
175 switches::kExtensionContentVerificationEnforce);
178 // Setup our unload observer and JobDelegate, and install a test extension.
179 void SetUpOnMainThread() override {
180 ExtensionBrowserTest::SetUpOnMainThread();
183 void TearDownOnMainThread() override {
184 ContentVerifyJob::SetDelegateForTests(NULL);
185 ContentVerifyJob::SetObserverForTests(NULL);
186 ExtensionBrowserTest::TearDownOnMainThread();
189 virtual void OpenPageAndWaitForUnload() {
190 unload_observer_.reset(
191 new UnloadObserver(ExtensionRegistry::Get(profile())));
192 const Extension* extension = InstallExtensionFromWebstore(
193 test_data_dir_.AppendASCII("content_verifier/v1.crx"), 1);
194 ASSERT_TRUE(extension);
195 id_ = extension->id();
196 page_url_ = extension->GetResourceURL("page.html");
197 delegate_.set_id(id_);
198 ContentVerifyJob::SetDelegateForTests(&delegate_);
199 AddTabAtIndex(1, page_url_, ui::PAGE_TRANSITION_LINK);
200 unload_observer_->WaitForUnload(id_);
201 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
202 int reasons = prefs->GetDisableReasons(id_);
203 EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED);
205 // This needs to happen before the ExtensionRegistry gets deleted, which
206 // happens before TearDownOnMainThread is called.
207 unload_observer_.reset();
210 protected:
211 JobDelegate delegate_;
212 scoped_ptr<UnloadObserver> unload_observer_;
213 ExtensionId id_;
214 GURL page_url_;
217 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnRead) {
218 delegate_.fail_next_read();
219 OpenPageAndWaitForUnload();
222 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnDone) {
223 delegate_.fail_next_done();
224 OpenPageAndWaitForUnload();
227 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, DotSlashPaths) {
228 JobObserver job_observer;
229 ContentVerifyJob::SetObserverForTests(&job_observer);
230 std::string id = "hoipipabpcoomfapcecilckodldhmpgl";
232 job_observer.ExpectJobResult(
233 id, base::FilePath(FILE_PATH_LITERAL("background.js")), false);
234 job_observer.ExpectJobResult(
235 id, base::FilePath(FILE_PATH_LITERAL("page.html")), false);
236 job_observer.ExpectJobResult(
237 id, base::FilePath(FILE_PATH_LITERAL("page.js")), false);
238 job_observer.ExpectJobResult(
239 id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")), false);
240 job_observer.ExpectJobResult(
241 id, base::FilePath(FILE_PATH_LITERAL("page2.js")), false);
243 // Install a test extension we copied from the webstore that has actual
244 // signatures, and contains image paths with leading "./".
245 const Extension* extension = InstallExtensionFromWebstore(
246 test_data_dir_.AppendASCII("content_verifier/dot_slash_paths.crx"), 1);
248 ASSERT_TRUE(extension);
249 ASSERT_EQ(extension->id(), id);
251 EXPECT_TRUE(job_observer.WaitForExpectedJobs());
253 ContentVerifyJob::SetObserverForTests(NULL);
256 } // namespace extensions