| 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_number_conversions.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" | 15 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" |
| 16 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" | 16 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" |
| 17 #include "chrome/browser/android/offline_pages/offline_page_utils.h" | 17 #include "chrome/browser/android/offline_pages/offline_page_utils.h" |
| 18 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/browser/profiles/profile_manager.h" | 19 #include "chrome/browser/profiles/profile_manager.h" |
| 20 #include "components/offline_pages/offline_page_model.h" | 20 #include "components/offline_pages/offline_page_model.h" |
| 21 #include "components/offline_pages/request_header/offline_page_header.h" | 21 #include "components/offline_pages/request_header/offline_page_header.h" |
| 22 #include "components/previews/core/previews_experiments.h" | 22 #include "components/previews/core/previews_decider.h" |
| 23 #include "components/previews/core/previews_opt_out_store.h" |
| 23 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/resource_request_info.h" | 25 #include "content/public/browser/resource_request_info.h" |
| 25 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
| 26 #include "content/public/common/resource_type.h" | 27 #include "content/public/common/resource_type.h" |
| 27 #include "net/base/network_change_notifier.h" | 28 #include "net/base/network_change_notifier.h" |
| 28 #include "net/http/http_request_headers.h" | 29 #include "net/http/http_request_headers.h" |
| 29 #include "net/nqe/network_quality_estimator.h" | |
| 30 #include "net/url_request/url_request.h" | 30 #include "net/url_request/url_request.h" |
| 31 #include "net/url_request/url_request_context.h" | |
| 32 | 31 |
| 33 namespace offline_pages { | 32 namespace offline_pages { |
| 34 | 33 |
| 35 namespace { | 34 namespace { |
| 36 | 35 |
| 37 enum class NetworkState { | 36 enum class NetworkState { |
| 38 // No network connection. | 37 // No network connection. |
| 39 DISCONNECTED_NETWORK, | 38 DISCONNECTED_NETWORK, |
| 40 // Prohibitively slow means that the NetworkQualityEstimator reported a | 39 // Prohibitively slow means that the NetworkQualityEstimator reported a |
| 41 // connection slow enough to warrant showing an offline page if available. | 40 // connection slow enough to warrant showing an offline page if available. |
| 41 // This requires offline previews to be enabled and the URL of the request to |
| 42 // be allowed by previews. |
| 42 PROHIBITIVELY_SLOW_NETWORK, | 43 PROHIBITIVELY_SLOW_NETWORK, |
| 43 // Network error received due to bad network, i.e. connected to a hotspot or | 44 // Network error received due to bad network, i.e. connected to a hotspot or |
| 44 // proxy that does not have a working network. | 45 // proxy that does not have a working network. |
| 45 FLAKY_NETWORK, | 46 FLAKY_NETWORK, |
| 46 // Network is in working condition. | 47 // Network is in working condition. |
| 47 CONNECTED_NETWORK, | 48 CONNECTED_NETWORK, |
| 48 // Force to load the offline page if it is available, though network is in | 49 // Force to load the offline page if it is available, though network is in |
| 49 // working condition. | 50 // working condition. |
| 50 FORCE_OFFLINE_ON_CONNECTED_NETWORK | 51 FORCE_OFFLINE_ON_CONNECTED_NETWORK |
| 51 }; | 52 }; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 } | 102 } |
| 102 | 103 |
| 103 private: | 104 private: |
| 104 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { | 105 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { |
| 105 return OfflinePageUtils::GetTabId(web_contents, tab_id); | 106 return OfflinePageUtils::GetTabId(web_contents, tab_id); |
| 106 } | 107 } |
| 107 | 108 |
| 108 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); | 109 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); |
| 109 }; | 110 }; |
| 110 | 111 |
| 111 bool IsNetworkProhibitivelySlow(net::URLRequest* request) { | |
| 112 // NetworkQualityEstimator only works when it is enabled. | |
| 113 if (!previews::IsOfflinePreviewsEnabled()) | |
| 114 return false; | |
| 115 | |
| 116 if (!request->context()) | |
| 117 return false; | |
| 118 | |
| 119 net::NetworkQualityEstimator* network_quality_estimator = | |
| 120 request->context()->network_quality_estimator(); | |
| 121 if (!network_quality_estimator) | |
| 122 return false; | |
| 123 | |
| 124 net::EffectiveConnectionType effective_connection_type = | |
| 125 network_quality_estimator->GetEffectiveConnectionType(); | |
| 126 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && | |
| 127 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; | |
| 128 } | |
| 129 | |
| 130 NetworkState GetNetworkState(net::URLRequest* request, | 112 NetworkState GetNetworkState(net::URLRequest* request, |
| 131 const OfflinePageHeader& offline_header) { | 113 const OfflinePageHeader& offline_header, |
| 114 previews::PreviewsDecider* previews_decider) { |
| 132 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 115 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 133 | 116 |
| 134 if (offline_header.reason == OfflinePageHeader::Reason::NET_ERROR) | 117 if (offline_header.reason == OfflinePageHeader::Reason::NET_ERROR) |
| 135 return NetworkState::FLAKY_NETWORK; | 118 return NetworkState::FLAKY_NETWORK; |
| 136 | 119 |
| 137 if (net::NetworkChangeNotifier::IsOffline()) | 120 if (net::NetworkChangeNotifier::IsOffline()) |
| 138 return NetworkState::DISCONNECTED_NETWORK; | 121 return NetworkState::DISCONNECTED_NETWORK; |
| 139 | 122 // Checks if previews are allowed, the network is slow, and the request is |
| 140 if (IsNetworkProhibitivelySlow(request)) | 123 // allowed to be shown for previews. |
| 124 if (previews_decider && |
| 125 previews_decider->ShouldAllowPreview(*request, |
| 126 previews::PreviewsType::OFFLINE)) { |
| 141 return NetworkState::PROHIBITIVELY_SLOW_NETWORK; | 127 return NetworkState::PROHIBITIVELY_SLOW_NETWORK; |
| 128 } |
| 142 | 129 |
| 143 // If offline header contains a reason other than RELOAD, the offline page | 130 // If offline header contains a reason other than RELOAD, the offline page |
| 144 // should be forced to load even when the network is connected. | 131 // should be forced to load even when the network is connected. |
| 145 return (offline_header.reason != OfflinePageHeader::Reason::NONE && | 132 return (offline_header.reason != OfflinePageHeader::Reason::NONE && |
| 146 offline_header.reason != OfflinePageHeader::Reason::RELOAD) | 133 offline_header.reason != OfflinePageHeader::Reason::RELOAD) |
| 147 ? NetworkState::FORCE_OFFLINE_ON_CONNECTED_NETWORK | 134 ? NetworkState::FORCE_OFFLINE_ON_CONNECTED_NETWORK |
| 148 : NetworkState::CONNECTED_NETWORK; | 135 : NetworkState::CONNECTED_NETWORK; |
| 149 } | 136 } |
| 150 | 137 |
| 151 OfflinePageRequestJob::AggregatedRequestResult | 138 OfflinePageRequestJob::AggregatedRequestResult |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 void OfflinePageRequestJob::ReportAggregatedRequestResult( | 435 void OfflinePageRequestJob::ReportAggregatedRequestResult( |
| 449 AggregatedRequestResult result) { | 436 AggregatedRequestResult result) { |
| 450 UMA_HISTOGRAM_ENUMERATION("OfflinePages.AggregatedRequestResult", | 437 UMA_HISTOGRAM_ENUMERATION("OfflinePages.AggregatedRequestResult", |
| 451 static_cast<int>(result), | 438 static_cast<int>(result), |
| 452 static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX)); | 439 static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX)); |
| 453 } | 440 } |
| 454 | 441 |
| 455 // static | 442 // static |
| 456 OfflinePageRequestJob* OfflinePageRequestJob::Create( | 443 OfflinePageRequestJob* OfflinePageRequestJob::Create( |
| 457 net::URLRequest* request, | 444 net::URLRequest* request, |
| 458 net::NetworkDelegate* network_delegate) { | 445 net::NetworkDelegate* network_delegate, |
| 446 previews::PreviewsDecider* previews_decider) { |
| 459 const content::ResourceRequestInfo* resource_request_info = | 447 const content::ResourceRequestInfo* resource_request_info = |
| 460 content::ResourceRequestInfo::ForRequest(request); | 448 content::ResourceRequestInfo::ForRequest(request); |
| 461 if (!resource_request_info) | 449 if (!resource_request_info) |
| 462 return nullptr; | 450 return nullptr; |
| 463 | 451 |
| 464 // Ignore the requests not for the main resource. | 452 // Ignore the requests not for the main resource. |
| 465 if (resource_request_info->GetResourceType() != | 453 if (resource_request_info->GetResourceType() != |
| 466 content::RESOURCE_TYPE_MAIN_FRAME) { | 454 content::RESOURCE_TYPE_MAIN_FRAME) { |
| 467 return nullptr; | 455 return nullptr; |
| 468 } | 456 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 479 OfflinePageRequestInfo::GetFromRequest(request); | 467 OfflinePageRequestInfo::GetFromRequest(request); |
| 480 if (info) { | 468 if (info) { |
| 481 // Fall back to default which is set when an offline page cannot be served, | 469 // Fall back to default which is set when an offline page cannot be served, |
| 482 // either page not found or online version desired. | 470 // either page not found or online version desired. |
| 483 if (info->use_default()) | 471 if (info->use_default()) |
| 484 return nullptr; | 472 return nullptr; |
| 485 } else { | 473 } else { |
| 486 request->SetUserData(&kUserDataKey, new OfflinePageRequestInfo()); | 474 request->SetUserData(&kUserDataKey, new OfflinePageRequestInfo()); |
| 487 } | 475 } |
| 488 | 476 |
| 489 return new OfflinePageRequestJob(request, network_delegate); | 477 return new OfflinePageRequestJob(request, network_delegate, previews_decider); |
| 490 } | 478 } |
| 491 | 479 |
| 492 OfflinePageRequestJob::OfflinePageRequestJob( | 480 OfflinePageRequestJob::OfflinePageRequestJob( |
| 493 net::URLRequest* request, | 481 net::URLRequest* request, |
| 494 net::NetworkDelegate* network_delegate) | 482 net::NetworkDelegate* network_delegate, |
| 483 previews::PreviewsDecider* previews_decider) |
| 495 : net::URLRequestFileJob( | 484 : net::URLRequestFileJob( |
| 496 request, | 485 request, |
| 497 network_delegate, | 486 network_delegate, |
| 498 base::FilePath(), | 487 base::FilePath(), |
| 499 content::BrowserThread::GetBlockingPool()-> | 488 content::BrowserThread::GetBlockingPool() |
| 500 GetTaskRunnerWithShutdownBehavior( | 489 ->GetTaskRunnerWithShutdownBehavior( |
| 501 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 490 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
| 502 delegate_(new DefaultDelegate()), | 491 delegate_(new DefaultDelegate()), |
| 503 weak_ptr_factory_(this) { | 492 previews_decider_(previews_decider), |
| 504 } | 493 weak_ptr_factory_(this) {} |
| 505 | 494 |
| 506 OfflinePageRequestJob::~OfflinePageRequestJob() { | 495 OfflinePageRequestJob::~OfflinePageRequestJob() { |
| 507 } | 496 } |
| 508 | 497 |
| 509 void OfflinePageRequestJob::Start() { | 498 void OfflinePageRequestJob::Start() { |
| 510 base::ThreadTaskRunnerHandle::Get()->PostTask( | 499 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 511 FROM_HERE, base::Bind(&OfflinePageRequestJob::StartAsync, | 500 FROM_HERE, base::Bind(&OfflinePageRequestJob::StartAsync, |
| 512 weak_ptr_factory_.GetWeakPtr())); | 501 weak_ptr_factory_.GetWeakPtr())); |
| 513 } | 502 } |
| 514 | 503 |
| 515 void OfflinePageRequestJob::StartAsync() { | 504 void OfflinePageRequestJob::StartAsync() { |
| 516 std::string offline_header_value; | 505 std::string offline_header_value; |
| 517 request()->extra_request_headers().GetHeader( | 506 request()->extra_request_headers().GetHeader( |
| 518 kOfflinePageHeader, &offline_header_value); | 507 kOfflinePageHeader, &offline_header_value); |
| 519 // Note that |offline_header| will be empty if parsing from the header value | 508 // Note that |offline_header| will be empty if parsing from the header value |
| 520 // fails. | 509 // fails. |
| 521 OfflinePageHeader offline_header(offline_header_value); | 510 OfflinePageHeader offline_header(offline_header_value); |
| 522 | 511 |
| 523 NetworkState network_state = GetNetworkState(request(), offline_header); | 512 NetworkState network_state = |
| 513 GetNetworkState(request(), offline_header, previews_decider_); |
| 524 if (network_state == NetworkState::CONNECTED_NETWORK) { | 514 if (network_state == NetworkState::CONNECTED_NETWORK) { |
| 525 FallbackToDefault(); | 515 FallbackToDefault(); |
| 526 return; | 516 return; |
| 527 } | 517 } |
| 528 | 518 |
| 529 content::BrowserThread::PostTask( | 519 content::BrowserThread::PostTask( |
| 530 content::BrowserThread::UI, | 520 content::BrowserThread::UI, |
| 531 FROM_HERE, | 521 FROM_HERE, |
| 532 base::Bind(&SelectPage, | 522 base::Bind(&SelectPage, |
| 533 request()->url(), | 523 request()->url(), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 file_path_ = offline_file_path; | 555 file_path_ = offline_file_path; |
| 566 URLRequestFileJob::Start(); | 556 URLRequestFileJob::Start(); |
| 567 } | 557 } |
| 568 | 558 |
| 569 void OfflinePageRequestJob::SetDelegateForTesting( | 559 void OfflinePageRequestJob::SetDelegateForTesting( |
| 570 std::unique_ptr<Delegate> delegate) { | 560 std::unique_ptr<Delegate> delegate) { |
| 571 delegate_ = std::move(delegate); | 561 delegate_ = std::move(delegate); |
| 572 } | 562 } |
| 573 | 563 |
| 574 } // namespace offline_pages | 564 } // namespace offline_pages |
| OLD | NEW |