NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / renderer_host / chrome_resource_dispatcher_host_delegate.cc
blob8ef11b61230060f608e7e459c0b7d57f559ea698
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.
5 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
7 #include <string>
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/google/google_util.h"
22 #include "chrome/browser/metrics/variations/variations_http_header_provider.h"
23 #include "chrome/browser/prefetch/prefetch.h"
24 #include "chrome/browser/prerender/prerender_manager.h"
25 #include "chrome/browser/prerender/prerender_manager_factory.h"
26 #include "chrome/browser/prerender/prerender_pending_swap_throttle.h"
27 #include "chrome/browser/prerender/prerender_resource_throttle.h"
28 #include "chrome/browser/prerender/prerender_tracker.h"
29 #include "chrome/browser/prerender/prerender_util.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/profiles/profile_io_data.h"
32 #include "chrome/browser/renderer_host/safe_browsing_resource_throttle_factory.h"
33 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
34 #include "chrome/browser/signin/signin_header_helper.h"
35 #include "chrome/browser/ui/auto_login_prompter.h"
36 #include "chrome/browser/ui/login/login_prompt.h"
37 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
38 #include "chrome/common/extensions/extension_constants.h"
39 #include "chrome/common/extensions/mime_types_handler.h"
40 #include "chrome/common/render_messages.h"
41 #include "chrome/common/url_constants.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/notification_service.h"
44 #include "content/public/browser/render_process_host.h"
45 #include "content/public/browser/render_view_host.h"
46 #include "content/public/browser/resource_context.h"
47 #include "content/public/browser/resource_dispatcher_host.h"
48 #include "content/public/browser/resource_request_info.h"
49 #include "content/public/browser/stream_handle.h"
50 #include "content/public/browser/web_contents.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"
61 #if defined(ENABLE_CONFIGURATION_POLICY)
62 #include "components/policy/core/common/cloud/policy_header_io_helper.h"
63 #endif
65 #if defined(ENABLE_MANAGED_USERS)
66 #include "chrome/browser/managed_mode/managed_mode_resource_throttle.h"
67 #endif
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
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 #include "chrome/browser/apps/ephemeral_app_throttle.h"
81 #endif
83 #if defined(OS_CHROMEOS)
84 #include "chrome/browser/chromeos/login/merge_session_throttle.h"
85 // TODO(oshima): Enable this for other platforms.
86 #include "chrome/browser/renderer_host/offline_resource_throttle.h"
87 #endif
89 using content::BrowserThread;
90 using content::RenderViewHost;
91 using content::ResourceDispatcherHostLoginDelegate;
92 using content::ResourceRequestInfo;
93 using extensions::Extension;
94 using extensions::StreamsPrivateAPI;
96 #if defined(OS_ANDROID)
97 using navigation_interception::InterceptNavigationDelegate;
98 #endif
100 namespace {
102 ExternalProtocolHandler::Delegate* g_external_protocol_handler_delegate = NULL;
104 void NotifyDownloadInitiatedOnUI(int render_process_id, int render_view_id) {
105 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
106 render_view_id);
107 if (!rvh)
108 return;
110 content::NotificationService::current()->Notify(
111 chrome::NOTIFICATION_DOWNLOAD_INITIATED,
112 content::Source<RenderViewHost>(rvh),
113 content::NotificationService::NoDetails());
116 prerender::PrerenderContents* FindPrerenderContents(int render_process_id,
117 int render_view_id) {
118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
119 content::RenderViewHost* rvh =
120 content::RenderViewHost::FromID(render_process_id, render_view_id);
121 if (!rvh)
122 return NULL;
123 content::WebContents* web_contents =
124 content::WebContents::FromRenderViewHost(rvh);
125 if (!web_contents)
126 return NULL;
128 return prerender::PrerenderContents::FromWebContents(web_contents);
131 void UpdatePrerenderNetworkBytesCallback(int render_process_id,
132 int render_view_id,
133 int64 bytes) {
134 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
136 prerender::PrerenderContents* prerender_contents =
137 FindPrerenderContents(render_process_id, render_view_id);
139 if (!prerender_contents)
140 return;
141 prerender_contents->AddNetworkBytes(bytes);
142 prerender_contents->prerender_manager()->AddProfileNetworkBytesIfEnabled(
143 bytes);
146 #if !defined(OS_ANDROID)
147 // Goes through the extension's file browser handlers and checks if there is one
148 // that can handle the |mime_type|.
149 // |extension| must not be NULL.
150 bool ExtensionCanHandleMimeType(const Extension* extension,
151 const std::string& mime_type) {
152 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
153 if (!handler)
154 return false;
156 return handler->CanHandleMIMEType(mime_type);
159 void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamHandle> stream,
160 int64 expected_content_size,
161 int render_process_id,
162 int render_view_id,
163 const std::string& extension_id) {
164 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
166 content::RenderViewHost* render_view_host =
167 content::RenderViewHost::FromID(render_process_id, render_view_id);
168 if (!render_view_host)
169 return;
171 content::WebContents* web_contents =
172 content::WebContents::FromRenderViewHost(render_view_host);
173 if (!web_contents)
174 return;
176 content::BrowserContext* browser_context = web_contents->GetBrowserContext();
177 if (!browser_context)
178 return;
180 Profile* profile = Profile::FromBrowserContext(browser_context);
181 if (!profile)
182 return;
184 StreamsPrivateAPI* streams_private = StreamsPrivateAPI::Get(profile);
185 if (!streams_private)
186 return;
187 streams_private->ExecuteMimeTypeHandler(
188 extension_id, web_contents, stream.Pass(), expected_content_size);
191 void LaunchURL(const GURL& url, int render_process_id, int render_view_id) {
192 // If there is no longer a WebContents, the request may have raced with tab
193 // closing. Don't fire the external request. (It may have been a prerender.)
195 prerender::PrerenderContents* prerender_contents =
196 FindPrerenderContents(render_process_id, render_view_id);
197 if (prerender_contents) {
198 prerender_contents->Destroy(prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
199 prerender::ReportPrerenderExternalURL();
200 return;
203 ExternalProtocolHandler::LaunchUrlWithDelegate(
204 url, render_process_id, render_view_id,
205 g_external_protocol_handler_delegate);
207 #endif // !defined(OS_ANDROID)
209 void AppendComponentUpdaterThrottles(
210 net::URLRequest* request,
211 content::ResourceContext* resource_context,
212 ResourceType::Type resource_type,
213 ScopedVector<content::ResourceThrottle>* throttles) {
214 const char* crx_id = NULL;
215 component_updater::ComponentUpdateService* cus =
216 g_browser_process->component_updater();
217 if (!cus)
218 return;
219 // Check for PNaCl pexe request.
220 if (resource_type == ResourceType::OBJECT) {
221 const net::HttpRequestHeaders& headers = request->extra_request_headers();
222 std::string accept_headers;
223 if (headers.GetHeader("Accept", &accept_headers)) {
224 if (accept_headers.find("application/x-pnacl") != std::string::npos &&
225 pnacl::NeedsOnDemandUpdate())
226 crx_id = "hnimpnehoodheedghdeeijklkeaacbdc";
230 if (crx_id) {
231 // We got a component we need to install, so throttle the resource
232 // until the component is installed.
233 throttles->push_back(cus->GetOnDemandResourceThrottle(request, crx_id));
237 } // end namespace
239 ChromeResourceDispatcherHostDelegate::ChromeResourceDispatcherHostDelegate(
240 prerender::PrerenderTracker* prerender_tracker)
241 : download_request_limiter_(g_browser_process->download_request_limiter()),
242 safe_browsing_(g_browser_process->safe_browsing_service()),
243 user_script_listener_(new extensions::UserScriptListener()),
244 prerender_tracker_(prerender_tracker) {
247 ChromeResourceDispatcherHostDelegate::~ChromeResourceDispatcherHostDelegate() {
250 bool ChromeResourceDispatcherHostDelegate::ShouldBeginRequest(
251 int child_id,
252 int route_id,
253 const std::string& method,
254 const GURL& url,
255 ResourceType::Type resource_type,
256 content::ResourceContext* resource_context) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
259 // Handle a PREFETCH resource type. If prefetch is disabled, squelch the
260 // request. Otherwise, do a normal request to warm the cache.
261 if (resource_type == ResourceType::PREFETCH) {
262 // All PREFETCH requests should be GETs, but be defensive about it.
263 if (method != "GET")
264 return false;
266 // If prefetch is disabled, kill the request.
267 if (!prefetch::IsPrefetchEnabled(resource_context))
268 return false;
271 return true;
274 void ChromeResourceDispatcherHostDelegate::RequestBeginning(
275 net::URLRequest* request,
276 content::ResourceContext* resource_context,
277 appcache::AppCacheService* appcache_service,
278 ResourceType::Type resource_type,
279 int child_id,
280 int route_id,
281 ScopedVector<content::ResourceThrottle>* throttles) {
282 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
283 bool is_prerendering =
284 info->GetVisibilityState() == blink::WebPageVisibilityStatePrerender;
285 if (is_prerendering) {
286 // Requests with the IGNORE_LIMITS flag set (i.e., sync XHRs)
287 // should remain at MAXIMUM_PRIORITY.
288 if (request->load_flags() & net::LOAD_IGNORE_LIMITS) {
289 DCHECK_EQ(request->priority(), net::MAXIMUM_PRIORITY);
290 } else {
291 request->SetPriority(net::IDLE);
295 ProfileIOData* io_data = ProfileIOData::FromResourceContext(
296 resource_context);
298 if (!is_prerendering && resource_type == ResourceType::MAIN_FRAME) {
299 #if defined(OS_ANDROID)
300 throttles->push_back(
301 InterceptNavigationDelegate::CreateThrottleFor(request));
302 #else
303 // Redirect some navigations to apps that have registered matching URL
304 // handlers ('url_handlers' in the manifest).
305 content::ResourceThrottle* url_to_app_throttle =
306 AppUrlRedirector::MaybeCreateThrottleFor(request, io_data);
307 if (url_to_app_throttle)
308 throttles->push_back(url_to_app_throttle);
310 // Experimental: Launch ephemeral apps from search results.
311 content::ResourceThrottle* ephemeral_app_throttle =
312 EphemeralAppThrottle::MaybeCreateThrottleForLaunch(
313 request, io_data);
314 if (ephemeral_app_throttle)
315 throttles->push_back(ephemeral_app_throttle);
316 #endif
319 #if defined(OS_CHROMEOS)
320 // Check if we need to add offline throttle. This should be done only
321 // for main frames.
322 if (resource_type == ResourceType::MAIN_FRAME) {
323 // We check offline first, then check safe browsing so that we still can
324 // block unsafe site after we remove offline page.
325 throttles->push_back(new OfflineResourceThrottle(request,
326 appcache_service));
329 // Check if we need to add merge session throttle. This throttle will postpone
330 // loading of main frames and XHR request.
331 if (resource_type == ResourceType::MAIN_FRAME ||
332 resource_type == ResourceType::XHR) {
333 // Add interstitial page while merge session process (cookie
334 // reconstruction from OAuth2 refresh token in ChromeOS login) is still in
335 // progress while we are attempting to load a google property.
336 if (!MergeSessionThrottle::AreAllSessionMergedAlready() &&
337 request->url().SchemeIsHTTPOrHTTPS()) {
338 throttles->push_back(new MergeSessionThrottle(request, resource_type));
341 #endif
343 // Don't attempt to append headers to requests that have already started.
344 // TODO(stevet): Remove this once the request ordering issues are resolved
345 // in crbug.com/128048.
346 if (!request->is_pending()) {
347 net::HttpRequestHeaders headers;
348 headers.CopyFrom(request->extra_request_headers());
349 bool incognito = io_data->is_incognito();
350 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->
351 AppendHeaders(request->url(),
352 incognito,
353 !incognito && io_data->GetMetricsEnabledStateOnIOThread(),
354 &headers);
355 request->SetExtraRequestHeaders(headers);
358 #if defined(ENABLE_ONE_CLICK_SIGNIN)
359 AppendChromeSyncGaiaHeader(request, resource_context);
360 #endif
362 #if defined(ENABLE_CONFIGURATION_POLICY)
363 if (io_data->policy_header_helper())
364 io_data->policy_header_helper()->AddPolicyHeaders(request);
365 #endif
367 signin::AppendMirrorRequestHeaderIfPossible(
368 request, GURL() /* redirect_url */,
369 io_data, info->GetChildID(), info->GetRouteID());
371 AppendStandardResourceThrottles(request,
372 resource_context,
373 resource_type,
374 throttles);
375 if (!is_prerendering) {
376 AppendComponentUpdaterThrottles(request,
377 resource_context,
378 resource_type,
379 throttles);
383 void ChromeResourceDispatcherHostDelegate::DownloadStarting(
384 net::URLRequest* request,
385 content::ResourceContext* resource_context,
386 int child_id,
387 int route_id,
388 int request_id,
389 bool is_content_initiated,
390 bool must_download,
391 ScopedVector<content::ResourceThrottle>* throttles) {
392 BrowserThread::PostTask(
393 BrowserThread::UI, FROM_HERE,
394 base::Bind(&NotifyDownloadInitiatedOnUI, child_id, route_id));
396 // If it's from the web, we don't trust it, so we push the throttle on.
397 if (is_content_initiated) {
398 throttles->push_back(
399 new DownloadResourceThrottle(download_request_limiter_.get(),
400 child_id,
401 route_id,
402 request_id,
403 request->method()));
404 #if defined(OS_ANDROID)
405 throttles->push_back(
406 new chrome::InterceptDownloadResourceThrottle(
407 request, child_id, route_id, request_id));
408 #endif
411 // If this isn't a new request, we've seen this before and added the standard
412 // resource throttles already so no need to add it again.
413 if (!request->is_pending()) {
414 AppendStandardResourceThrottles(request,
415 resource_context,
416 ResourceType::MAIN_FRAME,
417 throttles);
421 ResourceDispatcherHostLoginDelegate*
422 ChromeResourceDispatcherHostDelegate::CreateLoginDelegate(
423 net::AuthChallengeInfo* auth_info, net::URLRequest* request) {
424 return CreateLoginPrompt(auth_info, request);
427 bool ChromeResourceDispatcherHostDelegate::HandleExternalProtocol(
428 const GURL& url, int child_id, int route_id) {
429 #if defined(OS_ANDROID)
430 // Android use a resource throttle to handle external as well as internal
431 // protocols.
432 return false;
433 #else
435 ExtensionRendererState::WebViewInfo info;
436 if (ExtensionRendererState::GetInstance()->GetWebViewInfo(child_id,
437 route_id,
438 &info)) {
439 return false;
442 BrowserThread::PostTask(
443 BrowserThread::UI, FROM_HERE,
444 base::Bind(&LaunchURL, url, child_id, route_id));
445 return true;
446 #endif
449 void ChromeResourceDispatcherHostDelegate::AppendStandardResourceThrottles(
450 net::URLRequest* request,
451 content::ResourceContext* resource_context,
452 ResourceType::Type resource_type,
453 ScopedVector<content::ResourceThrottle>* throttles) {
454 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
455 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
456 // Insert safe browsing at the front of the list, so it gets to decide on
457 // policies first.
458 if (io_data->safe_browsing_enabled()->GetValue()) {
459 bool is_subresource_request = resource_type != ResourceType::MAIN_FRAME;
460 content::ResourceThrottle* throttle =
461 SafeBrowsingResourceThrottleFactory::Create(request,
462 is_subresource_request,
463 safe_browsing_.get());
464 if (throttle)
465 throttles->push_back(throttle);
467 #endif
469 #if defined(ENABLE_MANAGED_USERS)
470 bool is_subresource_request = resource_type != ResourceType::MAIN_FRAME;
471 throttles->push_back(new ManagedModeResourceThrottle(
472 request, !is_subresource_request,
473 io_data->managed_mode_url_filter()));
474 #endif
476 content::ResourceThrottle* throttle =
477 user_script_listener_->CreateResourceThrottle(request->url(),
478 resource_type);
479 if (throttle)
480 throttles->push_back(throttle);
482 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
483 if (info->GetVisibilityState() == blink::WebPageVisibilityStatePrerender) {
484 throttles->push_back(new prerender::PrerenderResourceThrottle(request));
486 if (prerender_tracker_->IsPendingSwapRequestOnIOThread(
487 info->GetChildID(), info->GetRenderFrameID(), request->url())) {
488 throttles->push_back(new prerender::PrerenderPendingSwapThrottle(
489 request, prerender_tracker_));
493 #if defined(ENABLE_ONE_CLICK_SIGNIN)
494 void ChromeResourceDispatcherHostDelegate::AppendChromeSyncGaiaHeader(
495 net::URLRequest* request,
496 content::ResourceContext* resource_context) {
497 static const char kAllowChromeSignIn[] = "Allow-Chrome-SignIn";
499 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
500 OneClickSigninHelper::Offer offer =
501 OneClickSigninHelper::CanOfferOnIOThread(request, io_data);
502 switch (offer) {
503 case OneClickSigninHelper::CAN_OFFER:
504 request->SetExtraRequestHeaderByName(kAllowChromeSignIn, "1", false);
505 break;
506 case OneClickSigninHelper::DONT_OFFER:
507 request->RemoveRequestHeaderByName(kAllowChromeSignIn);
508 break;
509 case OneClickSigninHelper::IGNORE_REQUEST:
510 break;
513 #endif
515 bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource(
516 const GURL& url, const std::string& mime_type) {
517 // Special-case user scripts to get downloaded instead of viewed.
518 return extensions::UserScript::IsURLUserScript(url, mime_type);
521 bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
522 content::ResourceContext* resource_context,
523 const GURL& url,
524 const std::string& mime_type,
525 GURL* origin,
526 std::string* target_id) {
527 #if !defined(OS_ANDROID)
528 ProfileIOData* io_data =
529 ProfileIOData::FromResourceContext(resource_context);
530 bool profile_is_incognito = io_data->is_incognito();
531 const scoped_refptr<const extensions::InfoMap> extension_info_map(
532 io_data->GetExtensionInfoMap());
533 std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
534 // Go through the white-listed extensions and try to use them to intercept
535 // the URL request.
536 for (size_t i = 0; i < whitelist.size(); ++i) {
537 const char* extension_id = whitelist[i].c_str();
538 const Extension* extension =
539 extension_info_map->extensions().GetByID(extension_id);
540 // The white-listed extension may not be installed, so we have to NULL check
541 // |extension|.
542 if (!extension ||
543 (profile_is_incognito &&
544 !extension_info_map->IsIncognitoEnabled(extension_id))) {
545 continue;
548 if (ExtensionCanHandleMimeType(extension, mime_type)) {
549 *origin = Extension::GetBaseURLFromExtensionId(extension_id);
550 *target_id = extension_id;
551 return true;
554 #endif
555 return false;
558 void ChromeResourceDispatcherHostDelegate::OnStreamCreated(
559 content::ResourceContext* resource_context,
560 int render_process_id,
561 int render_view_id,
562 const std::string& target_id,
563 scoped_ptr<content::StreamHandle> stream,
564 int64 expected_content_size) {
565 #if !defined(OS_ANDROID)
566 content::BrowserThread::PostTask(
567 content::BrowserThread::UI, FROM_HERE,
568 base::Bind(&SendExecuteMimeTypeHandlerEvent, base::Passed(&stream),
569 expected_content_size, render_process_id, render_view_id,
570 target_id));
571 #endif
574 void ChromeResourceDispatcherHostDelegate::OnResponseStarted(
575 net::URLRequest* request,
576 content::ResourceContext* resource_context,
577 content::ResourceResponse* response,
578 IPC::Sender* sender) {
579 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
581 // See if the response contains the X-Auto-Login header. If so, this was
582 // a request for a login page, and the server is allowing the browser to
583 // suggest auto-login, if available.
584 AutoLoginPrompter::ShowInfoBarIfPossible(request, info->GetChildID(),
585 info->GetRouteID());
587 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
589 #if defined(ENABLE_ONE_CLICK_SIGNIN)
590 // See if the response contains the Google-Accounts-SignIn header. If so,
591 // then the user has just finished signing in, and the server is allowing the
592 // browser to suggest connecting the user's profile to the account.
593 OneClickSigninHelper::ShowInfoBarIfPossible(request, io_data,
594 info->GetChildID(),
595 info->GetRouteID());
596 #endif
598 // See if the response contains the X-Chrome-Manage-Accounts header. If so
599 // show the profile avatar bubble so that user can complete signin/out action
600 // the native UI.
601 signin::ProcessMirrorResponseHeaderIfExists(request, io_data,
602 info->GetChildID(),
603 info->GetRouteID());
605 // Build in additional protection for the chrome web store origin.
606 GURL webstore_url(extension_urls::GetWebstoreLaunchURL());
607 if (request->url().DomainIs(webstore_url.host().c_str())) {
608 net::HttpResponseHeaders* response_headers = request->response_headers();
609 if (!response_headers->HasHeaderValue("x-frame-options", "deny") &&
610 !response_headers->HasHeaderValue("x-frame-options", "sameorigin")) {
611 response_headers->RemoveHeader("x-frame-options");
612 response_headers->AddHeader("x-frame-options: sameorigin");
616 // Ignores x-frame-options for the chrome signin UI.
617 if (request->first_party_for_cookies().GetOrigin().spec() ==
618 chrome::kChromeUIChromeSigninURL) {
619 net::HttpResponseHeaders* response_headers = request->response_headers();
620 if (response_headers->HasHeader("x-frame-options"))
621 response_headers->RemoveHeader("x-frame-options");
624 prerender::URLRequestResponseStarted(request);
627 void ChromeResourceDispatcherHostDelegate::OnRequestRedirected(
628 const GURL& redirect_url,
629 net::URLRequest* request,
630 content::ResourceContext* resource_context,
631 content::ResourceResponse* response) {
632 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
633 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
635 #if defined(ENABLE_ONE_CLICK_SIGNIN)
636 // See if the response contains the Google-Accounts-SignIn header. If so,
637 // then the user has just finished signing in, and the server is allowing the
638 // browser to suggest connecting the user's profile to the account.
639 OneClickSigninHelper::ShowInfoBarIfPossible(request, io_data,
640 info->GetChildID(),
641 info->GetRouteID());
642 AppendChromeSyncGaiaHeader(request, resource_context);
643 #endif
645 // In the Mirror world, Chrome should append a X-Chrome-Connected header to
646 // all Gaia requests from a connected profile so Gaia could return a 204
647 // response and let Chrome handle the action with native UI. The only
648 // exception is requests from gaia webview, since the native profile
649 // management UI is built on top of it.
650 signin::AppendMirrorRequestHeaderIfPossible(request, redirect_url, io_data,
651 info->GetChildID(), info->GetRouteID());
654 // Notification that a request has completed.
655 void ChromeResourceDispatcherHostDelegate::RequestComplete(
656 net::URLRequest* url_request) {
657 // Jump on the UI thread and inform the prerender about the bytes.
658 const ResourceRequestInfo* info =
659 ResourceRequestInfo::ForRequest(url_request);
660 if (url_request && !url_request->was_cached()) {
661 BrowserThread::PostTask(BrowserThread::UI,
662 FROM_HERE,
663 base::Bind(&UpdatePrerenderNetworkBytesCallback,
664 info->GetChildID(),
665 info->GetRouteID(),
666 url_request->GetTotalReceivedBytes()));
670 // static
671 void ChromeResourceDispatcherHostDelegate::
672 SetExternalProtocolHandlerDelegateForTesting(
673 ExternalProtocolHandler::Delegate* delegate) {
674 g_external_protocol_handler_delegate = delegate;