OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/android/offline_pages/offline_page_request_job.h" | 5 #include "chrome/browser/android/offline_pages/offline_page_request_job.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/string_tokenizer.h" | 14 #include "base/strings/string_tokenizer.h" |
14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
16 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" | 17 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" |
17 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" | 18 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" |
18 #include "chrome/browser/android/offline_pages/offline_page_utils.h" | 19 #include "chrome/browser/android/offline_pages/offline_page_utils.h" |
19 #include "chrome/browser/browser_process.h" | 20 #include "chrome/browser/browser_process.h" |
20 #include "chrome/browser/profiles/profile.h" | |
21 #include "chrome/browser/profiles/profile_manager.h" | 21 #include "chrome/browser/profiles/profile_manager.h" |
22 #include "components/offline_pages/offline_page_model.h" | 22 #include "components/offline_pages/offline_page_model.h" |
23 #include "components/previews/previews_experiments.h" | 23 #include "components/previews/previews_experiments.h" |
24 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/browser/resource_request_info.h" | 25 #include "content/public/browser/resource_request_info.h" |
26 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
27 #include "content/public/common/resource_type.h" | 27 #include "content/public/common/resource_type.h" |
28 #include "net/base/network_change_notifier.h" | 28 #include "net/base/network_change_notifier.h" |
29 #include "net/http/http_request_headers.h" | 29 #include "net/http/http_request_headers.h" |
30 #include "net/nqe/network_quality_estimator.h" | 30 #include "net/nqe/network_quality_estimator.h" |
31 #include "net/url_request/url_request.h" | 31 #include "net/url_request/url_request.h" |
32 #include "net/url_request/url_request_context.h" | 32 #include "net/url_request/url_request_context.h" |
33 | 33 |
34 namespace offline_pages { | 34 namespace offline_pages { |
35 | 35 |
36 const char kLoadingOfflinePageHeader[] = "X-Chrome-offline"; | 36 const char kOfflinePageHeader[] = "X-Chrome-offline"; |
37 const char kLoadingOfflinePageReason[] = "reason="; | 37 const char kOfflinePageHeaderReasonKey[] = "reason"; |
38 const char kLoadingOfflinePageDueToNetError[] = "error"; | 38 const char kOfflinePageHeaderReasonValueDueToNetError[] = "error"; |
| 39 const char kOfflinePageHeaderReasonValueFromDownload[] = "download"; |
| 40 const char kOfflinePageHeaderPersistKey[] = "persist"; |
| 41 const char kOfflinePageHeaderIDKey[] = "id"; |
39 | 42 |
40 namespace { | 43 namespace { |
41 | 44 |
42 enum class NetworkState { | 45 enum class NetworkState { |
43 // No network connection. | 46 // No network connection. |
44 DISCONNECTED_NETWORK, | 47 DISCONNECTED_NETWORK, |
45 // Prohibitively slow means that the NetworkQualityEstimator reported a | 48 // Prohibitively slow means that the NetworkQualityEstimator reported a |
46 // connection slow enough to warrant showing an offline page if available. | 49 // connection slow enough to warrant showing an offline page if available. |
47 PROHIBITIVELY_SLOW_NETWORK, | 50 PROHIBITIVELY_SLOW_NETWORK, |
48 // Network error received due to bad network, i.e. connected to a hotspot or | 51 // Network error received due to bad network, i.e. connected to a hotspot or |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 } | 109 } |
107 | 110 |
108 private: | 111 private: |
109 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { | 112 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { |
110 return OfflinePageUtils::GetTabId(web_contents, tab_id); | 113 return OfflinePageUtils::GetTabId(web_contents, tab_id); |
111 } | 114 } |
112 | 115 |
113 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); | 116 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); |
114 }; | 117 }; |
115 | 118 |
116 // Returns true if custom offline header is present. | 119 // Used to parse the extra request header string that defines offline page |
117 // |reason| may be set with the reason to trigger the offline page loading. | 120 // loading behaviors. |
118 bool ParseOfflineHeader(net::URLRequest* request, std::string* reason) { | 121 class OfflinePageHeader { |
119 std::string value; | 122 public: |
120 if (!request->extra_request_headers().GetHeader(kLoadingOfflinePageHeader, | 123 enum class Reason { |
121 &value)) { | 124 NET_ERROR, |
122 return false; | 125 DOWNLOAD, |
| 126 UNKNOWN |
| 127 }; |
| 128 |
| 129 explicit OfflinePageHeader(const std::string& header_string); |
| 130 ~OfflinePageHeader() {} |
| 131 |
| 132 bool successfully_parsed() const { return successfully_parsed_; } |
| 133 bool need_to_persist() const { return need_to_persist_; } |
| 134 Reason reason() const { return reason_; } |
| 135 const std::string& id() const { return id_; } |
| 136 |
| 137 private: |
| 138 // True if the header is present and parsed successfully. |
| 139 bool successfully_parsed_; |
| 140 // Flag to indicate if the header should be persisted across session restore. |
| 141 bool need_to_persist_; |
| 142 // Describes the reason to load offline page. |
| 143 Reason reason_; |
| 144 // The offline ID of the page to load. |
| 145 std::string id_; |
| 146 |
| 147 DISALLOW_COPY_AND_ASSIGN(OfflinePageHeader); |
| 148 }; |
| 149 |
| 150 OfflinePageHeader::OfflinePageHeader(const std::string& header_string) |
| 151 : successfully_parsed_(false), |
| 152 need_to_persist_(false), |
| 153 reason_(Reason::UNKNOWN) { |
| 154 // If the offline header is not present, treat it as not parsed successfully. |
| 155 if (header_string.empty()) |
| 156 return; |
| 157 |
| 158 base::StringTokenizer tokenizer(header_string, ", "); |
| 159 while (tokenizer.GetNext()) { |
| 160 std::string pair = tokenizer.token(); |
| 161 std::size_t pos = pair.find('='); |
| 162 if (pos == std::string::npos) |
| 163 return; |
| 164 std::string key = base::ToLowerASCII(pair.substr(0, pos)); |
| 165 std::string value = base::ToLowerASCII(pair.substr(pos + 1)); |
| 166 if (key == kOfflinePageHeaderPersistKey) { |
| 167 need_to_persist_ = (value == "1"); |
| 168 } else if (key == kOfflinePageHeaderReasonKey) { |
| 169 if (value == kOfflinePageHeaderReasonValueDueToNetError) |
| 170 reason_ = Reason::NET_ERROR; |
| 171 else if (value == kOfflinePageHeaderReasonValueFromDownload) |
| 172 reason_ = Reason::DOWNLOAD; |
| 173 else |
| 174 reason_ = Reason::UNKNOWN; |
| 175 } else if (key == kOfflinePageHeaderIDKey) { |
| 176 id_ = value; |
| 177 } |
123 } | 178 } |
124 | 179 |
125 // Currently we only support reason field. | 180 successfully_parsed_ = true; |
126 base::StringTokenizer tokenizer(value, ", "); | |
127 while (tokenizer.GetNext()) { | |
128 if (base::StartsWith(tokenizer.token(), | |
129 kLoadingOfflinePageReason, | |
130 base::CompareCase::INSENSITIVE_ASCII)) { | |
131 *reason = tokenizer.token().substr( | |
132 arraysize(kLoadingOfflinePageReason) - 1); | |
133 break; | |
134 } | |
135 } | |
136 return true; | |
137 } | 181 } |
138 | 182 |
139 bool IsNetworkProhibitivelySlow(net::URLRequest* request) { | 183 bool IsNetworkProhibitivelySlow(net::URLRequest* request) { |
140 // NetworkQualityEstimator only works when it is enabled. | 184 // NetworkQualityEstimator only works when it is enabled. |
141 if (!previews::IsOfflinePreviewsEnabled()) | 185 if (!previews::IsOfflinePreviewsEnabled()) |
142 return false; | 186 return false; |
143 | 187 |
144 if (!request->context()) | 188 if (!request->context()) |
145 return false; | 189 return false; |
146 | 190 |
147 net::NetworkQualityEstimator* network_quality_estimator = | 191 net::NetworkQualityEstimator* network_quality_estimator = |
148 request->context()->network_quality_estimator(); | 192 request->context()->network_quality_estimator(); |
149 if (!network_quality_estimator) | 193 if (!network_quality_estimator) |
150 return false; | 194 return false; |
151 | 195 |
152 net::EffectiveConnectionType effective_connection_type = | 196 net::EffectiveConnectionType effective_connection_type = |
153 network_quality_estimator->GetEffectiveConnectionType(); | 197 network_quality_estimator->GetEffectiveConnectionType(); |
154 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && | 198 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && |
155 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; | 199 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; |
156 } | 200 } |
157 | 201 |
158 NetworkState GetNetworkState(net::URLRequest* request) { | 202 NetworkState GetNetworkState(net::URLRequest* request) { |
159 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 203 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
160 | 204 |
161 std::string reason; | 205 std::string offline_header_string; |
162 bool has_offline_header = ParseOfflineHeader(request, &reason); | 206 request->extra_request_headers().GetHeader( |
163 if (has_offline_header && | 207 kOfflinePageHeader, &offline_header_string); |
164 base::EqualsCaseInsensitiveASCII(reason, | 208 OfflinePageHeader offline_header(offline_header_string); |
165 kLoadingOfflinePageDueToNetError)) { | 209 if (offline_header.reason() == OfflinePageHeader::Reason::NET_ERROR) |
166 return NetworkState::FLAKY_NETWORK; | 210 return NetworkState::FLAKY_NETWORK; |
167 } | |
168 | 211 |
169 if (net::NetworkChangeNotifier::IsOffline()) | 212 if (net::NetworkChangeNotifier::IsOffline()) |
170 return NetworkState::DISCONNECTED_NETWORK; | 213 return NetworkState::DISCONNECTED_NETWORK; |
171 | 214 |
172 if (IsNetworkProhibitivelySlow(request)) | 215 if (IsNetworkProhibitivelySlow(request)) |
173 return NetworkState::PROHIBITIVELY_SLOW_NETWORK; | 216 return NetworkState::PROHIBITIVELY_SLOW_NETWORK; |
174 | 217 |
175 // The presence of custom offline header will force to load an offline page | 218 // If custom offline header is present, the offline page should be forced to |
176 // even when network is connected. | 219 // load even when the network is connected. |
177 return has_offline_header ? NetworkState::FORCE_OFFLINE_ON_CONNECTED_NETWORK | 220 return offline_header.successfully_parsed() |
178 : NetworkState::CONNECTED_NETWORK; | 221 ? NetworkState::FORCE_OFFLINE_ON_CONNECTED_NETWORK |
| 222 : NetworkState::CONNECTED_NETWORK; |
179 } | 223 } |
180 | 224 |
181 OfflinePageRequestJob::AggregatedRequestResult | 225 OfflinePageRequestJob::AggregatedRequestResult |
182 RequestResultToAggregatedRequestResult( | 226 RequestResultToAggregatedRequestResult( |
183 RequestResult request_result, NetworkState network_state) { | 227 RequestResult request_result, NetworkState network_state) { |
184 if (request_result == RequestResult::NO_TAB_ID) | 228 if (request_result == RequestResult::NO_TAB_ID) |
185 return OfflinePageRequestJob::AggregatedRequestResult::NO_TAB_ID; | 229 return OfflinePageRequestJob::AggregatedRequestResult::NO_TAB_ID; |
186 | 230 |
187 if (request_result == RequestResult::NO_WEB_CONTENTS) | 231 if (request_result == RequestResult::NO_WEB_CONTENTS) |
188 return OfflinePageRequestJob::AggregatedRequestResult::NO_WEB_CONTENTS; | 232 return OfflinePageRequestJob::AggregatedRequestResult::NO_WEB_CONTENTS; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 return OfflinePageRequestJob::AggregatedRequestResult:: | 278 return OfflinePageRequestJob::AggregatedRequestResult:: |
235 AGGREGATED_REQUEST_RESULT_MAX; | 279 AGGREGATED_REQUEST_RESULT_MAX; |
236 } | 280 } |
237 | 281 |
238 void ReportRequestResult( | 282 void ReportRequestResult( |
239 RequestResult request_result, NetworkState network_state) { | 283 RequestResult request_result, NetworkState network_state) { |
240 OfflinePageRequestJob::ReportAggregatedRequestResult( | 284 OfflinePageRequestJob::ReportAggregatedRequestResult( |
241 RequestResultToAggregatedRequestResult(request_result, network_state)); | 285 RequestResultToAggregatedRequestResult(request_result, network_state)); |
242 } | 286 } |
243 | 287 |
| 288 OfflinePageModel* GetOfflinePageModel( |
| 289 content::ResourceRequestInfo::WebContentsGetter web_contents_getter) { |
| 290 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 291 |
| 292 content::WebContents* web_contents = web_contents_getter.Run(); |
| 293 return web_contents ? |
| 294 OfflinePageModelFactory::GetForBrowserContext( |
| 295 web_contents->GetBrowserContext()) : |
| 296 nullptr; |
| 297 } |
| 298 |
244 void NotifyOfflineFilePathOnIO(base::WeakPtr<OfflinePageRequestJob> job, | 299 void NotifyOfflineFilePathOnIO(base::WeakPtr<OfflinePageRequestJob> job, |
245 const base::FilePath& offline_file_path) { | 300 const base::FilePath& offline_file_path) { |
246 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 301 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
247 | 302 |
248 if (!job) | 303 if (!job) |
249 return; | 304 return; |
250 job->OnOfflineFilePathAvailable(offline_file_path); | 305 job->OnOfflineFilePathAvailable(offline_file_path); |
251 } | 306 } |
252 | 307 |
253 // Notifies OfflinePageRequestJob about the offline file path. Note that the | 308 // Notifies OfflinePageRequestJob about the offline file path. Note that the |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 OfflinePageTabHelper::FromWebContents(web_contents); | 362 OfflinePageTabHelper::FromWebContents(web_contents); |
308 DCHECK(tab_helper); | 363 DCHECK(tab_helper); |
309 tab_helper->SetOfflinePage( | 364 tab_helper->SetOfflinePage( |
310 *offline_page, network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); | 365 *offline_page, network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); |
311 | 366 |
312 *offline_file_path = offline_page->file_path; | 367 *offline_file_path = offline_page->file_path; |
313 return RequestResult::OFFLINE_PAGE_SERVED; | 368 return RequestResult::OFFLINE_PAGE_SERVED; |
314 } | 369 } |
315 | 370 |
316 // Handles the result of finding an offline page. | 371 // Handles the result of finding an offline page. |
317 void SelectPageForOnlineURLDone( | 372 void SucceededToFindOfflinePage( |
318 NetworkState network_state, | 373 NetworkState network_state, |
319 base::WeakPtr<OfflinePageRequestJob> job, | 374 base::WeakPtr<OfflinePageRequestJob> job, |
320 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 375 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
321 const OfflinePageItem* offline_page) { | 376 const OfflinePageItem* offline_page) { |
322 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 377 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
323 | 378 |
324 base::FilePath offline_file_path; | 379 base::FilePath offline_file_path; |
325 RequestResult request_result = AccessOfflineFile( | 380 RequestResult request_result = AccessOfflineFile( |
326 network_state, job, web_contents_getter, offline_page, | 381 network_state, job, web_contents_getter, offline_page, |
327 &offline_file_path); | 382 &offline_file_path); |
328 | 383 |
329 ReportRequestResult(request_result, network_state); | 384 ReportRequestResult(request_result, network_state); |
330 | 385 |
331 // NotifyOfflineFilePathOnUI should always be called regardless the failure | 386 // NotifyOfflineFilePathOnUI should always be called regardless the failure |
332 // result and empty file path such that OfflinePageRequestJob will be notified | 387 // result and empty file path such that OfflinePageRequestJob will be notified |
333 // on failure. | 388 // on failure. |
334 NotifyOfflineFilePathOnUI(job, offline_file_path); | 389 NotifyOfflineFilePathOnUI(job, offline_file_path); |
335 } | 390 } |
336 | 391 |
337 void FailedToSelectOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { | 392 void FailedToFindOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { |
338 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 393 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
339 | 394 |
340 // Proceed with empty file path in order to notify the OfflinePageRequestJob | 395 // Proceed with empty file path in order to notify the OfflinePageRequestJob |
341 // about the failure. | 396 // about the failure. |
342 base::FilePath empty_file_path; | 397 base::FilePath empty_file_path; |
343 NotifyOfflineFilePathOnUI(job, empty_file_path); | 398 NotifyOfflineFilePathOnUI(job, empty_file_path); |
344 } | 399 } |
345 | 400 |
346 // Tries to find the offline page to serve for |online_url|. | 401 // Tries to find the offline page to serve for |online_url|. |
347 void SelectOfflinePage( | 402 void SelectPageForOnlineURL( |
348 const GURL& online_url, | 403 const GURL& online_url, |
349 NetworkState network_state, | 404 NetworkState network_state, |
350 void* profile_id, | |
351 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 405 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
352 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | 406 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
353 base::WeakPtr<OfflinePageRequestJob> job) { | 407 base::WeakPtr<OfflinePageRequestJob> job) { |
354 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 408 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
355 | 409 |
356 // |profile_id| needs to be checked with ProfileManager::IsValidProfile | |
357 // before using it. | |
358 if (!g_browser_process->profile_manager()->IsValidProfile(profile_id)) { | |
359 FailedToSelectOfflinePage(job); | |
360 return; | |
361 } | |
362 Profile* profile = reinterpret_cast<Profile*>(profile_id); | |
363 | |
364 content::WebContents* web_contents = web_contents_getter.Run(); | 410 content::WebContents* web_contents = web_contents_getter.Run(); |
365 if (!web_contents){ | 411 if (!web_contents){ |
366 ReportRequestResult(RequestResult::NO_WEB_CONTENTS, network_state); | 412 ReportRequestResult(RequestResult::NO_WEB_CONTENTS, network_state); |
367 FailedToSelectOfflinePage(job); | 413 FailedToFindOfflinePage(job); |
368 return; | 414 return; |
369 } | 415 } |
370 int tab_id; | 416 int tab_id; |
371 if (!tab_id_getter.Run(web_contents, &tab_id)) { | 417 if (!tab_id_getter.Run(web_contents, &tab_id)) { |
372 ReportRequestResult(RequestResult::NO_TAB_ID, network_state); | 418 ReportRequestResult(RequestResult::NO_TAB_ID, network_state); |
373 FailedToSelectOfflinePage(job); | 419 FailedToFindOfflinePage(job); |
374 return; | 420 return; |
375 } | 421 } |
376 | 422 |
377 OfflinePageUtils::SelectPageForOnlineURL( | 423 OfflinePageUtils::SelectPageForOnlineURL( |
378 profile, | 424 web_contents->GetBrowserContext(), |
379 online_url, | 425 online_url, |
380 tab_id, | 426 tab_id, |
381 base::Bind(&SelectPageForOnlineURLDone, | 427 base::Bind(&SucceededToFindOfflinePage, |
382 network_state, | 428 network_state, |
383 job, | 429 job, |
384 web_contents_getter)); | 430 web_contents_getter)); |
385 } | 431 } |
386 | 432 |
| 433 void FindPageWithOfflineIDDone( |
| 434 const GURL& online_url, |
| 435 NetworkState network_state, |
| 436 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 437 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
| 438 base::WeakPtr<OfflinePageRequestJob> job, |
| 439 const OfflinePageItem* offline_page) { |
| 440 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 441 |
| 442 // If the found offline page does not has same URL as the request URL, fall |
| 443 // back to find the offline page based on the URL. |
| 444 if (!offline_page || offline_page->url != online_url) { |
| 445 SelectPageForOnlineURL( |
| 446 online_url, network_state, web_contents_getter, tab_id_getter, job); |
| 447 return; |
| 448 } |
| 449 |
| 450 SucceededToFindOfflinePage( |
| 451 network_state, job, web_contents_getter, offline_page); |
| 452 } |
| 453 |
| 454 // Tries to find an offline page associated with |offline_id|. |
| 455 void FindPageWithOfflineID( |
| 456 const GURL& online_url, |
| 457 int64_t offline_id, |
| 458 NetworkState network_state, |
| 459 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 460 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
| 461 base::WeakPtr<OfflinePageRequestJob> job) { |
| 462 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 463 |
| 464 OfflinePageModel* offline_page_model = |
| 465 GetOfflinePageModel(web_contents_getter); |
| 466 if (!offline_page_model) { |
| 467 FailedToFindOfflinePage(job); |
| 468 return; |
| 469 } |
| 470 |
| 471 offline_page_model->GetPageByOfflineId( |
| 472 offline_id, |
| 473 base::Bind(&FindPageWithOfflineIDDone, |
| 474 online_url, |
| 475 network_state, |
| 476 web_contents_getter, |
| 477 tab_id_getter, |
| 478 job)); |
| 479 } |
| 480 |
| 481 // Tries to find the offline page to serve for |online_url|. |
| 482 void SelectPage( |
| 483 const GURL& online_url, |
| 484 const std::string& offline_header_string, |
| 485 NetworkState network_state, |
| 486 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 487 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
| 488 base::WeakPtr<OfflinePageRequestJob> job) { |
| 489 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 490 |
| 491 OfflinePageHeader offline_header(offline_header_string); |
| 492 |
| 493 // If an offline ID is present in the offline header, try to load that |
| 494 // particular version. |
| 495 if (!offline_header.id().empty()) { |
| 496 // if the id string cannot be converted to int64 id, fall through to |
| 497 // select page via online URL. |
| 498 int64_t offline_id; |
| 499 if (base::StringToInt64(offline_header.id(), &offline_id)) { |
| 500 FindPageWithOfflineID(online_url, offline_id, network_state, |
| 501 web_contents_getter, tab_id_getter, job); |
| 502 return; |
| 503 } |
| 504 } |
| 505 |
| 506 SelectPageForOnlineURL(online_url, network_state, web_contents_getter, |
| 507 tab_id_getter, job); |
| 508 } |
| 509 |
387 } // namespace | 510 } // namespace |
388 | 511 |
389 // static | 512 // static |
390 void OfflinePageRequestJob::ReportAggregatedRequestResult( | 513 void OfflinePageRequestJob::ReportAggregatedRequestResult( |
391 AggregatedRequestResult result) { | 514 AggregatedRequestResult result) { |
392 UMA_HISTOGRAM_ENUMERATION("OfflinePages.AggregatedRequestResult", | 515 UMA_HISTOGRAM_ENUMERATION("OfflinePages.AggregatedRequestResult", |
393 static_cast<int>(result), | 516 static_cast<int>(result), |
394 static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX)); | 517 static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX)); |
395 } | 518 } |
396 | 519 |
397 // static | 520 // static |
398 OfflinePageRequestJob* OfflinePageRequestJob::Create( | 521 OfflinePageRequestJob* OfflinePageRequestJob::Create( |
399 void* profile_id, | |
400 net::URLRequest* request, | 522 net::URLRequest* request, |
401 net::NetworkDelegate* network_delegate) { | 523 net::NetworkDelegate* network_delegate) { |
402 const content::ResourceRequestInfo* resource_request_info = | 524 const content::ResourceRequestInfo* resource_request_info = |
403 content::ResourceRequestInfo::ForRequest(request); | 525 content::ResourceRequestInfo::ForRequest(request); |
404 if (!resource_request_info) | 526 if (!resource_request_info) |
405 return nullptr; | 527 return nullptr; |
406 | 528 |
407 // Ignore the requests not for the main resource. | 529 // Ignore the requests not for the main resource. |
408 if (resource_request_info->GetResourceType() != | 530 if (resource_request_info->GetResourceType() != |
409 content::RESOURCE_TYPE_MAIN_FRAME) { | 531 content::RESOURCE_TYPE_MAIN_FRAME) { |
(...skipping 12 matching lines...) Expand all Loading... |
422 OfflinePageRequestInfo::GetFromRequest(request); | 544 OfflinePageRequestInfo::GetFromRequest(request); |
423 if (info) { | 545 if (info) { |
424 // Fall back to default which is set when an offline page cannot be served, | 546 // Fall back to default which is set when an offline page cannot be served, |
425 // either page not found or online version desired. | 547 // either page not found or online version desired. |
426 if (info->use_default()) | 548 if (info->use_default()) |
427 return nullptr; | 549 return nullptr; |
428 } else { | 550 } else { |
429 request->SetUserData(&kUserDataKey, new OfflinePageRequestInfo()); | 551 request->SetUserData(&kUserDataKey, new OfflinePageRequestInfo()); |
430 } | 552 } |
431 | 553 |
432 return new OfflinePageRequestJob(profile_id, request, network_delegate); | 554 return new OfflinePageRequestJob(request, network_delegate); |
433 } | 555 } |
434 | 556 |
435 OfflinePageRequestJob::OfflinePageRequestJob( | 557 OfflinePageRequestJob::OfflinePageRequestJob( |
436 void* profile_id, | |
437 net::URLRequest* request, | 558 net::URLRequest* request, |
438 net::NetworkDelegate* network_delegate) | 559 net::NetworkDelegate* network_delegate) |
439 : net::URLRequestFileJob( | 560 : net::URLRequestFileJob( |
440 request, | 561 request, |
441 network_delegate, | 562 network_delegate, |
442 base::FilePath(), | 563 base::FilePath(), |
443 content::BrowserThread::GetBlockingPool()-> | 564 content::BrowserThread::GetBlockingPool()-> |
444 GetTaskRunnerWithShutdownBehavior( | 565 GetTaskRunnerWithShutdownBehavior( |
445 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 566 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
446 profile_id_(profile_id), | |
447 delegate_(new DefaultDelegate()), | 567 delegate_(new DefaultDelegate()), |
448 weak_ptr_factory_(this) { | 568 weak_ptr_factory_(this) { |
449 } | 569 } |
450 | 570 |
451 OfflinePageRequestJob::~OfflinePageRequestJob() { | 571 OfflinePageRequestJob::~OfflinePageRequestJob() { |
452 } | 572 } |
453 | 573 |
454 void OfflinePageRequestJob::Start() { | 574 void OfflinePageRequestJob::Start() { |
455 base::ThreadTaskRunnerHandle::Get()->PostTask( | 575 base::ThreadTaskRunnerHandle::Get()->PostTask( |
456 FROM_HERE, base::Bind(&OfflinePageRequestJob::StartAsync, | 576 FROM_HERE, base::Bind(&OfflinePageRequestJob::StartAsync, |
457 weak_ptr_factory_.GetWeakPtr())); | 577 weak_ptr_factory_.GetWeakPtr())); |
458 } | 578 } |
459 | 579 |
460 void OfflinePageRequestJob::StartAsync() { | 580 void OfflinePageRequestJob::StartAsync() { |
461 NetworkState network_state = GetNetworkState(request()); | 581 NetworkState network_state = GetNetworkState(request()); |
462 if (network_state == NetworkState::CONNECTED_NETWORK) { | 582 if (network_state == NetworkState::CONNECTED_NETWORK) { |
463 FallbackToDefault(); | 583 FallbackToDefault(); |
464 return; | 584 return; |
465 } | 585 } |
466 | 586 |
| 587 std::string offline_header_string; |
| 588 request()->extra_request_headers().GetHeader(kOfflinePageHeader, |
| 589 &offline_header_string); |
467 content::BrowserThread::PostTask( | 590 content::BrowserThread::PostTask( |
468 content::BrowserThread::UI, | 591 content::BrowserThread::UI, |
469 FROM_HERE, | 592 FROM_HERE, |
470 base::Bind(&SelectOfflinePage, | 593 base::Bind(&SelectPage, |
471 request()->url(), | 594 request()->url(), |
| 595 offline_header_string, |
472 network_state, | 596 network_state, |
473 profile_id_, | |
474 delegate_->GetWebContentsGetter(request()), | 597 delegate_->GetWebContentsGetter(request()), |
475 delegate_->GetTabIdGetter(), | 598 delegate_->GetTabIdGetter(), |
476 weak_ptr_factory_.GetWeakPtr())); | 599 weak_ptr_factory_.GetWeakPtr())); |
477 } | 600 } |
478 | 601 |
479 void OfflinePageRequestJob::Kill() { | 602 void OfflinePageRequestJob::Kill() { |
480 net::URLRequestJob::Kill(); | 603 net::URLRequestJob::Kill(); |
481 weak_ptr_factory_.InvalidateWeakPtrs(); | 604 weak_ptr_factory_.InvalidateWeakPtrs(); |
482 } | 605 } |
483 | 606 |
(...skipping 19 matching lines...) Expand all Loading... |
503 file_path_ = offline_file_path; | 626 file_path_ = offline_file_path; |
504 URLRequestFileJob::Start(); | 627 URLRequestFileJob::Start(); |
505 } | 628 } |
506 | 629 |
507 void OfflinePageRequestJob::SetDelegateForTesting( | 630 void OfflinePageRequestJob::SetDelegateForTesting( |
508 std::unique_ptr<Delegate> delegate) { | 631 std::unique_ptr<Delegate> delegate) { |
509 delegate_ = std::move(delegate); | 632 delegate_ = std::move(delegate); |
510 } | 633 } |
511 | 634 |
512 } // namespace offline_pages | 635 } // namespace offline_pages |
OLD | NEW |