Add a minor text member to ui::MenuModel.
[chromium-blink-merge.git] / chrome / browser / renderer_host / chrome_resource_dispatcher_host_delegate.cc
blob266d8e1b9ed2def0d49ea851cea7b0bc2193f9df
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 "base/metrics/histogram.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/content_settings/host_content_settings_map.h"
15 #include "chrome/browser/download/download_request_limiter.h"
16 #include "chrome/browser/download/download_resource_throttle.h"
17 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
18 #include "chrome/browser/extensions/extension_info_map.h"
19 #include "chrome/browser/extensions/user_script_listener.h"
20 #include "chrome/browser/external_protocol/external_protocol_handler.h"
21 #include "chrome/browser/google/google_util.h"
22 #include "chrome/browser/metrics/variations/variations_http_header_provider.h"
23 #include "chrome/browser/net/resource_prefetch_predictor_observer.h"
24 #include "chrome/browser/prerender/prerender_manager.h"
25 #include "chrome/browser/prerender/prerender_tracker.h"
26 #include "chrome/browser/prerender/prerender_util.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_io_data.h"
29 #include "chrome/browser/renderer_host/chrome_url_request_user_data.h"
30 #include "chrome/browser/renderer_host/safe_browsing_resource_throttle_factory.h"
31 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
32 #include "chrome/browser/ui/auto_login_prompter.h"
33 #include "chrome/browser/ui/login/login_prompt.h"
34 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
35 #include "chrome/common/extensions/mime_types_handler.h"
36 #include "chrome/common/render_messages.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/notification_service.h"
39 #include "content/public/browser/render_process_host.h"
40 #include "content/public/browser/render_view_host.h"
41 #include "content/public/browser/resource_context.h"
42 #include "content/public/browser/resource_dispatcher_host.h"
43 #include "content/public/browser/resource_request_info.h"
44 #include "content/public/browser/stream_handle.h"
45 #include "content/public/common/resource_response.h"
46 #include "extensions/common/constants.h"
47 #include "extensions/common/user_script.h"
48 #include "net/base/load_flags.h"
49 #include "net/base/load_timing_info.h"
50 #include "net/http/http_response_headers.h"
51 #include "net/ssl/ssl_config_service.h"
52 #include "net/url_request/url_request.h"
54 #if defined(ENABLE_MANAGED_USERS)
55 #include "chrome/browser/managed_mode/managed_mode_resource_throttle.h"
56 #endif
58 #if defined(USE_SYSTEM_PROTOBUF)
59 #include <google/protobuf/repeated_field.h>
60 #else
61 #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
62 #endif
64 #if defined(OS_ANDROID)
65 #include "chrome/browser/android/intercept_download_resource_throttle.h"
66 #include "components/navigation_interception/intercept_navigation_delegate.h"
67 #endif
69 #if defined(OS_CHROMEOS)
70 #include "chrome/browser/chromeos/login/merge_session_throttle.h"
71 // TODO(oshima): Enable this for other platforms.
72 #include "chrome/browser/renderer_host/offline_resource_throttle.h"
73 #endif
75 using content::BrowserThread;
76 using content::RenderViewHost;
77 using content::ResourceDispatcherHostLoginDelegate;
78 using content::ResourceRequestInfo;
79 using extensions::Extension;
80 using extensions::StreamsPrivateAPI;
82 #if defined(OS_ANDROID)
83 using navigation_interception::InterceptNavigationDelegate;
84 #endif
86 namespace {
88 void NotifyDownloadInitiatedOnUI(int render_process_id, int render_view_id) {
89 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
90 render_view_id);
91 if (!rvh)
92 return;
94 content::NotificationService::current()->Notify(
95 chrome::NOTIFICATION_DOWNLOAD_INITIATED,
96 content::Source<RenderViewHost>(rvh),
97 content::NotificationService::NoDetails());
100 // Goes through the extension's file browser handlers and checks if there is one
101 // that can handle the |mime_type|.
102 // |extension| must not be NULL.
103 bool ExtensionCanHandleMimeType(const Extension* extension,
104 const std::string& mime_type) {
105 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
106 if (!handler)
107 return false;
109 return handler->CanHandleMIMEType(mime_type);
112 void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamHandle> stream,
113 int64 expected_content_size,
114 int render_process_id,
115 int render_view_id,
116 const std::string& extension_id) {
117 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
119 content::RenderViewHost* render_view_host =
120 content::RenderViewHost::FromID(render_process_id, render_view_id);
121 if (!render_view_host)
122 return;
124 content::WebContents* web_contents =
125 content::WebContents::FromRenderViewHost(render_view_host);
126 if (!web_contents)
127 return;
129 content::BrowserContext* browser_context = web_contents->GetBrowserContext();
130 if (!browser_context)
131 return;
133 Profile* profile = Profile::FromBrowserContext(browser_context);
134 if (!profile)
135 return;
137 StreamsPrivateAPI* streams_private = StreamsPrivateAPI::Get(profile);
138 if (!streams_private)
139 return;
140 streams_private->ExecuteMimeTypeHandler(
141 extension_id, web_contents, stream.Pass(), expected_content_size);
144 enum PrerenderSchemeCancelReason {
145 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL,
146 PRERENDER_SCHEME_CANCEL_REASON_DATA,
147 PRERENDER_SCHEME_CANCEL_REASON_BLOB,
148 PRERENDER_SCHEME_CANCEL_REASON_FILE,
149 PRERENDER_SCHEME_CANCEL_REASON_FILESYSTEM,
150 PRERENDER_SCHEME_CANCEL_REASON_WEBSOCKET,
151 PRERENDER_SCHEME_CANCEL_REASON_FTP,
152 PRERENDER_SCHEME_CANCEL_REASON_CHROME,
153 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION,
154 PRERENDER_SCHEME_CANCEL_REASON_ABOUT,
155 PRERENDER_SCHEME_CANCEL_REASON_UNKNOWN,
156 PRERENDER_SCHEME_CANCEL_REASON_MAX,
159 void ReportPrerenderSchemeCancelReason(PrerenderSchemeCancelReason reason) {
160 UMA_HISTOGRAM_ENUMERATION(
161 "Prerender.SchemeCancelReason", reason,
162 PRERENDER_SCHEME_CANCEL_REASON_MAX);
165 void ReportUnsupportedPrerenderScheme(const GURL& url) {
166 if (url.SchemeIs("data")) {
167 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_DATA);
168 } else if (url.SchemeIs("blob")) {
169 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_BLOB);
170 } else if (url.SchemeIsFile()) {
171 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_FILE);
172 } else if (url.SchemeIsFileSystem()) {
173 ReportPrerenderSchemeCancelReason(
174 PRERENDER_SCHEME_CANCEL_REASON_FILESYSTEM);
175 } else if (url.SchemeIs("ws") || url.SchemeIs("wss")) {
176 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_WEBSOCKET);
177 } else if (url.SchemeIs("ftp")) {
178 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_FTP);
179 } else if (url.SchemeIs("chrome")) {
180 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_CHROME);
181 } else if (url.SchemeIs("chrome-extension")) {
182 ReportPrerenderSchemeCancelReason(
183 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION);
184 } else if (url.SchemeIs("about")) {
185 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_ABOUT);
186 } else {
187 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_UNKNOWN);
191 } // end namespace
193 ChromeResourceDispatcherHostDelegate::ChromeResourceDispatcherHostDelegate(
194 prerender::PrerenderTracker* prerender_tracker)
195 : download_request_limiter_(g_browser_process->download_request_limiter()),
196 safe_browsing_(g_browser_process->safe_browsing_service()),
197 user_script_listener_(new extensions::UserScriptListener()),
198 prerender_tracker_(prerender_tracker) {
201 ChromeResourceDispatcherHostDelegate::~ChromeResourceDispatcherHostDelegate() {
204 bool ChromeResourceDispatcherHostDelegate::ShouldBeginRequest(
205 int child_id,
206 int route_id,
207 const std::string& method,
208 const GURL& url,
209 ResourceType::Type resource_type,
210 content::ResourceContext* resource_context) {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
213 // Handle a PREFETCH resource type. If prefetch is disabled, squelch the
214 // request. Otherwise, do a normal request to warm the cache.
215 if (resource_type == ResourceType::PREFETCH) {
216 // All PREFETCH requests should be GETs, but be defensive about it.
217 if (method != "GET")
218 return false;
220 // If prefetch is disabled, kill the request.
221 if (!prerender::PrerenderManager::IsPrefetchEnabled())
222 return false;
225 // Abort any prerenders that spawn requests that use invalid HTTP methods
226 // or invalid schemes.
227 if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) {
228 if (!prerender::PrerenderManager::IsValidHttpMethod(method)) {
229 prerender_tracker_->TryCancelOnIOThread(
230 child_id, route_id, prerender::FINAL_STATUS_INVALID_HTTP_METHOD);
231 return false;
233 if (!prerender::PrerenderManager::DoesSubresourceURLHaveValidScheme(url)) {
234 ReportUnsupportedPrerenderScheme(url);
235 prerender_tracker_->TryCancelOnIOThread(
236 child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
237 return false;
241 return true;
244 void ChromeResourceDispatcherHostDelegate::RequestBeginning(
245 net::URLRequest* request,
246 content::ResourceContext* resource_context,
247 appcache::AppCacheService* appcache_service,
248 ResourceType::Type resource_type,
249 int child_id,
250 int route_id,
251 bool is_continuation_of_transferred_request,
252 ScopedVector<content::ResourceThrottle>* throttles) {
253 if (is_continuation_of_transferred_request)
254 ChromeURLRequestUserData::Delete(request);
256 ChromeURLRequestUserData* user_data =
257 ChromeURLRequestUserData::Create(request);
258 bool is_prerendering = prerender_tracker_->IsPrerenderingOnIOThread(
259 child_id, route_id);
260 if (is_prerendering) {
261 user_data->set_is_prerender(true);
262 request->SetPriority(net::IDLE);
265 #if defined(OS_ANDROID)
266 if (!is_prerendering && resource_type == ResourceType::MAIN_FRAME) {
267 throttles->push_back(
268 InterceptNavigationDelegate::CreateThrottleFor(request));
270 #endif
271 #if defined(OS_CHROMEOS)
272 if (resource_type == ResourceType::MAIN_FRAME) {
273 // We check offline first, then check safe browsing so that we still can
274 // block unsafe site after we remove offline page.
275 throttles->push_back(new OfflineResourceThrottle(
276 child_id, route_id, request, appcache_service));
277 // Add interstitial page while merge session process (cookie
278 // reconstruction from OAuth2 refresh token in ChromeOS login) is still in
279 // progress while we are attempting to load a google property.
280 throttles->push_back(new MergeSessionThrottle(
281 child_id, route_id, request));
283 #endif
285 // Don't attempt to append headers to requests that have already started.
286 // TODO(stevet): Remove this once the request ordering issues are resolved
287 // in crbug.com/128048.
288 if (!request->is_pending()) {
289 net::HttpRequestHeaders headers;
290 headers.CopyFrom(request->extra_request_headers());
291 ProfileIOData* io_data = ProfileIOData::FromResourceContext(
292 resource_context);
293 bool incognito = io_data->is_incognito();
294 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->
295 AppendHeaders(request->url(),
296 incognito,
297 !incognito && io_data->GetMetricsEnabledStateOnIOThread(),
298 &headers);
299 request->SetExtraRequestHeaders(headers);
302 #if defined(ENABLE_ONE_CLICK_SIGNIN)
303 AppendChromeSyncGaiaHeader(request, resource_context);
304 #endif
306 AppendStandardResourceThrottles(request,
307 resource_context,
308 child_id,
309 route_id,
310 resource_type,
311 throttles);
313 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
314 if (io_data->resource_prefetch_predictor_observer()) {
315 io_data->resource_prefetch_predictor_observer()->OnRequestStarted(
316 request, resource_type, child_id, route_id);
320 void ChromeResourceDispatcherHostDelegate::DownloadStarting(
321 net::URLRequest* request,
322 content::ResourceContext* resource_context,
323 int child_id,
324 int route_id,
325 int request_id,
326 bool is_content_initiated,
327 bool must_download,
328 ScopedVector<content::ResourceThrottle>* throttles) {
329 BrowserThread::PostTask(
330 BrowserThread::UI, FROM_HERE,
331 base::Bind(&NotifyDownloadInitiatedOnUI, child_id, route_id));
333 // If it's from the web, we don't trust it, so we push the throttle on.
334 if (is_content_initiated) {
335 throttles->push_back(
336 new DownloadResourceThrottle(download_request_limiter_.get(),
337 child_id,
338 route_id,
339 request_id,
340 request->method()));
341 #if defined(OS_ANDROID)
342 throttles->push_back(
343 new chrome::InterceptDownloadResourceThrottle(
344 request, child_id, route_id, request_id));
345 #endif
348 // If this isn't a new request, we've seen this before and added the standard
349 // resource throttles already so no need to add it again.
350 if (!request->is_pending()) {
351 AppendStandardResourceThrottles(request,
352 resource_context,
353 child_id,
354 route_id,
355 ResourceType::MAIN_FRAME,
356 throttles);
360 bool ChromeResourceDispatcherHostDelegate::AcceptSSLClientCertificateRequest(
361 net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info) {
362 if (request->load_flags() & net::LOAD_PREFETCH)
363 return false;
365 ChromeURLRequestUserData* user_data = ChromeURLRequestUserData::Get(request);
366 if (user_data && user_data->is_prerender()) {
367 int child_id, route_id;
368 if (ResourceRequestInfo::ForRequest(request)->GetAssociatedRenderView(
369 &child_id, &route_id)) {
370 if (prerender_tracker_->TryCancel(
371 child_id, route_id,
372 prerender::FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED)) {
373 return false;
378 return true;
381 bool ChromeResourceDispatcherHostDelegate::AcceptAuthRequest(
382 net::URLRequest* request,
383 net::AuthChallengeInfo* auth_info) {
384 ChromeURLRequestUserData* user_data = ChromeURLRequestUserData::Get(request);
385 if (!user_data || !user_data->is_prerender())
386 return true;
388 int child_id, route_id;
389 if (!ResourceRequestInfo::ForRequest(request)->GetAssociatedRenderView(
390 &child_id, &route_id)) {
391 NOTREACHED();
392 return true;
395 if (!prerender_tracker_->TryCancelOnIOThread(
396 child_id, route_id, prerender::FINAL_STATUS_AUTH_NEEDED)) {
397 return true;
400 return false;
403 ResourceDispatcherHostLoginDelegate*
404 ChromeResourceDispatcherHostDelegate::CreateLoginDelegate(
405 net::AuthChallengeInfo* auth_info, net::URLRequest* request) {
406 return CreateLoginPrompt(auth_info, request);
409 bool ChromeResourceDispatcherHostDelegate::HandleExternalProtocol(
410 const GURL& url, int child_id, int route_id) {
411 #if defined(OS_ANDROID)
412 // Android use a resource throttle to handle external as well as internal
413 // protocols.
414 return false;
415 #else
417 if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) {
418 ReportPrerenderSchemeCancelReason(
419 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL);
420 prerender_tracker_->TryCancel(
421 child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
422 return false;
425 RenderViewHost* view = RenderViewHost::FromID(child_id, route_id);
426 if (view && view->GetProcess()->IsGuest())
427 return false;
429 BrowserThread::PostTask(
430 BrowserThread::UI, FROM_HERE,
431 base::Bind(&ExternalProtocolHandler::LaunchUrl, url, child_id, route_id));
432 return true;
433 #endif
436 void ChromeResourceDispatcherHostDelegate::AppendStandardResourceThrottles(
437 net::URLRequest* request,
438 content::ResourceContext* resource_context,
439 int child_id,
440 int route_id,
441 ResourceType::Type resource_type,
442 ScopedVector<content::ResourceThrottle>* throttles) {
443 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
444 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
445 // Insert safe browsing at the front of the list, so it gets to decide on
446 // policies first.
447 if (io_data->safe_browsing_enabled()->GetValue()) {
448 bool is_subresource_request = resource_type != ResourceType::MAIN_FRAME;
449 content::ResourceThrottle* throttle =
450 SafeBrowsingResourceThrottleFactory::Create(request,
451 child_id,
452 route_id,
453 is_subresource_request,
454 safe_browsing_.get());
455 if (throttle)
456 throttles->push_back(throttle);
458 #endif
460 #if defined(ENABLE_MANAGED_USERS)
461 bool is_subresource_request = resource_type != ResourceType::MAIN_FRAME;
462 throttles->push_back(new ManagedModeResourceThrottle(
463 request, child_id, route_id, !is_subresource_request,
464 io_data->managed_mode_url_filter()));
465 #endif
467 content::ResourceThrottle* throttle =
468 user_script_listener_->CreateResourceThrottle(request->url(),
469 resource_type);
470 if (throttle)
471 throttles->push_back(throttle);
474 #if defined(ENABLE_ONE_CLICK_SIGNIN)
475 void ChromeResourceDispatcherHostDelegate::AppendChromeSyncGaiaHeader(
476 net::URLRequest* request,
477 content::ResourceContext* resource_context) {
478 static const char kAllowChromeSignIn[] = "Allow-Chrome-SignIn";
480 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
481 OneClickSigninHelper::Offer offer =
482 OneClickSigninHelper::CanOfferOnIOThread(request, io_data);
483 switch (offer) {
484 case OneClickSigninHelper::CAN_OFFER:
485 request->SetExtraRequestHeaderByName(kAllowChromeSignIn, "1", false);
486 break;
487 case OneClickSigninHelper::DONT_OFFER:
488 request->RemoveRequestHeaderByName(kAllowChromeSignIn);
489 break;
490 case OneClickSigninHelper::IGNORE_REQUEST:
491 break;
494 #endif
496 bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource(
497 const GURL& url, const std::string& mime_type) {
498 // Special-case user scripts to get downloaded instead of viewed.
499 return extensions::UserScript::IsURLUserScript(url, mime_type);
502 bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
503 content::ResourceContext* resource_context,
504 const GURL& url,
505 const std::string& mime_type,
506 GURL* origin,
507 std::string* target_id) {
508 #if !defined(OS_ANDROID)
509 ProfileIOData* io_data =
510 ProfileIOData::FromResourceContext(resource_context);
511 bool profile_is_incognito = io_data->is_incognito();
512 const scoped_refptr<const ExtensionInfoMap> extension_info_map(
513 io_data->GetExtensionInfoMap());
514 std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
515 // Go through the white-listed extensions and try to use them to intercept
516 // the URL request.
517 for (size_t i = 0; i < whitelist.size(); ++i) {
518 const char* extension_id = whitelist[i].c_str();
519 const Extension* extension =
520 extension_info_map->extensions().GetByID(extension_id);
521 // The white-listed extension may not be installed, so we have to NULL check
522 // |extension|.
523 if (!extension ||
524 (profile_is_incognito &&
525 !extension_info_map->IsIncognitoEnabled(extension_id))) {
526 continue;
529 if (ExtensionCanHandleMimeType(extension, mime_type)) {
530 *origin = Extension::GetBaseURLFromExtensionId(extension_id);
531 *target_id = extension_id;
532 return true;
535 #endif
536 return false;
539 void ChromeResourceDispatcherHostDelegate::OnStreamCreated(
540 content::ResourceContext* resource_context,
541 int render_process_id,
542 int render_view_id,
543 const std::string& target_id,
544 scoped_ptr<content::StreamHandle> stream,
545 int64 expected_content_size) {
546 #if !defined(OS_ANDROID)
547 content::BrowserThread::PostTask(
548 content::BrowserThread::UI, FROM_HERE,
549 base::Bind(&SendExecuteMimeTypeHandlerEvent, base::Passed(&stream),
550 expected_content_size, render_process_id, render_view_id,
551 target_id));
552 #endif
555 void ChromeResourceDispatcherHostDelegate::OnResponseStarted(
556 net::URLRequest* request,
557 content::ResourceContext* resource_context,
558 content::ResourceResponse* response,
559 IPC::Sender* sender) {
560 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
562 if (request->url().SchemeIsSecure()) {
563 const net::URLRequestContext* context = request->context();
564 net::TransportSecurityState* state = context->transport_security_state();
565 if (state) {
566 net::TransportSecurityState::DomainState domain_state;
567 bool has_sni = net::SSLConfigService::IsSNIAvailable(
568 context->ssl_config_service());
569 if (state->GetDomainState(request->url().host(), has_sni,
570 &domain_state) &&
571 domain_state.ShouldUpgradeToSSL()) {
572 sender->Send(new ChromeViewMsg_AddStrictSecurityHost(
573 info->GetRouteID(), request->url().host()));
578 // See if the response contains the X-Auto-Login header. If so, this was
579 // a request for a login page, and the server is allowing the browser to
580 // suggest auto-login, if available.
581 AutoLoginPrompter::ShowInfoBarIfPossible(request, info->GetChildID(),
582 info->GetRouteID());
584 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
586 #if defined(ENABLE_ONE_CLICK_SIGNIN)
587 // See if the response contains the Google-Accounts-SignIn header. If so,
588 // then the user has just finished signing in, and the server is allowing the
589 // browser to suggest connecting the user's profile to the account.
590 OneClickSigninHelper::ShowInfoBarIfPossible(request, io_data,
591 info->GetChildID(),
592 info->GetRouteID());
593 #endif
595 // Build in additional protection for the chrome web store origin.
596 GURL webstore_url(extension_urls::GetWebstoreLaunchURL());
597 if (request->url().DomainIs(webstore_url.host().c_str())) {
598 net::HttpResponseHeaders* response_headers = request->response_headers();
599 if (!response_headers->HasHeaderValue("x-frame-options", "deny") &&
600 !response_headers->HasHeaderValue("x-frame-options", "sameorigin")) {
601 response_headers->RemoveHeader("x-frame-options");
602 response_headers->AddHeader("x-frame-options: sameorigin");
606 if (io_data->resource_prefetch_predictor_observer())
607 io_data->resource_prefetch_predictor_observer()->OnResponseStarted(request);
609 prerender::URLRequestResponseStarted(request);
612 void ChromeResourceDispatcherHostDelegate::OnRequestRedirected(
613 const GURL& redirect_url,
614 net::URLRequest* request,
615 content::ResourceContext* resource_context,
616 content::ResourceResponse* response) {
617 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
619 #if defined(ENABLE_ONE_CLICK_SIGNIN)
620 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
622 // See if the response contains the Google-Accounts-SignIn header. If so,
623 // then the user has just finished signing in, and the server is allowing the
624 // browser to suggest connecting the user's profile to the account.
625 OneClickSigninHelper::ShowInfoBarIfPossible(request, io_data,
626 info->GetChildID(),
627 info->GetRouteID());
628 AppendChromeSyncGaiaHeader(request, resource_context);
629 #endif
631 if (io_data->resource_prefetch_predictor_observer()) {
632 io_data->resource_prefetch_predictor_observer()->OnRequestRedirected(
633 redirect_url, request);
636 int child_id, route_id;
637 if (!prerender::PrerenderManager::DoesURLHaveValidScheme(redirect_url) &&
638 ResourceRequestInfo::ForRequest(request)->GetAssociatedRenderView(
639 &child_id, &route_id) &&
640 prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) {
641 ReportUnsupportedPrerenderScheme(redirect_url);
642 prerender_tracker_->TryCancel(
643 child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
644 request->Cancel();