Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: chrome/browser/android/offline_pages/offline_page_request_job.cc

Issue 2322833002: Support serving offline page by offline ID (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698