OLD | NEW |
---|---|
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/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/weak_ptr.h" | |
12 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
13 #include "base/path_service.h" | 14 #include "base/path_service.h" |
14 #include "base/string_util.h" | 15 #include "base/string_util.h" |
15 #include "base/stringprintf.h" | 16 #include "base/stringprintf.h" |
16 #include "base/threading/thread_restrictions.h" | 17 #include "base/threading/thread_restrictions.h" |
18 #include "base/threading/worker_pool.h" | |
17 #include "build/build_config.h" | 19 #include "build/build_config.h" |
18 #include "chrome/browser/extensions/extension_info_map.h" | 20 #include "chrome/browser/extensions/extension_info_map.h" |
19 #include "chrome/browser/net/chrome_url_request_context.h" | 21 #include "chrome/browser/net/chrome_url_request_context.h" |
20 #include "chrome/common/chrome_paths.h" | 22 #include "chrome/common/chrome_paths.h" |
21 #include "chrome/common/extensions/extension.h" | 23 #include "chrome/common/extensions/extension.h" |
22 #include "chrome/common/extensions/extension_file_util.h" | 24 #include "chrome/common/extensions/extension_file_util.h" |
23 #include "chrome/common/extensions/extension_resource.h" | 25 #include "chrome/common/extensions/extension_resource.h" |
24 #include "chrome/common/url_constants.h" | 26 #include "chrome/common/url_constants.h" |
25 #include "content/public/browser/resource_request_info.h" | 27 #include "content/public/browser/resource_request_info.h" |
26 #include "googleurl/src/url_util.h" | 28 #include "googleurl/src/url_util.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
51 } | 53 } |
52 | 54 |
53 if (send_cors_header) { | 55 if (send_cors_header) { |
54 raw_headers.append(1, '\0'); | 56 raw_headers.append(1, '\0'); |
55 raw_headers.append("Access-Control-Allow-Origin: *"); | 57 raw_headers.append("Access-Control-Allow-Origin: *"); |
56 } | 58 } |
57 raw_headers.append(2, '\0'); | 59 raw_headers.append(2, '\0'); |
58 return new net::HttpResponseHeaders(raw_headers); | 60 return new net::HttpResponseHeaders(raw_headers); |
59 } | 61 } |
60 | 62 |
63 void ReadMimeTypeFromFile(const FilePath& filename, | |
64 std::string* mime_type, | |
65 bool* result) { | |
66 *result = net::GetMimeTypeFromFile(filename, mime_type); | |
67 } | |
68 | |
61 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob { | 69 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob { |
62 public: | 70 public: |
63 URLRequestResourceBundleJob( | 71 URLRequestResourceBundleJob( |
64 net::URLRequest* request, const FilePath& filename, int resource_id, | 72 net::URLRequest* request, const FilePath& filename, int resource_id, |
65 const std::string& content_security_policy, bool send_cors_header) | 73 const std::string& content_security_policy, bool send_cors_header) |
66 : net::URLRequestSimpleJob(request), | 74 : net::URLRequestSimpleJob(request), |
67 filename_(filename), | 75 filename_(filename), |
68 resource_id_(resource_id) { | 76 resource_id_(resource_id), |
77 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
69 response_info_.headers = BuildHttpHeaders(content_security_policy, | 78 response_info_.headers = BuildHttpHeaders(content_security_policy, |
70 send_cors_header); | 79 send_cors_header); |
71 } | 80 } |
72 | 81 |
73 // Overridden from URLRequestSimpleJob: | 82 // Overridden from URLRequestSimpleJob: |
74 virtual bool GetData(std::string* mime_type, | 83 virtual int GetData(std::string* mime_type, |
75 std::string* charset, | 84 std::string* charset, |
76 std::string* data) const OVERRIDE { | 85 std::string* data, |
86 const net::CompletionCallback& callback) const OVERRIDE { | |
77 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 87 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
78 *data = rb.GetRawDataResource( | 88 *data = rb.GetRawDataResource( |
79 resource_id_, ui::SCALE_FACTOR_NONE).as_string(); | 89 resource_id_, ui::SCALE_FACTOR_NONE).as_string(); |
80 | 90 |
81 // Requests should not block on the disk! On Windows this goes to the | 91 std::string* read_mime_type = new std::string; |
82 // registry. | 92 bool* read_result = new bool; |
83 // http://code.google.com/p/chromium/issues/detail?id=59849 | 93 bool posted = base::WorkerPool::PostTaskAndReply( |
84 bool result; | 94 FROM_HERE, |
85 { | 95 base::Bind(&ReadMimeTypeFromFile, filename_, |
86 base::ThreadRestrictions::ScopedAllowIO allow_io; | 96 base::Unretained(read_mime_type), |
87 result = net::GetMimeTypeFromFile(filename_, mime_type); | 97 base::Unretained(read_result)), |
88 } | 98 base::Bind(&URLRequestResourceBundleJob::OnMimeTypeRead, |
99 weak_factory_.GetWeakPtr(), | |
100 mime_type, charset, data, | |
101 base::Owned(read_mime_type), | |
102 base::Owned(read_result), | |
103 callback), | |
104 true /* task is slow */); | |
105 DCHECK(posted); | |
89 | 106 |
90 if (StartsWithASCII(*mime_type, "text/", false)) { | 107 return net::ERR_IO_PENDING; |
91 // All of our HTML files should be UTF-8 and for other resource types | |
92 // (like images), charset doesn't matter. | |
93 DCHECK(IsStringUTF8(*data)); | |
94 *charset = "utf-8"; | |
95 } | |
96 return result; | |
97 } | 108 } |
98 | 109 |
99 virtual void GetResponseInfo(net::HttpResponseInfo* info) { | 110 virtual void GetResponseInfo(net::HttpResponseInfo* info) { |
100 *info = response_info_; | 111 *info = response_info_; |
101 } | 112 } |
102 | 113 |
103 private: | 114 private: |
104 virtual ~URLRequestResourceBundleJob() { } | 115 virtual ~URLRequestResourceBundleJob() { } |
105 | 116 |
117 void OnMimeTypeRead(std::string* out_mime_type, | |
118 std::string* charset, | |
119 std::string* data, | |
120 std::string* read_mime_type, | |
121 bool* read_result, | |
122 const net::CompletionCallback& callback) { | |
123 *out_mime_type = *read_mime_type; | |
124 if (StartsWithASCII(*read_mime_type, "text/", false)) { | |
125 // All of our HTML files should be UTF-8 and for other resource types | |
126 // (like images), charset doesn't matter. | |
127 DCHECK(IsStringUTF8(*data)); | |
128 *charset = "utf-8"; | |
129 } | |
130 int result = *read_result? net::OK: net::ERR_INVALID_URL; | |
wtc
2012/07/13 22:55:14
The use of net::ERR_INVALID_URL here was not obvio
wtc
2012/07/14 00:08:55
Thank you for the explanation. I didn't think abo
| |
131 callback.Run(result); | |
132 } | |
133 | |
106 // We need the filename of the resource to determine the mime type. | 134 // We need the filename of the resource to determine the mime type. |
107 FilePath filename_; | 135 FilePath filename_; |
108 | 136 |
109 // The resource bundle id to load. | 137 // The resource bundle id to load. |
110 int resource_id_; | 138 int resource_id_; |
111 | 139 |
112 net::HttpResponseInfo response_info_; | 140 net::HttpResponseInfo response_info_; |
141 | |
142 mutable base::WeakPtrFactory<URLRequestResourceBundleJob> weak_factory_; | |
113 }; | 143 }; |
114 | 144 |
115 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { | 145 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { |
116 public: | 146 public: |
117 GeneratedBackgroundPageJob(net::URLRequest* request, | 147 GeneratedBackgroundPageJob(net::URLRequest* request, |
118 const scoped_refptr<const Extension> extension, | 148 const scoped_refptr<const Extension> extension, |
119 const std::string& content_security_policy) | 149 const std::string& content_security_policy) |
120 : net::URLRequestSimpleJob(request), | 150 : net::URLRequestSimpleJob(request), |
121 extension_(extension) { | 151 extension_(extension) { |
122 const bool send_cors_headers = false; | 152 const bool send_cors_headers = false; |
123 response_info_.headers = BuildHttpHeaders(content_security_policy, | 153 response_info_.headers = BuildHttpHeaders(content_security_policy, |
124 send_cors_headers); | 154 send_cors_headers); |
125 } | 155 } |
126 | 156 |
127 // Overridden from URLRequestSimpleJob: | 157 // Overridden from URLRequestSimpleJob: |
128 virtual bool GetData(std::string* mime_type, | 158 virtual int GetData(std::string* mime_type, |
129 std::string* charset, | 159 std::string* charset, |
130 std::string* data) const OVERRIDE { | 160 std::string* data, |
161 const net::CompletionCallback& callback) const OVERRIDE { | |
131 *mime_type = "text/html"; | 162 *mime_type = "text/html"; |
132 *charset = "utf-8"; | 163 *charset = "utf-8"; |
133 | 164 |
134 *data = "<!DOCTYPE html>\n<body>\n"; | 165 *data = "<!DOCTYPE html>\n<body>\n"; |
135 for (size_t i = 0; i < extension_->background_scripts().size(); ++i) { | 166 for (size_t i = 0; i < extension_->background_scripts().size(); ++i) { |
136 *data += "<script src=\""; | 167 *data += "<script src=\""; |
137 *data += extension_->background_scripts()[i]; | 168 *data += extension_->background_scripts()[i]; |
138 *data += "\"></script>\n"; | 169 *data += "\"></script>\n"; |
139 } | 170 } |
140 | 171 |
141 return true; | 172 return net::OK; |
142 } | 173 } |
143 | 174 |
144 virtual void GetResponseInfo(net::HttpResponseInfo* info) { | 175 virtual void GetResponseInfo(net::HttpResponseInfo* info) { |
145 *info = response_info_; | 176 *info = response_info_; |
146 } | 177 } |
147 | 178 |
148 private: | 179 private: |
149 virtual ~GeneratedBackgroundPageJob() {} | 180 virtual ~GeneratedBackgroundPageJob() {} |
150 | 181 |
151 scoped_refptr<const Extension> extension_; | 182 scoped_refptr<const Extension> extension_; |
152 net::HttpResponseInfo response_info_; | 183 net::HttpResponseInfo response_info_; |
153 }; | 184 }; |
154 | 185 |
186 void ReadResourceFilePath(const ExtensionResource& resource, | |
187 FilePath* file_path) { | |
188 *file_path = resource.GetFilePath(); | |
189 } | |
190 | |
155 class URLRequestExtensionJob : public net::URLRequestFileJob { | 191 class URLRequestExtensionJob : public net::URLRequestFileJob { |
156 public: | 192 public: |
157 URLRequestExtensionJob(net::URLRequest* request, | 193 URLRequestExtensionJob(net::URLRequest* request, |
158 const FilePath& filename, | 194 const std::string& extension_id, |
195 const FilePath& directory_path, | |
159 const std::string& content_security_policy, | 196 const std::string& content_security_policy, |
160 bool send_cors_header) | 197 bool send_cors_header) |
161 : net::URLRequestFileJob(request, filename) { | 198 : net::URLRequestFileJob(request, FilePath()), |
199 // TODO(tc): Move all of these files into resources.pak so we don't break | |
200 // when updating on Linux. | |
201 resource_(extension_id, directory_path, | |
202 extension_file_util::ExtensionURLToRelativeFilePath( | |
203 request->url())), | |
204 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
162 response_info_.headers = BuildHttpHeaders(content_security_policy, | 205 response_info_.headers = BuildHttpHeaders(content_security_policy, |
163 send_cors_header); | 206 send_cors_header); |
164 } | 207 } |
165 | 208 |
166 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { | 209 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { |
167 *info = response_info_; | 210 *info = response_info_; |
168 } | 211 } |
169 | 212 |
213 virtual void Start() OVERRIDE { | |
214 FilePath* read_file_path = new FilePath; | |
215 bool posted = base::WorkerPool::PostTaskAndReply( | |
216 FROM_HERE, | |
217 base::Bind(&ReadResourceFilePath, resource_, | |
218 base::Unretained(read_file_path)), | |
219 base::Bind(&URLRequestExtensionJob::OnFilePathRead, | |
220 weak_factory_.GetWeakPtr(), | |
221 base::Owned(read_file_path)), | |
222 true /* task is slow */); | |
223 DCHECK(posted); | |
224 } | |
225 | |
170 private: | 226 private: |
171 virtual ~URLRequestExtensionJob() {} | 227 virtual ~URLRequestExtensionJob() {} |
172 | 228 |
229 void OnFilePathRead(FilePath* read_file_path) { | |
230 file_path_ = *read_file_path; | |
231 URLRequestFileJob::Start(); | |
232 } | |
233 | |
173 net::HttpResponseInfo response_info_; | 234 net::HttpResponseInfo response_info_; |
235 ExtensionResource resource_; | |
236 base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_; | |
174 }; | 237 }; |
175 | 238 |
176 bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info, | 239 bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info, |
177 const std::string& extension_id, | 240 const std::string& extension_id, |
178 ExtensionInfoMap* extension_info_map) { | 241 ExtensionInfoMap* extension_info_map) { |
179 if (!extension_info_map->IsIncognitoEnabled(extension_id)) | 242 if (!extension_info_map->IsIncognitoEnabled(extension_id)) |
180 return false; | 243 return false; |
181 | 244 |
182 // Only allow incognito toplevel navigations to extension resources in | 245 // Only allow incognito toplevel navigations to extension resources in |
183 // split mode. In spanning mode, the extension must run in a single process, | 246 // split mode. In spanning mode, the extension must run in a single process, |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 FilePath bm_resource_path = | 378 FilePath bm_resource_path = |
316 FilePath().AppendASCII(kComponentExtensionResources[i].name); | 379 FilePath().AppendASCII(kComponentExtensionResources[i].name); |
317 bm_resource_path = bm_resource_path.NormalizePathSeparators(); | 380 bm_resource_path = bm_resource_path.NormalizePathSeparators(); |
318 if (relative_path == bm_resource_path) { | 381 if (relative_path == bm_resource_path) { |
319 return new URLRequestResourceBundleJob(request, relative_path, | 382 return new URLRequestResourceBundleJob(request, relative_path, |
320 kComponentExtensionResources[i].value, content_security_policy, | 383 kComponentExtensionResources[i].value, content_security_policy, |
321 send_cors_header); | 384 send_cors_header); |
322 } | 385 } |
323 } | 386 } |
324 } | 387 } |
325 // TODO(tc): Move all of these files into resources.pak so we don't break | |
326 // when updating on Linux. | |
327 ExtensionResource resource(extension_id, directory_path, | |
328 extension_file_util::ExtensionURLToRelativeFilePath(request->url())); | |
329 | 388 |
330 FilePath resource_file_path; | 389 return new URLRequestExtensionJob(request, extension_id, directory_path, |
331 { | |
332 // Getting the file path will touch the file system. Fixing | |
333 // crbug.com/59849 would also fix this. Suppress the error for now. | |
334 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
335 resource_file_path = resource.GetFilePath(); | |
336 } | |
337 | |
338 return new URLRequestExtensionJob(request, resource_file_path, | |
339 content_security_policy, send_cors_header); | 390 content_security_policy, send_cors_header); |
340 } | 391 } |
341 | 392 |
342 } // namespace | 393 } // namespace |
343 | 394 |
344 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( | 395 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( |
345 bool is_incognito, | 396 bool is_incognito, |
346 ExtensionInfoMap* extension_info_map) { | 397 ExtensionInfoMap* extension_info_map) { |
347 return new ExtensionProtocolHandler(is_incognito, extension_info_map); | 398 return new ExtensionProtocolHandler(is_incognito, extension_info_map); |
348 } | 399 } |
OLD | NEW |