OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/scoped_observer.h" | 5 #include "base/scoped_observer.h" |
6 #include "chrome/browser/extensions/extension_browsertest.h" | 6 #include "chrome/browser/extensions/extension_browsertest.h" |
7 #include "chrome/common/chrome_switches.h" | 7 #include "chrome/common/chrome_switches.h" |
8 #include "content/public/test/test_utils.h" | 8 #include "content/public/test/test_utils.h" |
9 #include "extensions/browser/content_verify_job.h" | 9 #include "extensions/browser/content_verify_job.h" |
10 #include "extensions/browser/extension_prefs.h" | 10 #include "extensions/browser/extension_prefs.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 } | 80 } |
81 | 81 |
82 private: | 82 private: |
83 DISALLOW_COPY_AND_ASSIGN(JobDelegate); | 83 DISALLOW_COPY_AND_ASSIGN(JobDelegate); |
84 | 84 |
85 ExtensionId id_; | 85 ExtensionId id_; |
86 bool fail_next_read_; | 86 bool fail_next_read_; |
87 bool fail_next_done_; | 87 bool fail_next_done_; |
88 }; | 88 }; |
89 | 89 |
| 90 class JobObserver : public ContentVerifyJob::TestObserver { |
| 91 public: |
| 92 JobObserver(); |
| 93 virtual ~JobObserver(); |
| 94 |
| 95 // Call this to add an expected job result. |
| 96 void ExpectJobResult(const std::string& extension_id, |
| 97 const base::FilePath& relative_path, |
| 98 bool expected_to_fail); |
| 99 |
| 100 // Wait to see expected jobs. Returns true if we saw all jobs finish as |
| 101 // expected, or false if any job completed with non-expected success/failure |
| 102 // status. |
| 103 bool WaitForExpectedJobs(); |
| 104 |
| 105 // ContentVerifyJob::TestObserver interface |
| 106 virtual void JobStarted(const std::string& extension_id, |
| 107 const base::FilePath& relative_path) OVERRIDE; |
| 108 |
| 109 virtual void JobFinished(const std::string& extension_id, |
| 110 const base::FilePath& relative_path, |
| 111 bool failed) OVERRIDE; |
| 112 |
| 113 private: |
| 114 typedef std::pair<std::string, base::FilePath> ExtensionFile; |
| 115 typedef std::map<ExtensionFile, bool> ExpectedJobs; |
| 116 ExpectedJobs expected_jobs_; |
| 117 scoped_refptr<content::MessageLoopRunner> loop_runner_; |
| 118 bool saw_expected_job_results_; |
| 119 }; |
| 120 |
| 121 void JobObserver::ExpectJobResult(const std::string& extension_id, |
| 122 const base::FilePath& relative_path, |
| 123 bool expected_to_fail) { |
| 124 expected_jobs_.insert(std::make_pair( |
| 125 ExtensionFile(extension_id, relative_path), expected_to_fail)); |
| 126 } |
| 127 |
| 128 JobObserver::JobObserver() : saw_expected_job_results_(false) { |
| 129 } |
| 130 |
| 131 JobObserver::~JobObserver() { |
| 132 } |
| 133 |
| 134 bool JobObserver::WaitForExpectedJobs() { |
| 135 if (!expected_jobs_.empty()) { |
| 136 loop_runner_ = new content::MessageLoopRunner(); |
| 137 loop_runner_->Run(); |
| 138 } |
| 139 return saw_expected_job_results_; |
| 140 } |
| 141 |
| 142 void JobObserver::JobStarted(const std::string& extension_id, |
| 143 const base::FilePath& relative_path) { |
| 144 } |
| 145 |
| 146 void JobObserver::JobFinished(const std::string& extension_id, |
| 147 const base::FilePath& relative_path, |
| 148 bool failed) { |
| 149 ExpectedJobs::iterator i = expected_jobs_.find(ExtensionFile( |
| 150 extension_id, relative_path.NormalizePathSeparatorsTo('/'))); |
| 151 if (i != expected_jobs_.end()) { |
| 152 if (failed != i->second) { |
| 153 saw_expected_job_results_ = false; |
| 154 if (loop_runner_.get()) |
| 155 loop_runner_->Quit(); |
| 156 } |
| 157 expected_jobs_.erase(i); |
| 158 if (expected_jobs_.empty()) { |
| 159 saw_expected_job_results_ = true; |
| 160 if (loop_runner_.get()) |
| 161 loop_runner_->Quit(); |
| 162 } |
| 163 } |
| 164 } |
| 165 |
90 } // namespace | 166 } // namespace |
91 | 167 |
92 class ContentVerifierTest : public ExtensionBrowserTest { | 168 class ContentVerifierTest : public ExtensionBrowserTest { |
93 public: | 169 public: |
94 ContentVerifierTest() {} | 170 ContentVerifierTest() {} |
95 virtual ~ContentVerifierTest() {} | 171 virtual ~ContentVerifierTest() {} |
96 | 172 |
97 virtual void SetUpCommandLine(base::CommandLine* command_line) override { | 173 virtual void SetUpCommandLine(base::CommandLine* command_line) override { |
98 ExtensionBrowserTest::SetUpCommandLine(command_line); | 174 ExtensionBrowserTest::SetUpCommandLine(command_line); |
99 command_line->AppendSwitchASCII( | 175 command_line->AppendSwitchASCII( |
100 switches::kExtensionContentVerification, | 176 switches::kExtensionContentVerification, |
101 switches::kExtensionContentVerificationEnforce); | 177 switches::kExtensionContentVerificationEnforce); |
102 } | 178 } |
103 | 179 |
104 // Setup our unload observer and JobDelegate, and install a test extension. | 180 // Setup our unload observer and JobDelegate, and install a test extension. |
105 virtual void SetUpOnMainThread() override { | 181 virtual void SetUpOnMainThread() override { |
106 ExtensionBrowserTest::SetUpOnMainThread(); | 182 ExtensionBrowserTest::SetUpOnMainThread(); |
| 183 } |
| 184 |
| 185 virtual void TearDownOnMainThread() override { |
| 186 ContentVerifyJob::SetDelegateForTests(NULL); |
| 187 ContentVerifyJob::SetObserverForTests(NULL); |
| 188 ExtensionBrowserTest::TearDownOnMainThread(); |
| 189 } |
| 190 |
| 191 virtual void OpenPageAndWaitForUnload() { |
107 unload_observer_.reset( | 192 unload_observer_.reset( |
108 new UnloadObserver(ExtensionRegistry::Get(profile()))); | 193 new UnloadObserver(ExtensionRegistry::Get(profile()))); |
109 const Extension* extension = InstallExtensionFromWebstore( | 194 const Extension* extension = InstallExtensionFromWebstore( |
110 test_data_dir_.AppendASCII("content_verifier/v1.crx"), 1); | 195 test_data_dir_.AppendASCII("content_verifier/v1.crx"), 1); |
111 ASSERT_TRUE(extension); | 196 ASSERT_TRUE(extension); |
112 id_ = extension->id(); | 197 id_ = extension->id(); |
113 page_url_ = extension->GetResourceURL("page.html"); | 198 page_url_ = extension->GetResourceURL("page.html"); |
114 delegate_.set_id(id_); | 199 delegate_.set_id(id_); |
115 ContentVerifyJob::SetDelegateForTests(&delegate_); | 200 ContentVerifyJob::SetDelegateForTests(&delegate_); |
116 } | |
117 | |
118 virtual void TearDownOnMainThread() override { | |
119 ContentVerifyJob::SetDelegateForTests(NULL); | |
120 ExtensionBrowserTest::TearDownOnMainThread(); | |
121 } | |
122 | |
123 virtual void OpenPageAndWaitForUnload() { | |
124 AddTabAtIndex(1, page_url_, ui::PAGE_TRANSITION_LINK); | 201 AddTabAtIndex(1, page_url_, ui::PAGE_TRANSITION_LINK); |
125 unload_observer_->WaitForUnload(id_); | 202 unload_observer_->WaitForUnload(id_); |
126 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | 203 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
127 int reasons = prefs->GetDisableReasons(id_); | 204 int reasons = prefs->GetDisableReasons(id_); |
128 EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED); | 205 EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED); |
129 | 206 |
130 // This needs to happen before the ExtensionRegistry gets deleted, which | 207 // This needs to happen before the ExtensionRegistry gets deleted, which |
131 // happens before TearDownOnMainThread is called. | 208 // happens before TearDownOnMainThread is called. |
132 unload_observer_.reset(); | 209 unload_observer_.reset(); |
133 } | 210 } |
134 | 211 |
135 protected: | 212 protected: |
136 JobDelegate delegate_; | 213 JobDelegate delegate_; |
137 scoped_ptr<UnloadObserver> unload_observer_; | 214 scoped_ptr<UnloadObserver> unload_observer_; |
138 ExtensionId id_; | 215 ExtensionId id_; |
139 GURL page_url_; | 216 GURL page_url_; |
140 }; | 217 }; |
141 | 218 |
142 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnRead) { | 219 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnRead) { |
143 delegate_.fail_next_read(); | 220 delegate_.fail_next_read(); |
144 OpenPageAndWaitForUnload(); | 221 OpenPageAndWaitForUnload(); |
145 } | 222 } |
146 | 223 |
147 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnDone) { | 224 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnDone) { |
148 delegate_.fail_next_done(); | 225 delegate_.fail_next_done(); |
149 OpenPageAndWaitForUnload(); | 226 OpenPageAndWaitForUnload(); |
150 } | 227 } |
151 | 228 |
| 229 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, DotSlashPaths) { |
| 230 JobObserver job_observer; |
| 231 ContentVerifyJob::SetObserverForTests(&job_observer); |
| 232 std::string id = "hoipipabpcoomfapcecilckodldhmpgl"; |
| 233 |
| 234 job_observer.ExpectJobResult( |
| 235 id, base::FilePath(FILE_PATH_LITERAL("background.js")), false); |
| 236 job_observer.ExpectJobResult( |
| 237 id, base::FilePath(FILE_PATH_LITERAL("page.html")), false); |
| 238 job_observer.ExpectJobResult( |
| 239 id, base::FilePath(FILE_PATH_LITERAL("page.js")), false); |
| 240 job_observer.ExpectJobResult( |
| 241 id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")), false); |
| 242 job_observer.ExpectJobResult( |
| 243 id, base::FilePath(FILE_PATH_LITERAL("page2.js")), false); |
| 244 |
| 245 // Install a test extension we copied from the webstore that has actual |
| 246 // signatures, and contains image paths with leading "./". |
| 247 const Extension* extension = InstallExtensionFromWebstore( |
| 248 test_data_dir_.AppendASCII("content_verifier/dot_slash_paths.crx"), 1); |
| 249 |
| 250 ASSERT_TRUE(extension); |
| 251 ASSERT_EQ(extension->id(), id); |
| 252 |
| 253 EXPECT_TRUE(job_observer.WaitForExpectedJobs()); |
| 254 |
| 255 ContentVerifyJob::SetObserverForTests(NULL); |
| 256 } |
| 257 |
152 } // namespace extensions | 258 } // namespace extensions |
OLD | NEW |