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

Side by Side Diff: chrome/browser/extensions/extension_protocols.cc

Issue 15963003: Generate an etag for chrome-extension:// file requests, so caching can be optional (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cleanup Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/extensions/extension_protocols.h" 5 #include "chrome/browser/extensions/extension_protocols.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base64.h"
9 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/file_util.h"
10 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
11 #include "base/logging.h" 13 #include "base/logging.h"
12 #include "base/memory/weak_ptr.h" 14 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop.h" 15 #include "base/message_loop.h"
14 #include "base/path_service.h" 16 #include "base/path_service.h"
17 #include "base/sha1.h"
15 #include "base/string_util.h" 18 #include "base/string_util.h"
16 #include "base/stringprintf.h" 19 #include "base/stringprintf.h"
17 #include "base/threading/thread_restrictions.h" 20 #include "base/threading/thread_restrictions.h"
18 #include "base/threading/worker_pool.h" 21 #include "base/threading/worker_pool.h"
19 #include "base/utf_string_conversions.h" 22 #include "base/utf_string_conversions.h"
20 #include "build/build_config.h" 23 #include "build/build_config.h"
21 #include "chrome/browser/extensions/extension_info_map.h" 24 #include "chrome/browser/extensions/extension_info_map.h"
22 #include "chrome/browser/extensions/image_loader.h" 25 #include "chrome/browser/extensions/image_loader.h"
23 #include "chrome/common/chrome_paths.h" 26 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/extensions/background_info.h" 27 #include "chrome/common/extensions/background_info.h"
(...skipping 20 matching lines...) Expand all
45 #include "net/url_request/url_request_simple_job.h" 48 #include "net/url_request/url_request_simple_job.h"
46 #include "ui/base/resource/resource_bundle.h" 49 #include "ui/base/resource/resource_bundle.h"
47 50
48 using content::ResourceRequestInfo; 51 using content::ResourceRequestInfo;
49 using extensions::Extension; 52 using extensions::Extension;
50 using extensions::SharedModuleInfo; 53 using extensions::SharedModuleInfo;
51 54
52 namespace { 55 namespace {
53 56
54 net::HttpResponseHeaders* BuildHttpHeaders( 57 net::HttpResponseHeaders* BuildHttpHeaders(
55 const std::string& content_security_policy, bool send_cors_header) { 58 const std::string& content_security_policy, bool send_cors_header,
59 const base::Time& last_modified_time) {
56 std::string raw_headers; 60 std::string raw_headers;
57 raw_headers.append("HTTP/1.1 200 OK"); 61 raw_headers.append("HTTP/1.1 200 OK");
58 if (!content_security_policy.empty()) { 62 if (!content_security_policy.empty()) {
59 raw_headers.append(1, '\0'); 63 raw_headers.append(1, '\0');
60 raw_headers.append("Content-Security-Policy: "); 64 raw_headers.append("Content-Security-Policy: ");
61 raw_headers.append(content_security_policy); 65 raw_headers.append(content_security_policy);
62 } 66 }
63 67
64 if (send_cors_header) { 68 if (send_cors_header) {
65 raw_headers.append(1, '\0'); 69 raw_headers.append(1, '\0');
66 raw_headers.append("Access-Control-Allow-Origin: *"); 70 raw_headers.append("Access-Control-Allow-Origin: *");
67 } 71 }
72
73 if (!last_modified_time.is_null()) {
74 // Hash the time and make an etag to avoid exposing the exact
75 // user installation time of the extension.
76 std::string hash = base::StringPrintf("%f", last_modified_time.ToDoubleT());
rvargas (doing something else) 2013/06/03 21:12:37 nit: ToInternalValue ?
jvoung (off chromium) 2013/06/03 22:08:22 Done.
77 hash = base::SHA1HashString(hash);
78 std::string etag;
79 if (base::Base64Encode(hash, &etag)) {
80 raw_headers.append(1, '\0');
81 raw_headers.append("ETag: \"");
82 raw_headers.append(etag);
83 raw_headers.append("\"");
84 // Also force revalidation.
85 raw_headers.append(1, '\0');
86 raw_headers.append("cache-control: no-cache");
87 }
88 }
89
68 raw_headers.append(2, '\0'); 90 raw_headers.append(2, '\0');
69 return new net::HttpResponseHeaders(raw_headers); 91 return new net::HttpResponseHeaders(raw_headers);
70 } 92 }
71 93
72 void ReadMimeTypeFromFile(const base::FilePath& filename, 94 void ReadMimeTypeFromFile(const base::FilePath& filename,
73 std::string* mime_type, 95 std::string* mime_type,
74 bool* result) { 96 bool* result) {
75 *result = net::GetMimeTypeFromFile(filename, mime_type); 97 *result = net::GetMimeTypeFromFile(filename, mime_type);
76 } 98 }
77 99
100 void GetLastModifiedTime(const base::FilePath& filename,
101 base::Time* last_modified_time) {
102 if (file_util::PathExists(filename)) {
103 base::PlatformFileInfo info;
104 if (file_util::GetFileInfo(filename, &info))
105 *last_modified_time = info.last_modified;
106 }
107 }
108
78 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob { 109 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob {
79 public: 110 public:
80 URLRequestResourceBundleJob(net::URLRequest* request, 111 URLRequestResourceBundleJob(net::URLRequest* request,
81 net::NetworkDelegate* network_delegate, 112 net::NetworkDelegate* network_delegate,
82 const base::FilePath& filename, 113 const base::FilePath& filename,
83 int resource_id, 114 int resource_id,
84 const std::string& content_security_policy, 115 const std::string& content_security_policy,
85 bool send_cors_header) 116 bool send_cors_header)
86 : net::URLRequestSimpleJob(request, network_delegate), 117 : net::URLRequestSimpleJob(request, network_delegate),
87 filename_(filename), 118 filename_(filename),
88 resource_id_(resource_id), 119 resource_id_(resource_id),
89 weak_factory_(this) { 120 weak_factory_(this) {
121 // Leave cache headers out of resource bundle requests.
90 response_info_.headers = BuildHttpHeaders(content_security_policy, 122 response_info_.headers = BuildHttpHeaders(content_security_policy,
91 send_cors_header); 123 send_cors_header,
124 base::Time());
92 } 125 }
93 126
94 // Overridden from URLRequestSimpleJob: 127 // Overridden from URLRequestSimpleJob:
95 virtual int GetData(std::string* mime_type, 128 virtual int GetData(std::string* mime_type,
96 std::string* charset, 129 std::string* charset,
97 std::string* data, 130 std::string* data,
98 const net::CompletionCallback& callback) const OVERRIDE { 131 const net::CompletionCallback& callback) const OVERRIDE {
99 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 132 const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
100 *data = rb.GetRawDataResource(resource_id_).as_string(); 133 *data = rb.GetRawDataResource(resource_id_).as_string();
101 134
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 188
156 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { 189 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob {
157 public: 190 public:
158 GeneratedBackgroundPageJob(net::URLRequest* request, 191 GeneratedBackgroundPageJob(net::URLRequest* request,
159 net::NetworkDelegate* network_delegate, 192 net::NetworkDelegate* network_delegate,
160 const scoped_refptr<const Extension> extension, 193 const scoped_refptr<const Extension> extension,
161 const std::string& content_security_policy) 194 const std::string& content_security_policy)
162 : net::URLRequestSimpleJob(request, network_delegate), 195 : net::URLRequestSimpleJob(request, network_delegate),
163 extension_(extension) { 196 extension_(extension) {
164 const bool send_cors_headers = false; 197 const bool send_cors_headers = false;
198 // Leave cache headers out of generated background page jobs.
165 response_info_.headers = BuildHttpHeaders(content_security_policy, 199 response_info_.headers = BuildHttpHeaders(content_security_policy,
166 send_cors_headers); 200 send_cors_headers,
201 base::Time());
167 } 202 }
168 203
169 // Overridden from URLRequestSimpleJob: 204 // Overridden from URLRequestSimpleJob:
170 virtual int GetData(std::string* mime_type, 205 virtual int GetData(std::string* mime_type,
171 std::string* charset, 206 std::string* charset,
172 std::string* data, 207 std::string* data,
173 const net::CompletionCallback& callback) const OVERRIDE { 208 const net::CompletionCallback& callback) const OVERRIDE {
174 *mime_type = "text/html"; 209 *mime_type = "text/html";
175 *charset = "utf-8"; 210 *charset = "utf-8";
176 211
(...skipping 13 matching lines...) Expand all
190 *info = response_info_; 225 *info = response_info_;
191 } 226 }
192 227
193 private: 228 private:
194 virtual ~GeneratedBackgroundPageJob() {} 229 virtual ~GeneratedBackgroundPageJob() {}
195 230
196 scoped_refptr<const Extension> extension_; 231 scoped_refptr<const Extension> extension_;
197 net::HttpResponseInfo response_info_; 232 net::HttpResponseInfo response_info_;
198 }; 233 };
199 234
200 void ReadResourceFilePath(const extensions::ExtensionResource& resource, 235 void ReadResourceFilePathAndLastModifiedTime(
201 base::FilePath* file_path) { 236 const extensions::ExtensionResource& resource,
237 base::FilePath* file_path,
238 base::Time* last_modified_time) {
202 *file_path = resource.GetFilePath(); 239 *file_path = resource.GetFilePath();
240 GetLastModifiedTime(*file_path, last_modified_time);
203 } 241 }
204 242
205 class URLRequestExtensionJob : public net::URLRequestFileJob { 243 class URLRequestExtensionJob : public net::URLRequestFileJob {
206 public: 244 public:
207 URLRequestExtensionJob(net::URLRequest* request, 245 URLRequestExtensionJob(net::URLRequest* request,
208 net::NetworkDelegate* network_delegate, 246 net::NetworkDelegate* network_delegate,
209 const std::string& extension_id, 247 const std::string& extension_id,
210 const base::FilePath& directory_path, 248 const base::FilePath& directory_path,
211 const base::FilePath& relative_path, 249 const base::FilePath& relative_path,
212 const std::string& content_security_policy, 250 const std::string& content_security_policy,
213 bool send_cors_header) 251 bool send_cors_header)
214 : net::URLRequestFileJob(request, network_delegate, base::FilePath()), 252 : net::URLRequestFileJob(request, network_delegate, base::FilePath()),
215 // TODO(tc): Move all of these files into resources.pak so we don't break 253 // TODO(tc): Move all of these files into resources.pak so we don't break
216 // when updating on Linux. 254 // when updating on Linux.
217 resource_(extension_id, directory_path, relative_path), 255 resource_(extension_id, directory_path, relative_path),
256 content_security_policy_(content_security_policy),
257 send_cors_header_(send_cors_header),
218 weak_factory_(this) { 258 weak_factory_(this) {
219 response_info_.headers = BuildHttpHeaders(content_security_policy,
220 send_cors_header);
221 } 259 }
222 260
223 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { 261 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE {
224 *info = response_info_; 262 *info = response_info_;
225 } 263 }
226 264
227 virtual void Start() OVERRIDE { 265 virtual void Start() OVERRIDE {
228 base::FilePath* read_file_path = new base::FilePath; 266 base::FilePath* read_file_path = new base::FilePath;
267 base::Time* last_modified_time = new base::Time();
229 bool posted = base::WorkerPool::PostTaskAndReply( 268 bool posted = base::WorkerPool::PostTaskAndReply(
230 FROM_HERE, 269 FROM_HERE,
231 base::Bind(&ReadResourceFilePath, resource_, 270 base::Bind(&ReadResourceFilePathAndLastModifiedTime, resource_,
232 base::Unretained(read_file_path)), 271 base::Unretained(read_file_path),
233 base::Bind(&URLRequestExtensionJob::OnFilePathRead, 272 base::Unretained(last_modified_time)),
273 base::Bind(&URLRequestExtensionJob::OnFilePathAndLastModifiedTimeRead,
234 weak_factory_.GetWeakPtr(), 274 weak_factory_.GetWeakPtr(),
235 base::Owned(read_file_path)), 275 base::Owned(read_file_path),
276 base::Owned(last_modified_time)),
236 true /* task is slow */); 277 true /* task is slow */);
237 DCHECK(posted); 278 DCHECK(posted);
238 } 279 }
239 280
240 private: 281 private:
241 virtual ~URLRequestExtensionJob() {} 282 virtual ~URLRequestExtensionJob() {}
242 283
243 void OnFilePathRead(base::FilePath* read_file_path) { 284 void OnFilePathAndLastModifiedTimeRead(base::FilePath* read_file_path,
285 base::Time* last_modified_time) {
244 file_path_ = *read_file_path; 286 file_path_ = *read_file_path;
287 response_info_.headers = BuildHttpHeaders(
288 content_security_policy_,
289 send_cors_header_,
290 *last_modified_time);
245 URLRequestFileJob::Start(); 291 URLRequestFileJob::Start();
246 } 292 }
247 293
248 net::HttpResponseInfo response_info_; 294 net::HttpResponseInfo response_info_;
249 extensions::ExtensionResource resource_; 295 extensions::ExtensionResource resource_;
296 std::string content_security_policy_;
297 bool send_cors_header_;
250 base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_; 298 base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_;
251 }; 299 };
252 300
253 bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info, 301 bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info,
254 const std::string& extension_id, 302 const std::string& extension_id,
255 ExtensionInfoMap* extension_info_map) { 303 ExtensionInfoMap* extension_info_map) {
256 if (!extension_info_map->IsIncognitoEnabled(extension_id)) 304 if (!extension_info_map->IsIncognitoEnabled(extension_id))
257 return false; 305 return false;
258 306
259 // Only allow incognito toplevel navigations to extension resources in 307 // Only allow incognito toplevel navigations to extension resources in
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 send_cors_header); 564 send_cors_header);
517 } 565 }
518 566
519 } // namespace 567 } // namespace
520 568
521 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( 569 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler(
522 bool is_incognito, 570 bool is_incognito,
523 ExtensionInfoMap* extension_info_map) { 571 ExtensionInfoMap* extension_info_map) {
524 return new ExtensionProtocolHandler(is_incognito, extension_info_map); 572 return new ExtensionProtocolHandler(is_incognito, extension_info_map);
525 } 573 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698