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/renderer_host/chrome_resource_dispatcher_host_delegate.
h" | 5 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.
h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/base64.h" | 10 #include "base/base64.h" |
| 11 #include "base/guid.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
13 #include "chrome/browser/chrome_notification_types.h" | 14 #include "chrome/browser/chrome_notification_types.h" |
14 #include "chrome/browser/component_updater/component_updater_service.h" | 15 #include "chrome/browser/component_updater/component_updater_service.h" |
15 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" | 16 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" |
16 #include "chrome/browser/content_settings/host_content_settings_map.h" | 17 #include "chrome/browser/content_settings/host_content_settings_map.h" |
17 #include "chrome/browser/download/download_request_limiter.h" | 18 #include "chrome/browser/download/download_request_limiter.h" |
18 #include "chrome/browser/download/download_resource_throttle.h" | 19 #include "chrome/browser/download/download_resource_throttle.h" |
19 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h" | 20 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h" |
20 #include "chrome/browser/extensions/extension_renderer_state.h" | 21 #include "chrome/browser/extensions/extension_renderer_state.h" |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 if (prerender_contents) | 150 if (prerender_contents) |
150 prerender_contents->AddNetworkBytes(bytes); | 151 prerender_contents->AddNetworkBytes(bytes); |
151 | 152 |
152 prerender::PrerenderManager* prerender_manager = | 153 prerender::PrerenderManager* prerender_manager = |
153 GetPrerenderManager(render_process_id, render_view_id); | 154 GetPrerenderManager(render_process_id, render_view_id); |
154 if (prerender_manager) | 155 if (prerender_manager) |
155 prerender_manager->AddProfileNetworkBytesIfEnabled(bytes); | 156 prerender_manager->AddProfileNetworkBytesIfEnabled(bytes); |
156 } | 157 } |
157 | 158 |
158 #if !defined(OS_ANDROID) | 159 #if !defined(OS_ANDROID) |
159 // Goes through the extension's file browser handlers and checks if there is one | |
160 // that can handle the |mime_type|. | |
161 // |extension| must not be NULL. | |
162 bool ExtensionCanHandleMimeType(const Extension* extension, | |
163 const std::string& mime_type) { | |
164 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); | |
165 if (!handler) | |
166 return false; | |
167 | |
168 return handler->CanHandleMIMEType(mime_type); | |
169 } | |
170 | |
171 void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamHandle> stream, | 160 void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamHandle> stream, |
172 int64 expected_content_size, | 161 int64 expected_content_size, |
173 int render_process_id, | 162 int render_process_id, |
174 int render_view_id, | 163 int render_view_id, |
175 const std::string& extension_id) { | 164 const std::string& extension_id, |
| 165 const std::string& view_id) { |
176 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 166 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
177 | 167 |
178 content::WebContents* web_contents = | 168 content::WebContents* web_contents = |
179 tab_util::GetWebContentsByID(render_process_id, render_view_id); | 169 tab_util::GetWebContentsByID(render_process_id, render_view_id); |
180 if (!web_contents) | 170 if (!web_contents) |
181 return; | 171 return; |
182 | 172 |
183 // If the request was for a prerender, abort the prerender and do not | 173 // If the request was for a prerender, abort the prerender and do not |
184 // continue. | 174 // continue. |
185 prerender::PrerenderContents* prerender_contents = | 175 prerender::PrerenderContents* prerender_contents = |
186 prerender::PrerenderContents::FromWebContents(web_contents); | 176 prerender::PrerenderContents::FromWebContents(web_contents); |
187 if (prerender_contents) { | 177 if (prerender_contents) { |
188 prerender_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD); | 178 prerender_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD); |
189 return; | 179 return; |
190 } | 180 } |
191 | 181 |
192 Profile* profile = | 182 Profile* profile = |
193 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 183 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
194 | 184 |
195 StreamsPrivateAPI* streams_private = StreamsPrivateAPI::Get(profile); | 185 StreamsPrivateAPI* streams_private = StreamsPrivateAPI::Get(profile); |
196 if (!streams_private) | 186 if (!streams_private) |
197 return; | 187 return; |
198 streams_private->ExecuteMimeTypeHandler( | 188 streams_private->ExecuteMimeTypeHandler( |
199 extension_id, web_contents, stream.Pass(), expected_content_size); | 189 extension_id, web_contents, stream.Pass(), view_id, |
| 190 expected_content_size); |
200 } | 191 } |
201 | 192 |
202 void LaunchURL(const GURL& url, int render_process_id, int render_view_id, | 193 void LaunchURL(const GURL& url, int render_process_id, int render_view_id, |
203 bool user_gesture) { | 194 bool user_gesture) { |
204 // If there is no longer a WebContents, the request may have raced with tab | 195 // If there is no longer a WebContents, the request may have raced with tab |
205 // closing. Don't fire the external request. (It may have been a prerender.) | 196 // closing. Don't fire the external request. (It may have been a prerender.) |
206 content::WebContents* web_contents = | 197 content::WebContents* web_contents = |
207 tab_util::GetWebContentsByID(render_process_id, render_view_id); | 198 tab_util::GetWebContentsByID(render_process_id, render_view_id); |
208 if (!web_contents) | 199 if (!web_contents) |
209 return; | 200 return; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 | 248 |
258 ChromeResourceDispatcherHostDelegate::ChromeResourceDispatcherHostDelegate( | 249 ChromeResourceDispatcherHostDelegate::ChromeResourceDispatcherHostDelegate( |
259 prerender::PrerenderTracker* prerender_tracker) | 250 prerender::PrerenderTracker* prerender_tracker) |
260 : download_request_limiter_(g_browser_process->download_request_limiter()), | 251 : download_request_limiter_(g_browser_process->download_request_limiter()), |
261 safe_browsing_(g_browser_process->safe_browsing_service()), | 252 safe_browsing_(g_browser_process->safe_browsing_service()), |
262 user_script_listener_(new extensions::UserScriptListener()), | 253 user_script_listener_(new extensions::UserScriptListener()), |
263 prerender_tracker_(prerender_tracker) { | 254 prerender_tracker_(prerender_tracker) { |
264 } | 255 } |
265 | 256 |
266 ChromeResourceDispatcherHostDelegate::~ChromeResourceDispatcherHostDelegate() { | 257 ChromeResourceDispatcherHostDelegate::~ChromeResourceDispatcherHostDelegate() { |
| 258 CHECK(stream_target_info_.empty()); |
267 } | 259 } |
268 | 260 |
269 bool ChromeResourceDispatcherHostDelegate::ShouldBeginRequest( | 261 bool ChromeResourceDispatcherHostDelegate::ShouldBeginRequest( |
270 int child_id, | 262 int child_id, |
271 int route_id, | 263 int route_id, |
272 const std::string& method, | 264 const std::string& method, |
273 const GURL& url, | 265 const GURL& url, |
274 ResourceType::Type resource_type, | 266 ResourceType::Type resource_type, |
275 content::ResourceContext* resource_context) { | 267 content::ResourceContext* resource_context) { |
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 } | 534 } |
543 #endif | 535 #endif |
544 | 536 |
545 bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource( | 537 bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource( |
546 const GURL& url, const std::string& mime_type) { | 538 const GURL& url, const std::string& mime_type) { |
547 // Special-case user scripts to get downloaded instead of viewed. | 539 // Special-case user scripts to get downloaded instead of viewed. |
548 return extensions::UserScript::IsURLUserScript(url, mime_type); | 540 return extensions::UserScript::IsURLUserScript(url, mime_type); |
549 } | 541 } |
550 | 542 |
551 bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( | 543 bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( |
552 content::ResourceContext* resource_context, | 544 net::URLRequest* request, |
553 const GURL& url, | |
554 const std::string& mime_type, | 545 const std::string& mime_type, |
555 GURL* origin, | 546 GURL* origin, |
556 std::string* target_id) { | 547 std::string* payload) { |
557 #if !defined(OS_ANDROID) | 548 #if !defined(OS_ANDROID) |
| 549 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); |
558 ProfileIOData* io_data = | 550 ProfileIOData* io_data = |
559 ProfileIOData::FromResourceContext(resource_context); | 551 ProfileIOData::FromResourceContext(info->GetContext()); |
560 bool profile_is_off_the_record = io_data->IsOffTheRecord(); | 552 bool profile_is_off_the_record = io_data->IsOffTheRecord(); |
561 const scoped_refptr<const extensions::InfoMap> extension_info_map( | 553 const scoped_refptr<const extensions::InfoMap> extension_info_map( |
562 io_data->GetExtensionInfoMap()); | 554 io_data->GetExtensionInfoMap()); |
563 std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist(); | 555 std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist(); |
564 // Go through the white-listed extensions and try to use them to intercept | 556 // Go through the white-listed extensions and try to use them to intercept |
565 // the URL request. | 557 // the URL request. |
566 for (size_t i = 0; i < whitelist.size(); ++i) { | 558 for (size_t i = 0; i < whitelist.size(); ++i) { |
567 const char* extension_id = whitelist[i].c_str(); | 559 const char* extension_id = whitelist[i].c_str(); |
568 const Extension* extension = | 560 const Extension* extension = |
569 extension_info_map->extensions().GetByID(extension_id); | 561 extension_info_map->extensions().GetByID(extension_id); |
570 // The white-listed extension may not be installed, so we have to NULL check | 562 // The white-listed extension may not be installed, so we have to NULL check |
571 // |extension|. | 563 // |extension|. |
572 if (!extension || | 564 if (!extension || |
573 (profile_is_off_the_record && | 565 (profile_is_off_the_record && |
574 !extension_info_map->IsIncognitoEnabled(extension_id))) { | 566 !extension_info_map->IsIncognitoEnabled(extension_id))) { |
575 continue; | 567 continue; |
576 } | 568 } |
577 | 569 |
578 if (ExtensionCanHandleMimeType(extension, mime_type)) { | 570 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); |
| 571 if (handler && handler->CanHandleMIMEType(mime_type)) { |
| 572 StreamTargetInfo target_info; |
579 *origin = Extension::GetBaseURLFromExtensionId(extension_id); | 573 *origin = Extension::GetBaseURLFromExtensionId(extension_id); |
580 *target_id = extension_id; | 574 target_info.extension_id = extension_id; |
| 575 if (!handler->handler_url().empty()) { |
| 576 target_info.view_id = base::GenerateGUID(); |
| 577 *payload = origin->spec() + handler->handler_url() + |
| 578 "?id=" + target_info.view_id; |
| 579 } |
| 580 stream_target_info_[request] = target_info; |
581 return true; | 581 return true; |
582 } | 582 } |
583 } | 583 } |
584 #endif | 584 #endif |
585 return false; | 585 return false; |
586 } | 586 } |
587 | 587 |
588 void ChromeResourceDispatcherHostDelegate::OnStreamCreated( | 588 void ChromeResourceDispatcherHostDelegate::OnStreamCreated( |
589 content::ResourceContext* resource_context, | 589 net::URLRequest* request, |
590 int render_process_id, | 590 scoped_ptr<content::StreamHandle> stream) { |
591 int render_view_id, | |
592 const std::string& target_id, | |
593 scoped_ptr<content::StreamHandle> stream, | |
594 int64 expected_content_size) { | |
595 #if !defined(OS_ANDROID) | 591 #if !defined(OS_ANDROID) |
| 592 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); |
| 593 std::map<net::URLRequest*, StreamTargetInfo>::iterator ix = |
| 594 stream_target_info_.find(request); |
| 595 CHECK(ix != stream_target_info_.end()); |
596 content::BrowserThread::PostTask( | 596 content::BrowserThread::PostTask( |
597 content::BrowserThread::UI, FROM_HERE, | 597 content::BrowserThread::UI, FROM_HERE, |
598 base::Bind(&SendExecuteMimeTypeHandlerEvent, base::Passed(&stream), | 598 base::Bind(&SendExecuteMimeTypeHandlerEvent, base::Passed(&stream), |
599 expected_content_size, render_process_id, render_view_id, | 599 request->GetExpectedContentSize(), |
600 target_id)); | 600 info->GetChildID(), info->GetRouteID(), |
| 601 ix->second.extension_id, ix->second.view_id)); |
| 602 stream_target_info_.erase(request); |
601 #endif | 603 #endif |
602 } | 604 } |
603 | 605 |
604 void ChromeResourceDispatcherHostDelegate::OnResponseStarted( | 606 void ChromeResourceDispatcherHostDelegate::OnResponseStarted( |
605 net::URLRequest* request, | 607 net::URLRequest* request, |
606 content::ResourceContext* resource_context, | 608 content::ResourceContext* resource_context, |
607 content::ResourceResponse* response, | 609 content::ResourceResponse* response, |
608 IPC::Sender* sender) { | 610 IPC::Sender* sender) { |
609 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); | 611 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); |
610 | 612 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 url_request->GetTotalReceivedBytes())); | 711 url_request->GetTotalReceivedBytes())); |
710 } | 712 } |
711 } | 713 } |
712 | 714 |
713 // static | 715 // static |
714 void ChromeResourceDispatcherHostDelegate:: | 716 void ChromeResourceDispatcherHostDelegate:: |
715 SetExternalProtocolHandlerDelegateForTesting( | 717 SetExternalProtocolHandlerDelegateForTesting( |
716 ExternalProtocolHandler::Delegate* delegate) { | 718 ExternalProtocolHandler::Delegate* delegate) { |
717 g_external_protocol_handler_delegate = delegate; | 719 g_external_protocol_handler_delegate = delegate; |
718 } | 720 } |
OLD | NEW |