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

Side by Side Diff: extensions/browser/content_verifier.cc

Issue 1315713009: Fix content verification failures on unusual content script paths (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix windows compile error Created 5 years, 3 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 | « chrome/test/data/extensions/content_verifier/dot_slash_paths/manifest.json ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "extensions/browser/content_verifier.h" 5 #include "extensions/browser/content_verifier.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "extensions/browser/content_hash_fetcher.h" 13 #include "extensions/browser/content_hash_fetcher.h"
14 #include "extensions/browser/content_hash_reader.h" 14 #include "extensions/browser/content_hash_reader.h"
15 #include "extensions/browser/content_verifier_delegate.h" 15 #include "extensions/browser/content_verifier_delegate.h"
16 #include "extensions/browser/content_verifier_io_data.h" 16 #include "extensions/browser/content_verifier_io_data.h"
17 #include "extensions/browser/extension_registry.h" 17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/common/constants.h" 18 #include "extensions/common/constants.h"
19 #include "extensions/common/extension_l10n_util.h" 19 #include "extensions/common/extension_l10n_util.h"
20 20
21 namespace extensions { 21 namespace extensions {
22 22
23 namespace { 23 namespace {
24 24
25 ContentVerifier::TestObserver* g_test_observer = NULL; 25 ContentVerifier::TestObserver* g_test_observer = NULL;
26 26
27 // This function converts paths like "//foo/bar", "./foo/bar", and
28 // "/foo/bar" to "foo/bar". It also converts path separators to "/".
29 base::FilePath NormalizeRelativePath(const base::FilePath& path) {
30 if (path.ReferencesParent())
31 return base::FilePath();
32
33 std::vector<base::FilePath::StringType> parts;
34 path.GetComponents(&parts);
35 if (parts.empty())
36 return base::FilePath();
37
38 // Remove the first component if it is '.' or '/' or '//'.
39 const base::FilePath::StringType separators(
40 base::FilePath::kSeparators, base::FilePath::kSeparatorsLength);
41 if (!parts[0].empty() &&
42 (parts[0] == base::FilePath::kCurrentDirectory ||
43 parts[0].find_first_not_of(separators) == std::string::npos))
44 parts.erase(parts.begin());
45
46 // Note that elsewhere we always normalize path separators to '/' so this
47 // should work for all platforms.
48 return base::FilePath(
49 base::JoinString(parts, base::FilePath::StringType(1, '/')));
50 }
51
27 } // namespace 52 } // namespace
28 53
29 // static 54 // static
30 void ContentVerifier::SetObserverForTests(TestObserver* observer) { 55 void ContentVerifier::SetObserverForTests(TestObserver* observer) {
31 g_test_observer = observer; 56 g_test_observer = observer;
32 } 57 }
33 58
34 ContentVerifier::ContentVerifier(content::BrowserContext* context, 59 ContentVerifier::ContentVerifier(content::BrowserContext* context,
35 ContentVerifierDelegate* delegate) 60 ContentVerifierDelegate* delegate)
36 : shutdown_(false), 61 : shutdown_(false),
(...skipping 29 matching lines...) Expand all
66 const std::string& extension_id, 91 const std::string& extension_id,
67 const base::FilePath& extension_root, 92 const base::FilePath& extension_root,
68 const base::FilePath& relative_path) { 93 const base::FilePath& relative_path) {
69 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 94 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
70 95
71 const ContentVerifierIOData::ExtensionData* data = 96 const ContentVerifierIOData::ExtensionData* data =
72 io_data_->GetData(extension_id); 97 io_data_->GetData(extension_id);
73 if (!data) 98 if (!data)
74 return NULL; 99 return NULL;
75 100
101 base::FilePath normalized_path = NormalizeRelativePath(relative_path);
102
76 std::set<base::FilePath> paths; 103 std::set<base::FilePath> paths;
77 paths.insert(relative_path); 104 paths.insert(normalized_path);
78 if (!ShouldVerifyAnyPaths(extension_id, extension_root, paths)) 105 if (!ShouldVerifyAnyPaths(extension_id, extension_root, paths))
79 return NULL; 106 return NULL;
80 107
81 // TODO(asargent) - we can probably get some good performance wins by having 108 // TODO(asargent) - we can probably get some good performance wins by having
82 // a cache of ContentHashReader's that we hold onto past the end of each job. 109 // a cache of ContentHashReader's that we hold onto past the end of each job.
83 return new ContentVerifyJob( 110 return new ContentVerifyJob(
84 new ContentHashReader(extension_id, data->version, extension_root, 111 new ContentHashReader(extension_id, data->version, extension_root,
85 relative_path, delegate_->GetPublicKey()), 112 normalized_path, delegate_->GetPublicKey()),
86 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id)); 113 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id));
87 } 114 }
88 115
89 void ContentVerifier::VerifyFailed(const std::string& extension_id, 116 void ContentVerifier::VerifyFailed(const std::string& extension_id,
90 ContentVerifyJob::FailureReason reason) { 117 ContentVerifyJob::FailureReason reason) {
91 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { 118 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
92 content::BrowserThread::PostTask( 119 content::BrowserThread::PostTask(
93 content::BrowserThread::UI, 120 content::BrowserThread::UI,
94 FROM_HERE, 121 FROM_HERE,
95 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason)); 122 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason));
(...skipping 13 matching lines...) Expand all
109 136
110 if (reason == ContentVerifyJob::MISSING_ALL_HASHES) { 137 if (reason == ContentVerifyJob::MISSING_ALL_HASHES) {
111 // If we failed because there were no hashes yet for this extension, just 138 // If we failed because there were no hashes yet for this extension, just
112 // request some. 139 // request some.
113 fetcher_->DoFetch(extension, true /* force */); 140 fetcher_->DoFetch(extension, true /* force */);
114 } else { 141 } else {
115 delegate_->VerifyFailed(extension_id, reason); 142 delegate_->VerifyFailed(extension_id, reason);
116 } 143 }
117 } 144 }
118 145
119 static base::FilePath MakeImagePathRelative(const base::FilePath& path) {
120 if (path.ReferencesParent())
121 return base::FilePath();
122
123 std::vector<base::FilePath::StringType> parts;
124 path.GetComponents(&parts);
125 if (parts.empty())
126 return base::FilePath();
127
128 // Remove the first component if it is '.' or '/' or '//'.
129 const base::FilePath::StringType separators(
130 base::FilePath::kSeparators, base::FilePath::kSeparatorsLength);
131 if (!parts[0].empty() &&
132 (parts[0] == base::FilePath::kCurrentDirectory ||
133 parts[0].find_first_not_of(separators) == std::string::npos))
134 parts.erase(parts.begin());
135
136 // Note that elsewhere we always normalize path separators to '/' so this
137 // should work for all platforms.
138 return base::FilePath(
139 base::JoinString(parts, base::FilePath::StringType(1, '/')));
140 }
141
142 void ContentVerifier::OnExtensionLoaded( 146 void ContentVerifier::OnExtensionLoaded(
143 content::BrowserContext* browser_context, 147 content::BrowserContext* browser_context,
144 const Extension* extension) { 148 const Extension* extension) {
145 if (shutdown_) 149 if (shutdown_)
146 return; 150 return;
147 151
148 ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); 152 ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension);
149 if (mode != ContentVerifierDelegate::NONE) { 153 if (mode != ContentVerifierDelegate::NONE) {
150 // The browser image paths from the extension may not be relative (eg 154 // The browser image paths from the extension may not be relative (eg
151 // they might have leading '/' or './'), so we strip those to make 155 // they might have leading '/' or './'), so we strip those to make
152 // comparing to actual relative paths work later on. 156 // comparing to actual relative paths work later on.
153 std::set<base::FilePath> original_image_paths = 157 std::set<base::FilePath> original_image_paths =
154 delegate_->GetBrowserImagePaths(extension); 158 delegate_->GetBrowserImagePaths(extension);
155 159
156 scoped_ptr<std::set<base::FilePath>> image_paths( 160 scoped_ptr<std::set<base::FilePath>> image_paths(
157 new std::set<base::FilePath>); 161 new std::set<base::FilePath>);
158 for (const auto& path : original_image_paths) { 162 for (const auto& path : original_image_paths) {
159 image_paths->insert(MakeImagePathRelative(path)); 163 image_paths->insert(NormalizeRelativePath(path));
160 } 164 }
161 165
162 scoped_ptr<ContentVerifierIOData::ExtensionData> data( 166 scoped_ptr<ContentVerifierIOData::ExtensionData> data(
163 new ContentVerifierIOData::ExtensionData( 167 new ContentVerifierIOData::ExtensionData(
164 image_paths.Pass(), 168 image_paths.Pass(),
165 extension->version() ? *extension->version() : base::Version())); 169 extension->version() ? *extension->version() : base::Version()));
166 content::BrowserThread::PostTask(content::BrowserThread::IO, 170 content::BrowserThread::PostTask(content::BrowserThread::IO,
167 FROM_HERE, 171 FROM_HERE,
168 base::Bind(&ContentVerifierIOData::AddData, 172 base::Bind(&ContentVerifierIOData::AddData,
169 io_data_, 173 io_data_,
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 !extension_l10n_util::ShouldSkipValidation( 280 !extension_l10n_util::ShouldSkipValidation(
277 locales_dir, full_path.DirName(), *all_locales)) 281 locales_dir, full_path.DirName(), *all_locales))
278 continue; 282 continue;
279 } 283 }
280 return true; 284 return true;
281 } 285 }
282 return false; 286 return false;
283 } 287 }
284 288
285 } // namespace extensions 289 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/test/data/extensions/content_verifier/dot_slash_paths/manifest.json ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698