OLD | NEW |
| (Empty) |
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/offline_resource_throttle.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/singleton.h" | |
12 #include "base/metrics/histogram.h" | |
13 #include "base/strings/string_util.h" | |
14 #include "chrome/browser/chromeos/offline/offline_load_page.h" | |
15 #include "content/public/browser/appcache_service.h" | |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "content/public/browser/render_view_host.h" | |
18 #include "content/public/browser/resource_controller.h" | |
19 #include "content/public/browser/resource_request_info.h" | |
20 #include "content/public/browser/service_worker_context.h" | |
21 #include "content/public/browser/web_contents.h" | |
22 #include "net/base/net_errors.h" | |
23 #include "net/base/net_util.h" | |
24 #include "net/base/network_change_notifier.h" | |
25 #include "net/url_request/url_request.h" | |
26 #include "net/url_request/url_request_context.h" | |
27 #include "url/url_constants.h" | |
28 | |
29 using content::BrowserThread; | |
30 using content::RenderViewHost; | |
31 using content::WebContents; | |
32 | |
33 namespace { | |
34 | |
35 void ShowOfflinePage( | |
36 int render_process_id, | |
37 int render_view_id, | |
38 const GURL& url, | |
39 const chromeos::OfflineLoadPage::CompletionCallback& callback) { | |
40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
41 | |
42 // Check again on UI thread and proceed if it's connected. | |
43 if (!net::NetworkChangeNotifier::IsOffline()) { | |
44 BrowserThread::PostTask( | |
45 BrowserThread::IO, FROM_HERE, base::Bind(callback, true)); | |
46 } else { | |
47 RenderViewHost* render_view_host = | |
48 RenderViewHost::FromID(render_process_id, render_view_id); | |
49 WebContents* web_contents = render_view_host ? | |
50 WebContents::FromRenderViewHost(render_view_host) : NULL; | |
51 // There is a chance that the tab closed after we decided to show | |
52 // the offline page on the IO thread and before we actually show the | |
53 // offline page here on the UI thread. | |
54 if (web_contents) | |
55 (new chromeos::OfflineLoadPage(web_contents, url, callback))->Show(); | |
56 } | |
57 } | |
58 | |
59 } // namespace | |
60 | |
61 OfflineResourceThrottle::OfflineResourceThrottle( | |
62 net::URLRequest* request, | |
63 content::AppCacheService* appcache_service) | |
64 : request_(request), | |
65 appcache_service_(appcache_service), | |
66 pending_callbacks_(0) { | |
67 DCHECK(appcache_service); | |
68 } | |
69 | |
70 OfflineResourceThrottle::~OfflineResourceThrottle() { | |
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
72 | |
73 if (!completion_callback_.IsCancelled()) | |
74 completion_callback_.Cancel(); | |
75 } | |
76 | |
77 void OfflineResourceThrottle::WillStartRequest(bool* defer) { | |
78 if (!ShouldShowOfflinePage(request_->url())) | |
79 return; | |
80 | |
81 DVLOG(1) << "WillStartRequest: this=" << this << ", url=" << request_->url(); | |
82 | |
83 const GURL* url = &(request_->url()); | |
84 const GURL* first_party = &(request_->first_party_for_cookies()); | |
85 | |
86 // Anticipate a client-side HSTS based redirect from HTTP to HTTPS, and | |
87 // ask the appcache about the HTTPS url instead of the HTTP url. | |
88 GURL redirect_url; | |
89 if (request_->GetHSTSRedirect(&redirect_url)) { | |
90 if (url->GetOrigin() == first_party->GetOrigin()) | |
91 first_party = &redirect_url; | |
92 url = &redirect_url; | |
93 } | |
94 | |
95 DCHECK(completion_callback_.IsCancelled()); | |
96 | |
97 completion_callback_.Reset( | |
98 base::Bind(&OfflineResourceThrottle::OnCanHandleOfflineComplete, | |
99 AsWeakPtr())); | |
100 | |
101 pending_callbacks_ = 1; | |
102 appcache_service_->CanHandleMainResourceOffline( | |
103 *url, *first_party, | |
104 completion_callback_.callback()); | |
105 | |
106 content::ServiceWorkerContext* service_worker_context = | |
107 content::ServiceWorkerContext::GetServiceWorkerContext(request_); | |
108 if (service_worker_context) { | |
109 ++pending_callbacks_; | |
110 service_worker_context->CanHandleMainResourceOffline( | |
111 *url, *first_party, | |
112 completion_callback_.callback()); | |
113 } | |
114 *defer = true; | |
115 } | |
116 | |
117 const char* OfflineResourceThrottle::GetNameForLogging() const { | |
118 return "OfflineResourceThrottle"; | |
119 } | |
120 | |
121 void OfflineResourceThrottle::OnBlockingPageComplete(bool proceed) { | |
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
123 | |
124 if (proceed) { | |
125 controller()->Resume(); | |
126 } else { | |
127 controller()->Cancel(); | |
128 } | |
129 } | |
130 | |
131 bool OfflineResourceThrottle::IsRemote(const GURL& url) const { | |
132 return !net::IsLocalhost(url.host()) && (url.SchemeIs(url::kFtpScheme) || | |
133 url.SchemeIs(url::kHttpScheme) || | |
134 url.SchemeIs(url::kHttpsScheme)); | |
135 } | |
136 | |
137 bool OfflineResourceThrottle::ShouldShowOfflinePage(const GURL& url) const { | |
138 // If the network is disconnected while loading other resources, we'll simply | |
139 // show broken link/images. | |
140 return IsRemote(url) && net::NetworkChangeNotifier::IsOffline(); | |
141 } | |
142 | |
143 void OfflineResourceThrottle::OnCanHandleOfflineComplete(int rv) { | |
144 --pending_callbacks_; | |
145 | |
146 if (rv == net::OK) { | |
147 completion_callback_.Cancel(); | |
148 controller()->Resume(); | |
149 } else if (!pending_callbacks_) { | |
150 completion_callback_.Cancel(); | |
151 const content::ResourceRequestInfo* info = | |
152 content::ResourceRequestInfo::ForRequest(request_); | |
153 BrowserThread::PostTask( | |
154 BrowserThread::UI, | |
155 FROM_HERE, | |
156 base::Bind( | |
157 &ShowOfflinePage, | |
158 info->GetChildID(), | |
159 info->GetRouteID(), | |
160 request_->url(), | |
161 base::Bind( | |
162 &OfflineResourceThrottle::OnBlockingPageComplete, | |
163 AsWeakPtr()))); | |
164 } | |
165 } | |
OLD | NEW |