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.h" |
21 #include "chrome/browser/profiles/profile_manager.h" | 22 #include "chrome/browser/profiles/profile_manager.h" |
22 #include "components/offline_pages/offline_page_model.h" | 23 #include "components/offline_pages/offline_page_model.h" |
23 #include "components/previews/previews_experiments.h" | 24 #include "components/previews/previews_experiments.h" |
24 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/browser/resource_request_info.h" | 26 #include "content/public/browser/resource_request_info.h" |
26 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" |
27 #include "content/public/common/resource_type.h" | 28 #include "content/public/common/resource_type.h" |
28 #include "net/base/network_change_notifier.h" | 29 #include "net/base/network_change_notifier.h" |
29 #include "net/http/http_request_headers.h" | 30 #include "net/http/http_request_headers.h" |
30 #include "net/nqe/network_quality_estimator.h" | 31 #include "net/nqe/network_quality_estimator.h" |
31 #include "net/url_request/url_request.h" | 32 #include "net/url_request/url_request.h" |
32 #include "net/url_request/url_request_context.h" | 33 #include "net/url_request/url_request_context.h" |
33 | 34 |
34 namespace offline_pages { | 35 namespace offline_pages { |
35 | 36 |
36 const char kLoadingOfflinePageHeader[] = "X-Chrome-offline"; | 37 const char kOfflinePageHeader[] = "X-Chrome-offline"; |
37 const char kLoadingOfflinePageReason[] = "reason="; | 38 const char kOfflinePageHeaderReasonKey[] = "reason"; |
38 const char kLoadingOfflinePageDueToNetError[] = "error"; | 39 const char kOfflinePageHeaderReasonValueDueToNetError[] = "error"; |
40 const char kOfflinePageHeaderPersistKey[] = "persist"; | |
41 const char kOfflinePageHeaderNamespaceKey[] = "namespace"; | |
42 const char kOfflinePageHeaderIDKey[] = "id"; | |
39 | 43 |
40 namespace { | 44 namespace { |
41 | 45 |
42 enum class NetworkState { | 46 enum class NetworkState { |
43 // No network connection. | 47 // No network connection. |
44 DISCONNECTED_NETWORK, | 48 DISCONNECTED_NETWORK, |
45 // Prohibitively slow means that the NetworkQualityEstimator reported a | 49 // Prohibitively slow means that the NetworkQualityEstimator reported a |
46 // connection slow enough to warrant showing an offline page if available. | 50 // connection slow enough to warrant showing an offline page if available. |
47 PROHIBITIVELY_SLOW_NETWORK, | 51 PROHIBITIVELY_SLOW_NETWORK, |
48 // Network error received due to bad network, i.e. connected to a hotspot or | 52 // 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 } | 110 } |
107 | 111 |
108 private: | 112 private: |
109 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { | 113 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { |
110 return OfflinePageUtils::GetTabId(web_contents, tab_id); | 114 return OfflinePageUtils::GetTabId(web_contents, tab_id); |
111 } | 115 } |
112 | 116 |
113 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); | 117 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); |
114 }; | 118 }; |
115 | 119 |
116 // Returns true if custom offline header is present. | 120 class OfflinePageHeader { |
Dmitry Titov
2016/09/09 04:33:06
Nice to add a class for that.
Please add a class
jianli
2016/09/10 00:56:03
Done.
| |
117 // |reason| may be set with the reason to trigger the offline page loading. | 121 public: |
118 bool ParseOfflineHeader(net::URLRequest* request, std::string* reason) { | 122 explicit OfflinePageHeader(const std::string& header_string); |
119 std::string value; | 123 ~OfflinePageHeader() {} |
120 if (!request->extra_request_headers().GetHeader(kLoadingOfflinePageHeader, | 124 |
121 &value)) { | 125 bool succeeded_to_parse() const { return succeeded_to_parse_; } |
Dmitry Titov
2016/09/09 04:33:06
Naming suggestion: successfully_parsed_
jianli
2016/09/10 00:56:03
Done.
| |
122 return false; | 126 bool need_to_persist() const { return need_to_persist_; } |
Dmitry Titov
2016/09/09 04:33:06
Shouldn't this always be 'true' ?
Again, if persis
jianli
2016/09/10 00:56:04
I think it should always be false because we shoul
| |
127 const std::string& reason() const { return reason_; } | |
Dmitry Titov
2016/09/09 04:33:06
this looks like enum that this class should expose
jianli
2016/09/10 00:56:03
Done.
| |
128 const std::string& name_space() const { return name_space_; } | |
129 const std::string& id() const { return id_; } | |
130 | |
131 private: | |
132 bool succeeded_to_parse_; | |
133 | |
Dmitry Titov
2016/09/09 04:33:06
extra empty line
jianli
2016/09/10 00:56:03
Done.
| |
134 bool need_to_persist_; | |
135 std::string reason_; | |
136 std::string name_space_; | |
137 std::string id_; | |
138 | |
139 DISALLOW_COPY_AND_ASSIGN(OfflinePageHeader); | |
140 }; | |
141 | |
142 OfflinePageHeader::OfflinePageHeader(const std::string& header_string) | |
143 : succeeded_to_parse_(false), need_to_persist_(false) { | |
144 if (header_string.empty()) { | |
145 succeeded_to_parse_ = true; | |
146 return; | |
123 } | 147 } |
124 | 148 |
125 // Currently we only support reason field. | 149 base::StringTokenizer tokenizer(header_string, ", "); |
126 base::StringTokenizer tokenizer(value, ", "); | |
127 while (tokenizer.GetNext()) { | 150 while (tokenizer.GetNext()) { |
128 if (base::StartsWith(tokenizer.token(), | 151 std::string pair = tokenizer.token(); |
129 kLoadingOfflinePageReason, | 152 std::size_t pos = pair.find('='); |
130 base::CompareCase::INSENSITIVE_ASCII)) { | 153 if (pos == std::string::npos) |
131 *reason = tokenizer.token().substr( | 154 return; |
132 arraysize(kLoadingOfflinePageReason) - 1); | 155 std::string key = pair.substr(0, pos); |
133 break; | 156 std::string value = pair.substr(pos + 1); |
134 } | 157 if (key == kOfflinePageHeaderPersistKey) |
fgorski
2016/09/08 02:25:02
is there a place where you call toLower? Or should
jianli
2016/09/10 00:56:03
Done.
| |
158 need_to_persist_ = (value == "1"); | |
159 else if (key == kOfflinePageHeaderReasonKey) | |
160 reason_ = value; | |
161 else if (key == kOfflinePageHeaderNamespaceKey) | |
162 name_space_ = value; | |
163 else if (key == kOfflinePageHeaderIDKey) | |
164 id_ = value; | |
135 } | 165 } |
136 return true; | 166 |
167 succeeded_to_parse_ = true; | |
Dmitry Titov
2016/09/09 04:33:06
Are there valid combinations and invalid combinati
jianli
2016/09/10 00:56:03
After I remove namespace field, all remaining 3 fi
| |
137 } | 168 } |
138 | 169 |
139 bool IsNetworkProhibitivelySlow(net::URLRequest* request) { | 170 bool IsNetworkProhibitivelySlow(net::URLRequest* request) { |
140 // NetworkQualityEstimator only works when it is enabled. | 171 // NetworkQualityEstimator only works when it is enabled. |
141 if (!previews::IsOfflinePreviewsEnabled()) | 172 if (!previews::IsOfflinePreviewsEnabled()) |
142 return false; | 173 return false; |
143 | 174 |
144 if (!request->context()) | 175 if (!request->context()) |
145 return false; | 176 return false; |
146 | 177 |
147 net::NetworkQualityEstimator* network_quality_estimator = | 178 net::NetworkQualityEstimator* network_quality_estimator = |
148 request->context()->network_quality_estimator(); | 179 request->context()->network_quality_estimator(); |
149 if (!network_quality_estimator) | 180 if (!network_quality_estimator) |
150 return false; | 181 return false; |
151 | 182 |
152 net::EffectiveConnectionType effective_connection_type = | 183 net::EffectiveConnectionType effective_connection_type = |
153 network_quality_estimator->GetEffectiveConnectionType(); | 184 network_quality_estimator->GetEffectiveConnectionType(); |
154 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && | 185 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && |
155 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; | 186 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; |
156 } | 187 } |
157 | 188 |
158 NetworkState GetNetworkState(net::URLRequest* request) { | 189 NetworkState GetNetworkState(net::URLRequest* request) { |
159 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 190 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
160 | 191 |
161 std::string reason; | 192 std::string offline_header_string; |
162 bool has_offline_header = ParseOfflineHeader(request, &reason); | 193 request->extra_request_headers().GetHeader( |
163 if (has_offline_header && | 194 kOfflinePageHeader, &offline_header_string); |
164 base::EqualsCaseInsensitiveASCII(reason, | 195 OfflinePageHeader offline_header(offline_header_string); |
165 kLoadingOfflinePageDueToNetError)) { | 196 if (base::EqualsCaseInsensitiveASCII( |
197 offline_header.reason(), kOfflinePageHeaderReasonValueDueToNetError)) { | |
166 return NetworkState::FLAKY_NETWORK; | 198 return NetworkState::FLAKY_NETWORK; |
167 } | 199 } |
168 | 200 |
169 if (net::NetworkChangeNotifier::IsOffline()) | 201 if (net::NetworkChangeNotifier::IsOffline()) |
170 return NetworkState::DISCONNECTED_NETWORK; | 202 return NetworkState::DISCONNECTED_NETWORK; |
171 | 203 |
172 if (IsNetworkProhibitivelySlow(request)) | 204 if (IsNetworkProhibitivelySlow(request)) |
173 return NetworkState::PROHIBITIVELY_SLOW_NETWORK; | 205 return NetworkState::PROHIBITIVELY_SLOW_NETWORK; |
174 | 206 |
175 // The presence of custom offline header will force to load an offline page | 207 // If custom offline header is present and contains the reason field, the |
176 // even when network is connected. | 208 // offline page should be forced to load even when the network is connected. |
177 return has_offline_header ? NetworkState::FORCE_OFFLINE_ON_CONNECTED_NETWORK | 209 return offline_header.succeeded_to_parse() && !offline_header.reason().empty() |
178 : NetworkState::CONNECTED_NETWORK; | 210 ? NetworkState::FORCE_OFFLINE_ON_CONNECTED_NETWORK |
211 : NetworkState::CONNECTED_NETWORK; | |
179 } | 212 } |
180 | 213 |
181 OfflinePageRequestJob::AggregatedRequestResult | 214 OfflinePageRequestJob::AggregatedRequestResult |
182 RequestResultToAggregatedRequestResult( | 215 RequestResultToAggregatedRequestResult( |
183 RequestResult request_result, NetworkState network_state) { | 216 RequestResult request_result, NetworkState network_state) { |
184 if (request_result == RequestResult::NO_TAB_ID) | 217 if (request_result == RequestResult::NO_TAB_ID) |
185 return OfflinePageRequestJob::AggregatedRequestResult::NO_TAB_ID; | 218 return OfflinePageRequestJob::AggregatedRequestResult::NO_TAB_ID; |
186 | 219 |
187 if (request_result == RequestResult::NO_WEB_CONTENTS) | 220 if (request_result == RequestResult::NO_WEB_CONTENTS) |
188 return OfflinePageRequestJob::AggregatedRequestResult::NO_WEB_CONTENTS; | 221 return OfflinePageRequestJob::AggregatedRequestResult::NO_WEB_CONTENTS; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 return OfflinePageRequestJob::AggregatedRequestResult:: | 267 return OfflinePageRequestJob::AggregatedRequestResult:: |
235 AGGREGATED_REQUEST_RESULT_MAX; | 268 AGGREGATED_REQUEST_RESULT_MAX; |
236 } | 269 } |
237 | 270 |
238 void ReportRequestResult( | 271 void ReportRequestResult( |
239 RequestResult request_result, NetworkState network_state) { | 272 RequestResult request_result, NetworkState network_state) { |
240 OfflinePageRequestJob::ReportAggregatedRequestResult( | 273 OfflinePageRequestJob::ReportAggregatedRequestResult( |
241 RequestResultToAggregatedRequestResult(request_result, network_state)); | 274 RequestResultToAggregatedRequestResult(request_result, network_state)); |
242 } | 275 } |
243 | 276 |
277 OfflinePageModel* GetOfflinePageModel( | |
278 content::ResourceRequestInfo::WebContentsGetter web_contents_getter) { | |
279 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
280 | |
281 content::WebContents* web_contents = web_contents_getter.Run(); | |
282 return web_contents ? | |
283 OfflinePageModelFactory::GetForBrowserContext( | |
284 web_contents->GetBrowserContext()) : | |
285 nullptr; | |
286 } | |
287 | |
244 void NotifyOfflineFilePathOnIO(base::WeakPtr<OfflinePageRequestJob> job, | 288 void NotifyOfflineFilePathOnIO(base::WeakPtr<OfflinePageRequestJob> job, |
245 const base::FilePath& offline_file_path) { | 289 const base::FilePath& offline_file_path) { |
246 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 290 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
247 | 291 |
248 if (!job) | 292 if (!job) |
249 return; | 293 return; |
250 job->OnOfflineFilePathAvailable(offline_file_path); | 294 job->OnOfflineFilePathAvailable(offline_file_path); |
251 } | 295 } |
252 | 296 |
253 // Notifies OfflinePageRequestJob about the offline file path. Note that the | 297 // 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); | 351 OfflinePageTabHelper::FromWebContents(web_contents); |
308 DCHECK(tab_helper); | 352 DCHECK(tab_helper); |
309 tab_helper->SetOfflinePage( | 353 tab_helper->SetOfflinePage( |
310 *offline_page, network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); | 354 *offline_page, network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); |
311 | 355 |
312 *offline_file_path = offline_page->file_path; | 356 *offline_file_path = offline_page->file_path; |
313 return RequestResult::OFFLINE_PAGE_SERVED; | 357 return RequestResult::OFFLINE_PAGE_SERVED; |
314 } | 358 } |
315 | 359 |
316 // Handles the result of finding an offline page. | 360 // Handles the result of finding an offline page. |
317 void SelectPageForOnlineURLDone( | 361 void SucceededToFindOfflinePage( |
318 NetworkState network_state, | 362 NetworkState network_state, |
319 base::WeakPtr<OfflinePageRequestJob> job, | 363 base::WeakPtr<OfflinePageRequestJob> job, |
320 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 364 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
321 const OfflinePageItem* offline_page) { | 365 const OfflinePageItem* offline_page) { |
322 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 366 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
323 | 367 |
324 base::FilePath offline_file_path; | 368 base::FilePath offline_file_path; |
325 RequestResult request_result = AccessOfflineFile( | 369 RequestResult request_result = AccessOfflineFile( |
326 network_state, job, web_contents_getter, offline_page, | 370 network_state, job, web_contents_getter, offline_page, |
327 &offline_file_path); | 371 &offline_file_path); |
328 | 372 |
329 ReportRequestResult(request_result, network_state); | 373 ReportRequestResult(request_result, network_state); |
330 | 374 |
331 // NotifyOfflineFilePathOnUI should always be called regardless the failure | 375 // NotifyOfflineFilePathOnUI should always be called regardless the failure |
332 // result and empty file path such that OfflinePageRequestJob will be notified | 376 // result and empty file path such that OfflinePageRequestJob will be notified |
333 // on failure. | 377 // on failure. |
334 NotifyOfflineFilePathOnUI(job, offline_file_path); | 378 NotifyOfflineFilePathOnUI(job, offline_file_path); |
335 } | 379 } |
336 | 380 |
337 void FailedToSelectOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { | 381 void FailedToFindOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { |
338 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 382 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
339 | 383 |
340 // Proceed with empty file path in order to notify the OfflinePageRequestJob | 384 // Proceed with empty file path in order to notify the OfflinePageRequestJob |
341 // about the failure. | 385 // about the failure. |
342 base::FilePath empty_file_path; | 386 base::FilePath empty_file_path; |
343 NotifyOfflineFilePathOnUI(job, empty_file_path); | 387 NotifyOfflineFilePathOnUI(job, empty_file_path); |
344 } | 388 } |
345 | 389 |
346 // Tries to find the offline page to serve for |online_url|. | 390 // Tries to find the offline page to serve for |online_url|. |
347 void SelectOfflinePage( | 391 void SelectPageForOnlineURL( |
348 const GURL& online_url, | 392 const GURL& online_url, |
349 NetworkState network_state, | 393 NetworkState network_state, |
350 void* profile_id, | |
351 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 394 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
352 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | 395 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
353 base::WeakPtr<OfflinePageRequestJob> job) { | 396 base::WeakPtr<OfflinePageRequestJob> job) { |
354 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 397 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
355 | 398 |
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(); | 399 content::WebContents* web_contents = web_contents_getter.Run(); |
365 if (!web_contents){ | 400 if (!web_contents){ |
366 ReportRequestResult(RequestResult::NO_WEB_CONTENTS, network_state); | 401 ReportRequestResult(RequestResult::NO_WEB_CONTENTS, network_state); |
367 FailedToSelectOfflinePage(job); | 402 FailedToFindOfflinePage(job); |
368 return; | 403 return; |
369 } | 404 } |
370 int tab_id; | 405 int tab_id; |
371 if (!tab_id_getter.Run(web_contents, &tab_id)) { | 406 if (!tab_id_getter.Run(web_contents, &tab_id)) { |
372 ReportRequestResult(RequestResult::NO_TAB_ID, network_state); | 407 ReportRequestResult(RequestResult::NO_TAB_ID, network_state); |
373 FailedToSelectOfflinePage(job); | 408 FailedToFindOfflinePage(job); |
374 return; | 409 return; |
375 } | 410 } |
376 | 411 |
377 OfflinePageUtils::SelectPageForOnlineURL( | 412 OfflinePageUtils::SelectPageForOnlineURL( |
378 profile, | 413 web_contents->GetBrowserContext(), |
379 online_url, | 414 online_url, |
380 tab_id, | 415 tab_id, |
381 base::Bind(&SelectPageForOnlineURLDone, | 416 base::Bind(&SucceededToFindOfflinePage, |
382 network_state, | 417 network_state, |
383 job, | 418 job, |
384 web_contents_getter)); | 419 web_contents_getter)); |
385 } | 420 } |
386 | 421 |
422 void FindPageWithOfflineIDDone( | |
423 const GURL& online_url, | |
fgorski
2016/09/08 02:25:02
nit: since we no longer have the concept of offlin
jianli
2016/09/10 00:56:04
Agreed. But I rather make another patch after land
| |
424 NetworkState network_state, | |
425 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | |
426 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | |
427 base::WeakPtr<OfflinePageRequestJob> job, | |
428 const OfflinePageItem* offline_page) { | |
429 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
430 | |
431 // If the found offline page does not has same online URL as the request URL, | |
fgorski
2016/09/08 02:25:02
nit: does not have the same URL as the online URL
jianli
2016/09/10 00:56:03
Done.
| |
432 // fall back to find the offline page based on the online URL. | |
433 if (offline_page->url != online_url) { | |
434 SelectPageForOnlineURL( | |
435 online_url, network_state, web_contents_getter, tab_id_getter, job); | |
436 return; | |
437 } | |
438 | |
439 SucceededToFindOfflinePage( | |
440 network_state, job, web_contents_getter, offline_page); | |
441 } | |
442 | |
443 // Tries to find an offline page associated with |offline_id|. | |
444 void FindPageWithOfflineID( | |
445 const GURL& online_url, | |
446 int64_t offline_id, | |
447 NetworkState network_state, | |
448 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | |
449 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | |
450 base::WeakPtr<OfflinePageRequestJob> job) { | |
451 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
452 | |
453 OfflinePageModel* offline_page_model = | |
454 GetOfflinePageModel(web_contents_getter); | |
455 if (!offline_page_model) { | |
456 FailedToFindOfflinePage(job); | |
457 return; | |
458 } | |
459 | |
460 offline_page_model->GetPageByOfflineId( | |
461 offline_id, | |
462 base::Bind(&FindPageWithOfflineIDDone, | |
463 online_url, | |
464 network_state, | |
465 web_contents_getter, | |
466 tab_id_getter, | |
467 job)); | |
468 } | |
469 | |
470 void GetOfflineIdsForClientIdDone( | |
471 const GURL& online_url, | |
472 NetworkState network_state, | |
473 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | |
474 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | |
475 base::WeakPtr<OfflinePageRequestJob> job, | |
476 const MultipleOfflineIdResult& offline_ids) { | |
477 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
478 | |
479 if (offline_ids.empty()) { | |
480 FailedToFindOfflinePage(job); | |
481 return; | |
482 } | |
483 | |
484 DCHECK_EQ(1u, offline_ids.size()); | |
485 FindPageWithOfflineID(online_url, | |
486 offline_ids[0], | |
487 network_state, | |
488 web_contents_getter, | |
489 tab_id_getter, | |
490 job); | |
491 } | |
492 | |
493 // Tries to find an offline page associated with |client_id|. | |
494 void FindPageWithClientID( | |
495 const GURL& online_url, | |
496 const ClientId& client_id, | |
497 NetworkState network_state, | |
498 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | |
499 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | |
500 base::WeakPtr<OfflinePageRequestJob> job) { | |
501 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
502 | |
503 OfflinePageModel* offline_page_model = | |
504 GetOfflinePageModel(web_contents_getter); | |
505 if (!offline_page_model) { | |
506 FailedToFindOfflinePage(job); | |
507 return; | |
508 } | |
509 | |
510 offline_page_model->GetOfflineIdsForClientId( | |
511 client_id, | |
512 base::Bind(&GetOfflineIdsForClientIdDone, | |
513 online_url, | |
514 network_state, | |
515 web_contents_getter, | |
516 tab_id_getter, | |
517 job)); | |
518 } | |
519 | |
520 // Tries to find the offline page to serve for |online_url|. | |
521 void SelectPage( | |
522 const GURL& online_url, | |
523 const std::string& offline_header_string, | |
524 NetworkState network_state, | |
525 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | |
526 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | |
527 base::WeakPtr<OfflinePageRequestJob> job) { | |
528 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
529 | |
530 OfflinePageHeader offline_header(offline_header_string); | |
531 | |
532 // If an id, either offline ID or client ID, is present in the offline header, | |
Dmitry Titov
2016/09/09 04:33:06
This logic is too complicated. It's hard to recall
jianli
2016/09/10 00:56:04
Per discussion, we only support passing offline id
| |
533 // try to load that particular version. | |
534 if (!offline_header.id().empty()) { | |
535 // If namespace is not set in offline header, the id given in the offline | |
536 // header should be used as offline ID. | |
537 if (offline_header.name_space().empty()) { | |
538 // if the id string cannot be converted to int64 id, fall through to | |
539 // select page via online URL. | |
540 int64_t offline_id; | |
541 if (base::StringToInt64(offline_header.id(), &offline_id)) { | |
542 FindPageWithOfflineID(online_url, offline_id, network_state, | |
543 web_contents_getter, tab_id_getter, job); | |
544 return; | |
545 } | |
546 } else { | |
547 // Otherwise, try to find the offline page based on the client ID. | |
548 ClientId client_id(offline_header.name_space(), offline_header.id()); | |
549 FindPageWithClientID(online_url, client_id, network_state, | |
550 web_contents_getter, tab_id_getter, job); | |
551 return; | |
552 } | |
553 } | |
554 | |
555 SelectPageForOnlineURL(online_url, network_state, web_contents_getter, | |
556 tab_id_getter, job); | |
557 } | |
558 | |
387 } // namespace | 559 } // namespace |
388 | 560 |
389 // static | 561 // static |
390 void OfflinePageRequestJob::ReportAggregatedRequestResult( | 562 void OfflinePageRequestJob::ReportAggregatedRequestResult( |
391 AggregatedRequestResult result) { | 563 AggregatedRequestResult result) { |
392 UMA_HISTOGRAM_ENUMERATION("OfflinePages.AggregatedRequestResult", | 564 UMA_HISTOGRAM_ENUMERATION("OfflinePages.AggregatedRequestResult", |
393 static_cast<int>(result), | 565 static_cast<int>(result), |
394 static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX)); | 566 static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX)); |
395 } | 567 } |
396 | 568 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 weak_ptr_factory_.GetWeakPtr())); | 629 weak_ptr_factory_.GetWeakPtr())); |
458 } | 630 } |
459 | 631 |
460 void OfflinePageRequestJob::StartAsync() { | 632 void OfflinePageRequestJob::StartAsync() { |
461 NetworkState network_state = GetNetworkState(request()); | 633 NetworkState network_state = GetNetworkState(request()); |
462 if (network_state == NetworkState::CONNECTED_NETWORK) { | 634 if (network_state == NetworkState::CONNECTED_NETWORK) { |
463 FallbackToDefault(); | 635 FallbackToDefault(); |
464 return; | 636 return; |
465 } | 637 } |
466 | 638 |
639 std::string offline_header_string; | |
640 request()->extra_request_headers().GetHeader(kOfflinePageHeader, | |
641 &offline_header_string); | |
467 content::BrowserThread::PostTask( | 642 content::BrowserThread::PostTask( |
468 content::BrowserThread::UI, | 643 content::BrowserThread::UI, |
469 FROM_HERE, | 644 FROM_HERE, |
470 base::Bind(&SelectOfflinePage, | 645 base::Bind(&SelectPage, |
471 request()->url(), | 646 request()->url(), |
647 offline_header_string, | |
472 network_state, | 648 network_state, |
473 profile_id_, | |
474 delegate_->GetWebContentsGetter(request()), | 649 delegate_->GetWebContentsGetter(request()), |
475 delegate_->GetTabIdGetter(), | 650 delegate_->GetTabIdGetter(), |
476 weak_ptr_factory_.GetWeakPtr())); | 651 weak_ptr_factory_.GetWeakPtr())); |
477 } | 652 } |
478 | 653 |
479 void OfflinePageRequestJob::Kill() { | 654 void OfflinePageRequestJob::Kill() { |
480 net::URLRequestJob::Kill(); | 655 net::URLRequestJob::Kill(); |
481 weak_ptr_factory_.InvalidateWeakPtrs(); | 656 weak_ptr_factory_.InvalidateWeakPtrs(); |
482 } | 657 } |
483 | 658 |
(...skipping 19 matching lines...) Expand all Loading... | |
503 file_path_ = offline_file_path; | 678 file_path_ = offline_file_path; |
504 URLRequestFileJob::Start(); | 679 URLRequestFileJob::Start(); |
505 } | 680 } |
506 | 681 |
507 void OfflinePageRequestJob::SetDelegateForTesting( | 682 void OfflinePageRequestJob::SetDelegateForTesting( |
508 std::unique_ptr<Delegate> delegate) { | 683 std::unique_ptr<Delegate> delegate) { |
509 delegate_ = std::move(delegate); | 684 delegate_ = std::move(delegate); |
510 } | 685 } |
511 | 686 |
512 } // namespace offline_pages | 687 } // namespace offline_pages |
OLD | NEW |