| 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/bind_helpers.h" |
| 10 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" | 16 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" |
| 16 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" | 17 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" |
| 17 #include "chrome/browser/android/offline_pages/offline_page_utils.h" | 18 #include "chrome/browser/android/offline_pages/offline_page_utils.h" |
| 18 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/browser/profiles/profile_manager.h" | 20 #include "chrome/browser/profiles/profile_manager.h" |
| 21 #include "components/offline_pages/loaded_offline_page_info.h" |
| 22 #include "components/offline_pages/offline_page_item.h" |
| 20 #include "components/offline_pages/offline_page_model.h" | 23 #include "components/offline_pages/offline_page_model.h" |
| 21 #include "components/offline_pages/request_header/offline_page_header.h" | 24 #include "components/offline_pages/request_header/offline_page_header.h" |
| 22 #include "components/previews/core/previews_decider.h" | 25 #include "components/previews/core/previews_decider.h" |
| 23 #include "components/previews/core/previews_opt_out_store.h" | 26 #include "components/previews/core/previews_opt_out_store.h" |
| 24 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 25 #include "content/public/browser/resource_request_info.h" | 28 #include "content/public/browser/resource_request_info.h" |
| 26 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 27 #include "content/public/common/resource_type.h" | 30 #include "content/public/common/resource_type.h" |
| 28 #include "net/base/network_change_notifier.h" | 31 #include "net/base/network_change_notifier.h" |
| 29 #include "net/http/http_request_headers.h" | 32 #include "net/http/http_request_headers.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 | 106 |
| 104 private: | 107 private: |
| 105 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { | 108 static bool GetTabId(content::WebContents* web_contents, int* tab_id) { |
| 106 return OfflinePageUtils::GetTabId(web_contents, tab_id); | 109 return OfflinePageUtils::GetTabId(web_contents, tab_id); |
| 107 } | 110 } |
| 108 | 111 |
| 109 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); | 112 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); |
| 110 }; | 113 }; |
| 111 | 114 |
| 112 NetworkState GetNetworkState(net::URLRequest* request, | 115 NetworkState GetNetworkState(net::URLRequest* request, |
| 113 const OfflinePageHeader& offline_header, | 116 const OfflinePageHeader& offline_header) { |
| 114 previews::PreviewsDecider* previews_decider) { | |
| 115 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 117 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 116 | 118 |
| 117 if (offline_header.reason == OfflinePageHeader::Reason::NET_ERROR) | 119 if (offline_header.reason == OfflinePageHeader::Reason::NET_ERROR) |
| 118 return NetworkState::FLAKY_NETWORK; | 120 return NetworkState::FLAKY_NETWORK; |
| 119 | 121 |
| 120 if (net::NetworkChangeNotifier::IsOffline()) | 122 if (net::NetworkChangeNotifier::IsOffline()) |
| 121 return NetworkState::DISCONNECTED_NETWORK; | 123 return NetworkState::DISCONNECTED_NETWORK; |
| 122 // Checks if previews are allowed, the network is slow, and the request is | 124 // Checks if previews are allowed, the network is slow, and the request is |
| 123 // allowed to be shown for previews. | 125 // allowed to be shown for previews. |
| 124 if (previews_decider && | 126 if (previews_decider && |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 content::ResourceRequestInfo::WebContentsGetter web_contents_getter) { | 204 content::ResourceRequestInfo::WebContentsGetter web_contents_getter) { |
| 203 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 204 | 206 |
| 205 content::WebContents* web_contents = web_contents_getter.Run(); | 207 content::WebContents* web_contents = web_contents_getter.Run(); |
| 206 return web_contents ? | 208 return web_contents ? |
| 207 OfflinePageModelFactory::GetForBrowserContext( | 209 OfflinePageModelFactory::GetForBrowserContext( |
| 208 web_contents->GetBrowserContext()) : | 210 web_contents->GetBrowserContext()) : |
| 209 nullptr; | 211 nullptr; |
| 210 } | 212 } |
| 211 | 213 |
| 212 void NotifyOfflineFilePathOnIO(base::WeakPtr<OfflinePageRequestJob> job, | 214 void NotifyOfflineFilePathOnIO( |
| 213 const base::FilePath& offline_file_path) { | 215 base::WeakPtr<OfflinePageRequestJob> job, |
| 216 const base::FilePath& offline_file_path, |
| 217 std::unique_ptr<OfflinePageHeader> offline_header, |
| 218 std::unique_ptr<OfflinePageItem> offline_page) { |
| 214 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 219 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 215 | 220 |
| 216 if (!job) | 221 if (!job) |
| 217 return; | 222 return; |
| 218 job->OnOfflineFilePathAvailable(offline_file_path); | 223 job->OnOfflineFilePathAvailable(offline_file_path, std::move(offline_header), |
| 224 std::move(offline_page)); |
| 219 } | 225 } |
| 220 | 226 |
| 221 // Notifies OfflinePageRequestJob about the offline file path. Note that the | 227 // Notifies OfflinePageRequestJob about the offline file path. Note that the |
| 222 // file path may be empty if not found or on error. | 228 // file path may be empty if not found or on error. |
| 223 void NotifyOfflineFilePathOnUI(base::WeakPtr<OfflinePageRequestJob> job, | 229 void NotifyOfflineFilePathOnUI(base::WeakPtr<OfflinePageRequestJob> job, |
| 224 const base::FilePath& offline_file_path) { | 230 const base::FilePath& offline_file_path, |
| 231 const OfflinePageHeader* offline_header, |
| 232 const OfflinePageItem* offline_page) { |
| 225 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 233 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 226 | 234 |
| 235 std::unique_ptr<OfflinePageHeader> offline_page_header; |
| 236 std::unique_ptr<OfflinePageItem> offline_page_item; |
| 237 |
| 238 if (offline_header && offline_page) { |
| 239 offline_page_header.reset(new OfflinePageHeader(*offline_header)); |
| 240 offline_page_item.reset(new OfflinePageItem(*offline_page)); |
| 241 } |
| 242 |
| 227 // Delegates to IO thread since OfflinePageRequestJob should only be accessed | 243 // Delegates to IO thread since OfflinePageRequestJob should only be accessed |
| 228 // from IO thread. | 244 // from IO thread. |
| 229 content::BrowserThread::PostTask( | 245 content::BrowserThread::PostTask( |
| 230 content::BrowserThread::IO, | 246 content::BrowserThread::IO, FROM_HERE, |
| 231 FROM_HERE, | 247 base::Bind(&NotifyOfflineFilePathOnIO, job, offline_file_path, |
| 232 base::Bind(&NotifyOfflineFilePathOnIO, job, offline_file_path)); | 248 base::Passed(&offline_page_header), |
| 249 base::Passed(&offline_page_item))); |
| 233 } | 250 } |
| 234 | 251 |
| 235 // Finds the offline file path based on the select page result and network | 252 // Finds the offline file path based on the select page result and network |
| 236 // state and marks it as accessed. | 253 // state and marks it as accessed. |
| 237 RequestResult AccessOfflineFile( | 254 RequestResult AccessOfflineFile( |
| 238 const OfflinePageHeader& offline_header, | 255 const OfflinePageHeader& offline_header, |
| 239 NetworkState network_state, | 256 NetworkState network_state, |
| 240 base::WeakPtr<OfflinePageRequestJob> job, | 257 base::WeakPtr<OfflinePageRequestJob> job, |
| 241 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 258 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 242 const OfflinePageItem* offline_page, | 259 const OfflinePageItem* offline_page, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 263 | 280 |
| 264 // Since offline page will be loaded, it should be marked as accessed. | 281 // Since offline page will be loaded, it should be marked as accessed. |
| 265 OfflinePageModel* offline_page_model = | 282 OfflinePageModel* offline_page_model = |
| 266 OfflinePageModelFactory::GetForBrowserContext( | 283 OfflinePageModelFactory::GetForBrowserContext( |
| 267 web_contents->GetBrowserContext()); | 284 web_contents->GetBrowserContext()); |
| 268 // |offline_page_model| cannot be null because OfflinePageRequestInterceptor | 285 // |offline_page_model| cannot be null because OfflinePageRequestInterceptor |
| 269 // will not be created under incognito mode. | 286 // will not be created under incognito mode. |
| 270 DCHECK(offline_page_model); | 287 DCHECK(offline_page_model); |
| 271 offline_page_model->MarkPageAccessed(offline_page->offline_id); | 288 offline_page_model->MarkPageAccessed(offline_page->offline_id); |
| 272 | 289 |
| 273 // Save an cached copy of OfflinePageItem such that Tab code can get | |
| 274 // the loaded offline page immediately. | |
| 275 OfflinePageTabHelper* tab_helper = | |
| 276 OfflinePageTabHelper::FromWebContents(web_contents); | |
| 277 DCHECK(tab_helper); | |
| 278 tab_helper->SetOfflinePage( | |
| 279 *offline_page, | |
| 280 offline_header, | |
| 281 network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); | |
| 282 | |
| 283 *offline_file_path = offline_page->file_path; | 290 *offline_file_path = offline_page->file_path; |
| 284 return RequestResult::OFFLINE_PAGE_SERVED; | 291 return RequestResult::OFFLINE_PAGE_SERVED; |
| 285 } | 292 } |
| 286 | 293 |
| 287 // Handles the result of finding an offline page. | 294 // Handles the result of finding an offline page. |
| 288 void SucceededToFindOfflinePage( | 295 void SucceededToFindOfflinePage( |
| 289 const OfflinePageHeader& offline_header, | 296 const OfflinePageHeader& offline_header, |
| 290 NetworkState network_state, | 297 NetworkState network_state, |
| 291 base::WeakPtr<OfflinePageRequestJob> job, | 298 base::WeakPtr<OfflinePageRequestJob> job, |
| 292 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 299 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 293 const OfflinePageItem* offline_page) { | 300 const OfflinePageItem* offline_page) { |
| 294 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 301 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 295 | 302 |
| 296 base::FilePath offline_file_path; | 303 base::FilePath offline_file_path; |
| 297 RequestResult request_result = AccessOfflineFile( | 304 RequestResult request_result = AccessOfflineFile( |
| 298 offline_header, network_state, job, web_contents_getter, offline_page, | 305 offline_header, network_state, job, web_contents_getter, offline_page, |
| 299 &offline_file_path); | 306 &offline_file_path); |
| 300 | 307 |
| 301 ReportRequestResult(request_result, network_state); | 308 ReportRequestResult(request_result, network_state); |
| 302 | 309 |
| 303 // NotifyOfflineFilePathOnUI should always be called regardless the failure | 310 // NotifyOfflineFilePathOnUI should always be called regardless the failure |
| 304 // result and empty file path such that OfflinePageRequestJob will be notified | 311 // result and empty file path such that OfflinePageRequestJob will be notified |
| 305 // on failure. | 312 // on failure. |
| 306 NotifyOfflineFilePathOnUI(job, offline_file_path); | 313 NotifyOfflineFilePathOnUI(job, offline_file_path, &offline_header, |
| 314 offline_page); |
| 307 } | 315 } |
| 308 | 316 |
| 309 void FailedToFindOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { | 317 void FailedToFindOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { |
| 310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 318 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 311 | 319 |
| 312 // Proceed with empty file path in order to notify the OfflinePageRequestJob | 320 // Proceed with empty file path in order to notify the OfflinePageRequestJob |
| 313 // about the failure. | 321 // about the failure. |
| 314 base::FilePath empty_file_path; | 322 base::FilePath empty_file_path; |
| 315 NotifyOfflineFilePathOnUI(job, empty_file_path); | 323 NotifyOfflineFilePathOnUI(job, empty_file_path, nullptr, nullptr); |
| 316 } | 324 } |
| 317 | 325 |
| 318 // Tries to find the offline page to serve for |online_url|. | 326 // Tries to find the offline page to serve for |online_url|. |
| 319 void SelectPageForOnlineURL( | 327 void SelectPageForOnlineURL( |
| 320 const GURL& online_url, | 328 const GURL& online_url, |
| 321 const OfflinePageHeader& offline_header, | 329 const OfflinePageHeader& offline_header, |
| 322 NetworkState network_state, | 330 NetworkState network_state, |
| 323 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 331 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 324 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | 332 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
| 325 base::WeakPtr<OfflinePageRequestJob> job) { | 333 base::WeakPtr<OfflinePageRequestJob> job) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 void OfflinePageRequestJob::StartAsync() { | 512 void OfflinePageRequestJob::StartAsync() { |
| 505 std::string offline_header_value; | 513 std::string offline_header_value; |
| 506 request()->extra_request_headers().GetHeader( | 514 request()->extra_request_headers().GetHeader( |
| 507 kOfflinePageHeader, &offline_header_value); | 515 kOfflinePageHeader, &offline_header_value); |
| 508 // Note that |offline_header| will be empty if parsing from the header value | 516 // Note that |offline_header| will be empty if parsing from the header value |
| 509 // fails. | 517 // fails. |
| 510 OfflinePageHeader offline_header(offline_header_value); | 518 OfflinePageHeader offline_header(offline_header_value); |
| 511 | 519 |
| 512 NetworkState network_state = | 520 NetworkState network_state = |
| 513 GetNetworkState(request(), offline_header, previews_decider_); | 521 GetNetworkState(request(), offline_header, previews_decider_); |
| 522 was_started_as_preview_ = |
| 523 network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK; |
| 514 if (network_state == NetworkState::CONNECTED_NETWORK) { | 524 if (network_state == NetworkState::CONNECTED_NETWORK) { |
| 515 FallbackToDefault(); | 525 FallbackToDefault(); |
| 516 return; | 526 return; |
| 517 } | 527 } |
| 518 | 528 |
| 519 content::BrowserThread::PostTask( | 529 content::BrowserThread::PostTask( |
| 520 content::BrowserThread::UI, | 530 content::BrowserThread::UI, |
| 521 FROM_HERE, | 531 FROM_HERE, |
| 522 base::Bind(&SelectPage, | 532 base::Bind(&SelectPage, |
| 523 request()->url(), | 533 request()->url(), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 536 void OfflinePageRequestJob::FallbackToDefault() { | 546 void OfflinePageRequestJob::FallbackToDefault() { |
| 537 OfflinePageRequestInfo* info = | 547 OfflinePageRequestInfo* info = |
| 538 OfflinePageRequestInfo::GetFromRequest(request()); | 548 OfflinePageRequestInfo::GetFromRequest(request()); |
| 539 DCHECK(info); | 549 DCHECK(info); |
| 540 info->set_use_default(true); | 550 info->set_use_default(true); |
| 541 | 551 |
| 542 URLRequestJob::NotifyRestartRequired(); | 552 URLRequestJob::NotifyRestartRequired(); |
| 543 } | 553 } |
| 544 | 554 |
| 545 void OfflinePageRequestJob::OnOfflineFilePathAvailable( | 555 void OfflinePageRequestJob::OnOfflineFilePathAvailable( |
| 546 const base::FilePath& offline_file_path) { | 556 const base::FilePath& offline_file_path, |
| 557 std::unique_ptr<OfflinePageHeader> offline_header, |
| 558 std::unique_ptr<OfflinePageItem> offline_page) { |
| 547 // If offline file path is empty, it means that offline page cannot be found | 559 // If offline file path is empty, it means that offline page cannot be found |
| 548 // and we want to restart the job to fall back to the default handling. | 560 // and we want to restart the job to fall back to the default handling. |
| 549 if (offline_file_path.empty()) { | 561 if (offline_file_path.empty()) { |
| 550 FallbackToDefault(); | 562 FallbackToDefault(); |
| 551 return; | 563 return; |
| 552 } | 564 } |
| 553 | 565 |
| 566 // Add LoadedOfflinePageInfo to the request. |
| 567 if (offline_header && offline_page) { |
| 568 LoadedOfflinePageInfo::CreateInfoForRequest( |
| 569 request(), std::move(offline_page), std::move(offline_header), |
| 570 was_started_as_preview_); |
| 571 } |
| 572 |
| 554 // Sets the file path and lets URLRequestFileJob start to read from the file. | 573 // Sets the file path and lets URLRequestFileJob start to read from the file. |
| 555 file_path_ = offline_file_path; | 574 file_path_ = offline_file_path; |
| 556 URLRequestFileJob::Start(); | 575 URLRequestFileJob::Start(); |
| 557 } | 576 } |
| 558 | 577 |
| 559 void OfflinePageRequestJob::SetDelegateForTesting( | 578 void OfflinePageRequestJob::SetDelegateForTesting( |
| 560 std::unique_ptr<Delegate> delegate) { | 579 std::unique_ptr<Delegate> delegate) { |
| 561 delegate_ = std::move(delegate); | 580 delegate_ = std::move(delegate); |
| 562 } | 581 } |
| 563 | 582 |
| 564 } // namespace offline_pages | 583 } // namespace offline_pages |
| OLD | NEW |