Home | History | Annotate | Download | only in renderer_host
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
      6 
      7 #include <string>
      8 
      9 #include "base/base64.h"
     10 #include "base/logging.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/component_updater/component_updater_service.h"
     14 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
     15 #include "chrome/browser/content_settings/host_content_settings_map.h"
     16 #include "chrome/browser/download/download_request_limiter.h"
     17 #include "chrome/browser/download/download_resource_throttle.h"
     18 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
     19 #include "chrome/browser/extensions/extension_renderer_state.h"
     20 #include "chrome/browser/extensions/user_script_listener.h"
     21 #include "chrome/browser/external_protocol/external_protocol_handler.h"
     22 #include "chrome/browser/google/google_util.h"
     23 #include "chrome/browser/metrics/variations/variations_http_header_provider.h"
     24 #include "chrome/browser/net/resource_prefetch_predictor_observer.h"
     25 #include "chrome/browser/prefetch/prefetch_field_trial.h"
     26 #include "chrome/browser/prerender/prerender_manager.h"
     27 #include "chrome/browser/prerender/prerender_pending_swap_throttle.h"
     28 #include "chrome/browser/prerender/prerender_resource_throttle.h"
     29 #include "chrome/browser/prerender/prerender_tracker.h"
     30 #include "chrome/browser/prerender/prerender_util.h"
     31 #include "chrome/browser/profiles/profile.h"
     32 #include "chrome/browser/profiles/profile_io_data.h"
     33 #include "chrome/browser/renderer_host/chrome_url_request_user_data.h"
     34 #include "chrome/browser/renderer_host/safe_browsing_resource_throttle_factory.h"
     35 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
     36 #include "chrome/browser/signin/signin_header_helper.h"
     37 #include "chrome/browser/ui/auto_login_prompter.h"
     38 #include "chrome/browser/ui/login/login_prompt.h"
     39 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
     40 #include "chrome/common/extensions/extension_constants.h"
     41 #include "chrome/common/extensions/mime_types_handler.h"
     42 #include "chrome/common/render_messages.h"
     43 #include "content/public/browser/browser_thread.h"
     44 #include "content/public/browser/notification_service.h"
     45 #include "content/public/browser/render_process_host.h"
     46 #include "content/public/browser/render_view_host.h"
     47 #include "content/public/browser/resource_context.h"
     48 #include "content/public/browser/resource_dispatcher_host.h"
     49 #include "content/public/browser/resource_request_info.h"
     50 #include "content/public/browser/stream_handle.h"
     51 #include "content/public/common/resource_response.h"
     52 #include "extensions/browser/info_map.h"
     53 #include "extensions/common/constants.h"
     54 #include "extensions/common/user_script.h"
     55 #include "net/base/load_flags.h"
     56 #include "net/base/load_timing_info.h"
     57 #include "net/base/request_priority.h"
     58 #include "net/http/http_response_headers.h"
     59 #include "net/url_request/url_request.h"
     60 
     61 #if defined(ENABLE_CONFIGURATION_POLICY)
     62 #include "components/policy/core/common/cloud/policy_header_io_helper.h"
     63 #endif
     64 
     65 #if defined(ENABLE_MANAGED_USERS)
     66 #include "chrome/browser/managed_mode/managed_mode_resource_throttle.h"
     67 #endif
     68 
     69 #if defined(USE_SYSTEM_PROTOBUF)
     70 #include <google/protobuf/repeated_field.h>
     71 #else
     72 #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
     73 #endif
     74 
     75 #if defined(OS_ANDROID)
     76 #include "chrome/browser/android/intercept_download_resource_throttle.h"
     77 #include "components/navigation_interception/intercept_navigation_delegate.h"
     78 #else
     79 #include "chrome/browser/apps/app_url_redirector.h"
     80 #endif
     81 
     82 #if defined(OS_CHROMEOS)
     83 #include "chrome/browser/chromeos/login/merge_session_throttle.h"
     84 // TODO(oshima): Enable this for other platforms.
     85 #include "chrome/browser/renderer_host/offline_resource_throttle.h"
     86 #endif
     87 
     88 using content::BrowserThread;
     89 using content::RenderViewHost;
     90 using content::ResourceDispatcherHostLoginDelegate;
     91 using content::ResourceRequestInfo;
     92 using extensions::Extension;
     93 using extensions::StreamsPrivateAPI;
     94 
     95 #if defined(OS_ANDROID)
     96 using navigation_interception::InterceptNavigationDelegate;
     97 #endif
     98 
     99 namespace {
    100 
    101 void NotifyDownloadInitiatedOnUI(int render_process_id, int render_view_id) {
    102   RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
    103                                                render_view_id);
    104   if (!rvh)
    105     return;
    106 
    107   content::NotificationService::current()->Notify(
    108       chrome::NOTIFICATION_DOWNLOAD_INITIATED,
    109       content::Source<RenderViewHost>(rvh),
    110       content::NotificationService::NoDetails());
    111 }
    112 
    113 #if !defined(OS_ANDROID)
    114 // Goes through the extension's file browser handlers and checks if there is one
    115 // that can handle the |mime_type|.
    116 // |extension| must not be NULL.
    117 bool ExtensionCanHandleMimeType(const Extension* extension,
    118                                 const std::string& mime_type) {
    119   MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
    120   if (!handler)
    121     return false;
    122 
    123   return handler->CanHandleMIMEType(mime_type);
    124 }
    125 
    126 void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamHandle> stream,
    127                                      int64 expected_content_size,
    128                                      int render_process_id,
    129                                      int render_view_id,
    130                                      const std::string& extension_id) {
    131   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    132 
    133   content::RenderViewHost* render_view_host =
    134       content::RenderViewHost::FromID(render_process_id, render_view_id);
    135   if (!render_view_host)
    136     return;
    137 
    138   content::WebContents* web_contents =
    139       content::WebContents::FromRenderViewHost(render_view_host);
    140   if (!web_contents)
    141     return;
    142 
    143   content::BrowserContext* browser_context = web_contents->GetBrowserContext();
    144   if (!browser_context)
    145     return;
    146 
    147   Profile* profile = Profile::FromBrowserContext(browser_context);
    148   if (!profile)
    149     return;
    150 
    151   StreamsPrivateAPI* streams_private = StreamsPrivateAPI::Get(profile);
    152   if (!streams_private)
    153     return;
    154   streams_private->ExecuteMimeTypeHandler(
    155       extension_id, web_contents, stream.Pass(), expected_content_size);
    156 }
    157 #endif  // !defined(OS_ANDROID)
    158 
    159 void AppendComponentUpdaterThrottles(
    160     net::URLRequest* request,
    161     content::ResourceContext* resource_context,
    162     ResourceType::Type resource_type,
    163     ScopedVector<content::ResourceThrottle>* throttles) {
    164   const char* crx_id = NULL;
    165   ComponentUpdateService* cus = g_browser_process->component_updater();
    166   if (!cus)
    167     return;
    168   // Check for PNaCl pexe request.
    169   if (resource_type == ResourceType::OBJECT) {
    170     const net::HttpRequestHeaders& headers = request->extra_request_headers();
    171     std::string accept_headers;
    172     if (headers.GetHeader("Accept", &accept_headers)) {
    173       if (accept_headers.find("application/x-pnacl") != std::string::npos &&
    174           pnacl::NeedsOnDemandUpdate())
    175         crx_id = "hnimpnehoodheedghdeeijklkeaacbdc";
    176     }
    177   }
    178 
    179   if (crx_id) {
    180     // We got a component we need to install, so throttle the resource
    181     // until the component is installed.
    182     throttles->push_back(cus->GetOnDemandResourceThrottle(request, crx_id));
    183   }
    184 }
    185 
    186 }  // end namespace
    187 
    188 ChromeResourceDispatcherHostDelegate::ChromeResourceDispatcherHostDelegate(
    189     prerender::PrerenderTracker* prerender_tracker)
    190     : download_request_limiter_(g_browser_process->download_request_limiter()),
    191       safe_browsing_(g_browser_process->safe_browsing_service()),
    192       user_script_listener_(new extensions::UserScriptListener()),
    193       prerender_tracker_(prerender_tracker) {
    194 }
    195 
    196 ChromeResourceDispatcherHostDelegate::~ChromeResourceDispatcherHostDelegate() {
    197 }
    198 
    199 bool ChromeResourceDispatcherHostDelegate::ShouldBeginRequest(
    200     int child_id,
    201     int route_id,
    202     const std::string& method,
    203     const GURL& url,
    204     ResourceType::Type resource_type,
    205     content::ResourceContext* resource_context) {
    206   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    207 
    208   // Handle a PREFETCH resource type. If prefetch is disabled, squelch the
    209   // request.  Otherwise, do a normal request to warm the cache.
    210   if (resource_type == ResourceType::PREFETCH) {
    211     // All PREFETCH requests should be GETs, but be defensive about it.
    212     if (method != "GET")
    213       return false;
    214 
    215     // If prefetch is disabled, kill the request.
    216     if (!prefetch::IsPrefetchEnabled())
    217       return false;
    218   }
    219 
    220   return true;
    221 }
    222 
    223 void ChromeResourceDispatcherHostDelegate::RequestBeginning(
    224     net::URLRequest* request,
    225     content::ResourceContext* resource_context,
    226     appcache::AppCacheService* appcache_service,
    227     ResourceType::Type resource_type,
    228     int child_id,
    229     int route_id,
    230     ScopedVector<content::ResourceThrottle>* throttles) {
    231   ChromeURLRequestUserData* user_data =
    232       ChromeURLRequestUserData::Create(request);
    233   bool is_prerendering = prerender_tracker_->IsPrerenderingOnIOThread(
    234       child_id, route_id);
    235   if (is_prerendering) {
    236     user_data->set_is_prerender(true);
    237     // Requests with the IGNORE_LIMITS flag set (i.e., sync XHRs)
    238     // should remain at MAXIMUM_PRIORITY.
    239     if (request->load_flags() & net::LOAD_IGNORE_LIMITS) {
    240       DCHECK_EQ(request->priority(), net::MAXIMUM_PRIORITY);
    241     } else {
    242       request->SetPriority(net::IDLE);
    243     }
    244   }
    245 
    246   ProfileIOData* io_data = ProfileIOData::FromResourceContext(
    247       resource_context);
    248 
    249   if (!is_prerendering && resource_type == ResourceType::MAIN_FRAME) {
    250 #if defined(OS_ANDROID)
    251     throttles->push_back(
    252         InterceptNavigationDelegate::CreateThrottleFor(request));
    253 #else
    254     // Redirect some navigations to apps that have registered matching URL
    255     // handlers ('url_handlers' in the manifest).
    256     content::ResourceThrottle* url_to_app_throttle =
    257         AppUrlRedirector::MaybeCreateThrottleFor(request, io_data);
    258     if (url_to_app_throttle)
    259       throttles->push_back(url_to_app_throttle);
    260 #endif
    261   }
    262 
    263 #if defined(OS_CHROMEOS)
    264   if (resource_type == ResourceType::MAIN_FRAME) {
    265     // We check offline first, then check safe browsing so that we still can
    266     // block unsafe site after we remove offline page.
    267     throttles->push_back(new OfflineResourceThrottle(request,
    268                                                      appcache_service));
    269     // Add interstitial page while merge session process (cookie
    270     // reconstruction from OAuth2 refresh token in ChromeOS login) is still in
    271     // progress while we are attempting to load a google property.
    272     if (!MergeSessionThrottle::AreAllSessionMergedAlready() &&
    273         request->url().SchemeIsHTTPOrHTTPS()) {
    274       throttles->push_back(new MergeSessionThrottle(request));
    275     }
    276   }
    277 #endif
    278 
    279   // Don't attempt to append headers to requests that have already started.
    280   // TODO(stevet): Remove this once the request ordering issues are resolved
    281   // in crbug.com/128048.
    282   if (!request->is_pending()) {
    283     net::HttpRequestHeaders headers;
    284     headers.CopyFrom(request->extra_request_headers());
    285     bool incognito = io_data->is_incognito();
    286     chrome_variations::VariationsHttpHeaderProvider::GetInstance()->
    287         AppendHeaders(request->url(),
    288                       incognito,
    289                       !incognito && io_data->GetMetricsEnabledStateOnIOThread(),
    290                       &headers);
    291     request->SetExtraRequestHeaders(headers);
    292   }
    293 
    294 #if defined(ENABLE_ONE_CLICK_SIGNIN)
    295   AppendChromeSyncGaiaHeader(request, resource_context);
    296 #endif
    297 
    298 #if defined(ENABLE_CONFIGURATION_POLICY)
    299   if (io_data->policy_header_helper())
    300     io_data->policy_header_helper()->AddPolicyHeaders(request);
    301 #endif
    302 
    303   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    304   signin::AppendMirrorRequestHeaderIfPossible(
    305       request, GURL() /* redirect_url */,
    306       io_data, info->GetChildID(), info->GetRouteID());
    307 
    308   AppendStandardResourceThrottles(request,
    309                                   resource_context,
    310                                   resource_type,
    311                                   throttles);
    312   if (!is_prerendering) {
    313     AppendComponentUpdaterThrottles(request,
    314                                     resource_context,
    315                                     resource_type,
    316                                     throttles);
    317   }
    318 
    319   if (io_data->resource_prefetch_predictor_observer()) {
    320     io_data->resource_prefetch_predictor_observer()->OnRequestStarted(
    321         request, resource_type, child_id, route_id);
    322   }
    323 }
    324 
    325 void ChromeResourceDispatcherHostDelegate::WillTransferRequestToNewProcess(
    326     int old_child_id,
    327     int old_route_id,
    328     int old_request_id,
    329     int new_child_id,
    330     int new_route_id,
    331     int new_request_id) {
    332   // If a prerender, it have should been aborted on cross-process
    333   // navigation in PrerenderContents::WebContentsImpl::OpenURLFromTab.
    334   DCHECK(!prerender_tracker_->IsPrerenderingOnIOThread(old_child_id,
    335                                                        old_route_id));
    336 }
    337 
    338 void ChromeResourceDispatcherHostDelegate::DownloadStarting(
    339     net::URLRequest* request,
    340     content::ResourceContext* resource_context,
    341     int child_id,
    342     int route_id,
    343     int request_id,
    344     bool is_content_initiated,
    345     bool must_download,
    346     ScopedVector<content::ResourceThrottle>* throttles) {
    347   BrowserThread::PostTask(
    348       BrowserThread::UI, FROM_HERE,
    349       base::Bind(&NotifyDownloadInitiatedOnUI, child_id, route_id));
    350 
    351   // If it's from the web, we don't trust it, so we push the throttle on.
    352   if (is_content_initiated) {
    353     throttles->push_back(
    354         new DownloadResourceThrottle(download_request_limiter_.get(),
    355                                      child_id,
    356                                      route_id,
    357                                      request_id,
    358                                      request->method()));
    359 #if defined(OS_ANDROID)
    360     throttles->push_back(
    361         new chrome::InterceptDownloadResourceThrottle(
    362             request, child_id, route_id, request_id));
    363 #endif
    364   }
    365 
    366   // If this isn't a new request, we've seen this before and added the standard
    367   //  resource throttles already so no need to add it again.
    368   if (!request->is_pending()) {
    369     AppendStandardResourceThrottles(request,
    370                                     resource_context,
    371                                     ResourceType::MAIN_FRAME,
    372                                     throttles);
    373   }
    374 }
    375 
    376 bool ChromeResourceDispatcherHostDelegate::AcceptSSLClientCertificateRequest(
    377     net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info) {
    378   if (request->load_flags() & net::LOAD_PREFETCH)
    379     return false;
    380 
    381   ChromeURLRequestUserData* user_data = ChromeURLRequestUserData::Get(request);
    382   if (user_data && user_data->is_prerender()) {
    383     int child_id, route_id;
    384     if (ResourceRequestInfo::ForRequest(request)->GetAssociatedRenderView(
    385             &child_id, &route_id)) {
    386       if (prerender_tracker_->TryCancel(
    387               child_id, route_id,
    388               prerender::FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED)) {
    389         return false;
    390       }
    391     }
    392   }
    393 
    394   return true;
    395 }
    396 
    397 bool ChromeResourceDispatcherHostDelegate::AcceptAuthRequest(
    398     net::URLRequest* request,
    399     net::AuthChallengeInfo* auth_info) {
    400   ChromeURLRequestUserData* user_data = ChromeURLRequestUserData::Get(request);
    401   if (!user_data || !user_data->is_prerender())
    402     return true;
    403 
    404   int child_id, route_id;
    405   if (!ResourceRequestInfo::ForRequest(request)->GetAssociatedRenderView(
    406           &child_id, &route_id)) {
    407     NOTREACHED();
    408     return true;
    409   }
    410 
    411   if (!prerender_tracker_->TryCancelOnIOThread(
    412           child_id, route_id, prerender::FINAL_STATUS_AUTH_NEEDED)) {
    413     return true;
    414   }
    415 
    416   return false;
    417 }
    418 
    419 ResourceDispatcherHostLoginDelegate*
    420     ChromeResourceDispatcherHostDelegate::CreateLoginDelegate(
    421         net::AuthChallengeInfo* auth_info, net::URLRequest* request) {
    422   return CreateLoginPrompt(auth_info, request);
    423 }
    424 
    425 bool ChromeResourceDispatcherHostDelegate::HandleExternalProtocol(
    426     const GURL& url, int child_id, int route_id) {
    427 #if defined(OS_ANDROID)
    428   // Android use a resource throttle to handle external as well as internal
    429   // protocols.
    430   return false;
    431 #else
    432 
    433   if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id) &&
    434       prerender_tracker_->TryCancel(
    435           child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME)) {
    436     prerender::ReportPrerenderExternalURL();
    437     return false;
    438   }
    439 
    440   ExtensionRendererState::WebViewInfo info;
    441   if (ExtensionRendererState::GetInstance()->GetWebViewInfo(child_id,
    442                                                             route_id,
    443                                                             &info)) {
    444     return false;
    445   }
    446 
    447   BrowserThread::PostTask(
    448       BrowserThread::UI, FROM_HERE,
    449       base::Bind(&ExternalProtocolHandler::LaunchUrl, url, child_id, route_id));
    450   return true;
    451 #endif
    452 }
    453 
    454 void ChromeResourceDispatcherHostDelegate::AppendStandardResourceThrottles(
    455     net::URLRequest* request,
    456     content::ResourceContext* resource_context,
    457     ResourceType::Type resource_type,
    458     ScopedVector<content::ResourceThrottle>* throttles) {
    459   ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
    460 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
    461   // Insert safe browsing at the front of the list, so it gets to decide on
    462   // policies first.
    463   if (io_data->safe_browsing_enabled()->GetValue()) {
    464     bool is_subresource_request = resource_type != ResourceType::MAIN_FRAME;
    465     content::ResourceThrottle* throttle =
    466         SafeBrowsingResourceThrottleFactory::Create(request,
    467                                                     is_subresource_request,
    468                                                     safe_browsing_.get());
    469     if (throttle)
    470       throttles->push_back(throttle);
    471   }
    472 #endif
    473 
    474 #if defined(ENABLE_MANAGED_USERS)
    475   bool is_subresource_request = resource_type != ResourceType::MAIN_FRAME;
    476   throttles->push_back(new ManagedModeResourceThrottle(
    477         request, !is_subresource_request,
    478         io_data->managed_mode_url_filter()));
    479 #endif
    480 
    481   content::ResourceThrottle* throttle =
    482       user_script_listener_->CreateResourceThrottle(request->url(),
    483                                                     resource_type);
    484   if (throttle)
    485     throttles->push_back(throttle);
    486 
    487   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    488   if (prerender_tracker_->IsPrerenderingOnIOThread(info->GetChildID(),
    489                                                    info->GetRouteID())) {
    490     throttles->push_back(new prerender::PrerenderResourceThrottle(
    491         request, prerender_tracker_));
    492   }
    493   if (prerender_tracker_->IsPendingSwapRequestOnIOThread(
    494           info->GetChildID(), info->GetRouteID(), request->url())) {
    495     throttles->push_back(new prerender::PrerenderPendingSwapThrottle(
    496         request, prerender_tracker_));
    497   }
    498 }
    499 
    500 #if defined(ENABLE_ONE_CLICK_SIGNIN)
    501 void ChromeResourceDispatcherHostDelegate::AppendChromeSyncGaiaHeader(
    502     net::URLRequest* request,
    503     content::ResourceContext* resource_context) {
    504   static const char kAllowChromeSignIn[] = "Allow-Chrome-SignIn";
    505 
    506   ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
    507   OneClickSigninHelper::Offer offer =
    508       OneClickSigninHelper::CanOfferOnIOThread(request, io_data);
    509   switch (offer) {
    510     case OneClickSigninHelper::CAN_OFFER:
    511       request->SetExtraRequestHeaderByName(kAllowChromeSignIn, "1", false);
    512       break;
    513     case OneClickSigninHelper::DONT_OFFER:
    514       request->RemoveRequestHeaderByName(kAllowChromeSignIn);
    515       break;
    516     case OneClickSigninHelper::IGNORE_REQUEST:
    517       break;
    518   }
    519 }
    520 #endif
    521 
    522 bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource(
    523     const GURL& url, const std::string& mime_type) {
    524   // Special-case user scripts to get downloaded instead of viewed.
    525   return extensions::UserScript::IsURLUserScript(url, mime_type);
    526 }
    527 
    528 bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
    529     content::ResourceContext* resource_context,
    530     const GURL& url,
    531     const std::string& mime_type,
    532     GURL* origin,
    533     std::string* target_id) {
    534 #if !defined(OS_ANDROID)
    535   ProfileIOData* io_data =
    536       ProfileIOData::FromResourceContext(resource_context);
    537   bool profile_is_incognito = io_data->is_incognito();
    538   const scoped_refptr<const extensions::InfoMap> extension_info_map(
    539       io_data->GetExtensionInfoMap());
    540   std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
    541   // Go through the white-listed extensions and try to use them to intercept
    542   // the URL request.
    543   for (size_t i = 0; i < whitelist.size(); ++i) {
    544     const char* extension_id = whitelist[i].c_str();
    545     const Extension* extension =
    546         extension_info_map->extensions().GetByID(extension_id);
    547     // The white-listed extension may not be installed, so we have to NULL check
    548     // |extension|.
    549     if (!extension ||
    550         (profile_is_incognito &&
    551          !extension_info_map->IsIncognitoEnabled(extension_id))) {
    552       continue;
    553     }
    554 
    555     if (ExtensionCanHandleMimeType(extension, mime_type)) {
    556       *origin = Extension::GetBaseURLFromExtensionId(extension_id);
    557       *target_id = extension_id;
    558       return true;
    559     }
    560   }
    561 #endif
    562   return false;
    563 }
    564 
    565 void ChromeResourceDispatcherHostDelegate::OnStreamCreated(
    566     content::ResourceContext* resource_context,
    567     int render_process_id,
    568     int render_view_id,
    569     const std::string& target_id,
    570     scoped_ptr<content::StreamHandle> stream,
    571     int64 expected_content_size) {
    572 #if !defined(OS_ANDROID)
    573   content::BrowserThread::PostTask(
    574       content::BrowserThread::UI, FROM_HERE,
    575       base::Bind(&SendExecuteMimeTypeHandlerEvent, base::Passed(&stream),
    576                  expected_content_size, render_process_id, render_view_id,
    577                  target_id));
    578 #endif
    579 }
    580 
    581 void ChromeResourceDispatcherHostDelegate::OnResponseStarted(
    582     net::URLRequest* request,
    583     content::ResourceContext* resource_context,
    584     content::ResourceResponse* response,
    585     IPC::Sender* sender) {
    586   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    587 
    588   // See if the response contains the X-Auto-Login header.  If so, this was
    589   // a request for a login page, and the server is allowing the browser to
    590   // suggest auto-login, if available.
    591   AutoLoginPrompter::ShowInfoBarIfPossible(request, info->GetChildID(),
    592                                            info->GetRouteID());
    593 
    594   ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
    595 
    596 #if defined(ENABLE_ONE_CLICK_SIGNIN)
    597   // See if the response contains the Google-Accounts-SignIn header.  If so,
    598   // then the user has just finished signing in, and the server is allowing the
    599   // browser to suggest connecting the user's profile to the account.
    600   OneClickSigninHelper::ShowInfoBarIfPossible(request, io_data,
    601                                               info->GetChildID(),
    602                                               info->GetRouteID());
    603 #endif
    604 
    605   // See if the response contains the X-Chrome-Manage-Accounts header. If so
    606   // show the profile avatar bubble so that user can complete signin/out action
    607   // the native UI.
    608   signin::ProcessMirrorResponseHeaderIfExists(request, io_data,
    609                                               info->GetChildID(),
    610                                               info->GetRouteID());
    611 
    612   // Build in additional protection for the chrome web store origin.
    613   GURL webstore_url(extension_urls::GetWebstoreLaunchURL());
    614   if (request->url().DomainIs(webstore_url.host().c_str())) {
    615     net::HttpResponseHeaders* response_headers = request->response_headers();
    616     if (!response_headers->HasHeaderValue("x-frame-options", "deny") &&
    617         !response_headers->HasHeaderValue("x-frame-options", "sameorigin")) {
    618       response_headers->RemoveHeader("x-frame-options");
    619       response_headers->AddHeader("x-frame-options: sameorigin");
    620     }
    621   }
    622 
    623   if (io_data->resource_prefetch_predictor_observer())
    624     io_data->resource_prefetch_predictor_observer()->OnResponseStarted(request);
    625 
    626   prerender::URLRequestResponseStarted(request);
    627 }
    628 
    629 void ChromeResourceDispatcherHostDelegate::OnRequestRedirected(
    630     const GURL& redirect_url,
    631     net::URLRequest* request,
    632     content::ResourceContext* resource_context,
    633     content::ResourceResponse* response) {
    634   ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
    635   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    636 
    637 #if defined(ENABLE_ONE_CLICK_SIGNIN)
    638   // See if the response contains the Google-Accounts-SignIn header.  If so,
    639   // then the user has just finished signing in, and the server is allowing the
    640   // browser to suggest connecting the user's profile to the account.
    641   OneClickSigninHelper::ShowInfoBarIfPossible(request, io_data,
    642                                               info->GetChildID(),
    643                                               info->GetRouteID());
    644   AppendChromeSyncGaiaHeader(request, resource_context);
    645 #endif
    646 
    647   // In the Mirror world, Chrome should append a X-Chrome-Connected header to
    648   // all Gaia requests from a connected profile so Gaia could return a 204
    649   // response and let Chrome handle the action with native UI. The only
    650   // exception is requests from gaia webview, since the native profile
    651   // management UI is built on top of it.
    652   signin::AppendMirrorRequestHeaderIfPossible(request, redirect_url, io_data,
    653       info->GetChildID(), info->GetRouteID());
    654 
    655   if (io_data->resource_prefetch_predictor_observer()) {
    656     io_data->resource_prefetch_predictor_observer()->OnRequestRedirected(
    657         redirect_url, request);
    658   }
    659 }
    660