| 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_experiments.h" | 25 #include "components/previews/core/previews_experiments.h" |
| 23 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/resource_request_info.h" | 27 #include "content/public/browser/resource_request_info.h" |
| 25 #include "content/public/browser/web_contents.h" | 28 #include "content/public/browser/web_contents.h" |
| 26 #include "content/public/common/resource_type.h" | 29 #include "content/public/common/resource_type.h" |
| 27 #include "net/base/network_change_notifier.h" | 30 #include "net/base/network_change_notifier.h" |
| 28 #include "net/http/http_request_headers.h" | 31 #include "net/http/http_request_headers.h" |
| 29 #include "net/nqe/network_quality_estimator.h" | 32 #include "net/nqe/network_quality_estimator.h" |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 content::ResourceRequestInfo::WebContentsGetter web_contents_getter) { | 218 content::ResourceRequestInfo::WebContentsGetter web_contents_getter) { |
| 216 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 219 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 217 | 220 |
| 218 content::WebContents* web_contents = web_contents_getter.Run(); | 221 content::WebContents* web_contents = web_contents_getter.Run(); |
| 219 return web_contents ? | 222 return web_contents ? |
| 220 OfflinePageModelFactory::GetForBrowserContext( | 223 OfflinePageModelFactory::GetForBrowserContext( |
| 221 web_contents->GetBrowserContext()) : | 224 web_contents->GetBrowserContext()) : |
| 222 nullptr; | 225 nullptr; |
| 223 } | 226 } |
| 224 | 227 |
| 225 void NotifyOfflineFilePathOnIO(base::WeakPtr<OfflinePageRequestJob> job, | 228 void NotifyOfflineFilePathOnIO( |
| 226 const base::FilePath& offline_file_path) { | 229 base::WeakPtr<OfflinePageRequestJob> job, |
| 230 const base::FilePath& offline_file_path, |
| 231 std::unique_ptr<OfflinePageHeader> offline_header, |
| 232 std::unique_ptr<OfflinePageItem> offline_page) { |
| 227 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 233 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 228 | 234 |
| 229 if (!job) | 235 if (!job) |
| 230 return; | 236 return; |
| 231 job->OnOfflineFilePathAvailable(offline_file_path); | 237 job->OnOfflineFilePathAvailable(offline_file_path, std::move(offline_header), |
| 238 std::move(offline_page)); |
| 232 } | 239 } |
| 233 | 240 |
| 234 // Notifies OfflinePageRequestJob about the offline file path. Note that the | 241 // Notifies OfflinePageRequestJob about the offline file path. Note that the |
| 235 // file path may be empty if not found or on error. | 242 // file path may be empty if not found or on error. |
| 236 void NotifyOfflineFilePathOnUI(base::WeakPtr<OfflinePageRequestJob> job, | 243 void NotifyOfflineFilePathOnUI(base::WeakPtr<OfflinePageRequestJob> job, |
| 237 const base::FilePath& offline_file_path) { | 244 const base::FilePath& offline_file_path, |
| 245 const OfflinePageHeader* offline_header, |
| 246 const OfflinePageItem* offline_page) { |
| 238 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 247 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 239 | 248 |
| 249 std::unique_ptr<OfflinePageHeader> offline_page_header; |
| 250 std::unique_ptr<OfflinePageItem> offline_page_item; |
| 251 |
| 252 if (offline_header && offline_page) { |
| 253 offline_page_header.reset(new OfflinePageHeader(*offline_header)); |
| 254 offline_page_item.reset(new OfflinePageItem(*offline_page)); |
| 255 } |
| 256 |
| 240 // Delegates to IO thread since OfflinePageRequestJob should only be accessed | 257 // Delegates to IO thread since OfflinePageRequestJob should only be accessed |
| 241 // from IO thread. | 258 // from IO thread. |
| 242 content::BrowserThread::PostTask( | 259 content::BrowserThread::PostTask( |
| 243 content::BrowserThread::IO, | 260 content::BrowserThread::IO, FROM_HERE, |
| 244 FROM_HERE, | 261 base::Bind(&NotifyOfflineFilePathOnIO, job, offline_file_path, |
| 245 base::Bind(&NotifyOfflineFilePathOnIO, job, offline_file_path)); | 262 base::Passed(&offline_page_header), |
| 263 base::Passed(&offline_page_item))); |
| 246 } | 264 } |
| 247 | 265 |
| 248 // Finds the offline file path based on the select page result and network | 266 // Finds the offline file path based on the select page result and network |
| 249 // state and marks it as accessed. | 267 // state and marks it as accessed. |
| 250 RequestResult AccessOfflineFile( | 268 RequestResult AccessOfflineFile( |
| 251 const OfflinePageHeader& offline_header, | 269 const OfflinePageHeader& offline_header, |
| 252 NetworkState network_state, | 270 NetworkState network_state, |
| 253 base::WeakPtr<OfflinePageRequestJob> job, | 271 base::WeakPtr<OfflinePageRequestJob> job, |
| 254 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 272 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 255 const OfflinePageItem* offline_page, | 273 const OfflinePageItem* offline_page, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 276 | 294 |
| 277 // Since offline page will be loaded, it should be marked as accessed. | 295 // Since offline page will be loaded, it should be marked as accessed. |
| 278 OfflinePageModel* offline_page_model = | 296 OfflinePageModel* offline_page_model = |
| 279 OfflinePageModelFactory::GetForBrowserContext( | 297 OfflinePageModelFactory::GetForBrowserContext( |
| 280 web_contents->GetBrowserContext()); | 298 web_contents->GetBrowserContext()); |
| 281 // |offline_page_model| cannot be null because OfflinePageRequestInterceptor | 299 // |offline_page_model| cannot be null because OfflinePageRequestInterceptor |
| 282 // will not be created under incognito mode. | 300 // will not be created under incognito mode. |
| 283 DCHECK(offline_page_model); | 301 DCHECK(offline_page_model); |
| 284 offline_page_model->MarkPageAccessed(offline_page->offline_id); | 302 offline_page_model->MarkPageAccessed(offline_page->offline_id); |
| 285 | 303 |
| 286 // Save an cached copy of OfflinePageItem such that Tab code can get | |
| 287 // the loaded offline page immediately. | |
| 288 OfflinePageTabHelper* tab_helper = | |
| 289 OfflinePageTabHelper::FromWebContents(web_contents); | |
| 290 DCHECK(tab_helper); | |
| 291 tab_helper->SetOfflinePage( | |
| 292 *offline_page, | |
| 293 offline_header, | |
| 294 network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); | |
| 295 | |
| 296 *offline_file_path = offline_page->file_path; | 304 *offline_file_path = offline_page->file_path; |
| 297 return RequestResult::OFFLINE_PAGE_SERVED; | 305 return RequestResult::OFFLINE_PAGE_SERVED; |
| 298 } | 306 } |
| 299 | 307 |
| 300 // Handles the result of finding an offline page. | 308 // Handles the result of finding an offline page. |
| 301 void SucceededToFindOfflinePage( | 309 void SucceededToFindOfflinePage( |
| 302 const OfflinePageHeader& offline_header, | 310 const OfflinePageHeader& offline_header, |
| 303 NetworkState network_state, | 311 NetworkState network_state, |
| 304 base::WeakPtr<OfflinePageRequestJob> job, | 312 base::WeakPtr<OfflinePageRequestJob> job, |
| 305 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 313 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 306 const OfflinePageItem* offline_page) { | 314 const OfflinePageItem* offline_page) { |
| 307 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 315 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 308 | 316 |
| 309 base::FilePath offline_file_path; | 317 base::FilePath offline_file_path; |
| 310 RequestResult request_result = AccessOfflineFile( | 318 RequestResult request_result = AccessOfflineFile( |
| 311 offline_header, network_state, job, web_contents_getter, offline_page, | 319 offline_header, network_state, job, web_contents_getter, offline_page, |
| 312 &offline_file_path); | 320 &offline_file_path); |
| 313 | 321 |
| 314 ReportRequestResult(request_result, network_state); | 322 ReportRequestResult(request_result, network_state); |
| 315 | 323 |
| 316 // NotifyOfflineFilePathOnUI should always be called regardless the failure | 324 // NotifyOfflineFilePathOnUI should always be called regardless the failure |
| 317 // result and empty file path such that OfflinePageRequestJob will be notified | 325 // result and empty file path such that OfflinePageRequestJob will be notified |
| 318 // on failure. | 326 // on failure. |
| 319 NotifyOfflineFilePathOnUI(job, offline_file_path); | 327 NotifyOfflineFilePathOnUI(job, offline_file_path, &offline_header, |
| 328 offline_page); |
| 320 } | 329 } |
| 321 | 330 |
| 322 void FailedToFindOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { | 331 void FailedToFindOfflinePage(base::WeakPtr<OfflinePageRequestJob> job) { |
| 323 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 332 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 324 | 333 |
| 325 // Proceed with empty file path in order to notify the OfflinePageRequestJob | 334 // Proceed with empty file path in order to notify the OfflinePageRequestJob |
| 326 // about the failure. | 335 // about the failure. |
| 327 base::FilePath empty_file_path; | 336 base::FilePath empty_file_path; |
| 328 NotifyOfflineFilePathOnUI(job, empty_file_path); | 337 NotifyOfflineFilePathOnUI(job, empty_file_path, nullptr, nullptr); |
| 329 } | 338 } |
| 330 | 339 |
| 331 // Tries to find the offline page to serve for |online_url|. | 340 // Tries to find the offline page to serve for |online_url|. |
| 332 void SelectPageForOnlineURL( | 341 void SelectPageForOnlineURL( |
| 333 const GURL& online_url, | 342 const GURL& online_url, |
| 334 const OfflinePageHeader& offline_header, | 343 const OfflinePageHeader& offline_header, |
| 335 NetworkState network_state, | 344 NetworkState network_state, |
| 336 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, | 345 content::ResourceRequestInfo::WebContentsGetter web_contents_getter, |
| 337 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, | 346 OfflinePageRequestJob::Delegate::TabIdGetter tab_id_getter, |
| 338 base::WeakPtr<OfflinePageRequestJob> job) { | 347 base::WeakPtr<OfflinePageRequestJob> job) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 return new OfflinePageRequestJob(request, network_delegate); | 498 return new OfflinePageRequestJob(request, network_delegate); |
| 490 } | 499 } |
| 491 | 500 |
| 492 OfflinePageRequestJob::OfflinePageRequestJob( | 501 OfflinePageRequestJob::OfflinePageRequestJob( |
| 493 net::URLRequest* request, | 502 net::URLRequest* request, |
| 494 net::NetworkDelegate* network_delegate) | 503 net::NetworkDelegate* network_delegate) |
| 495 : net::URLRequestFileJob( | 504 : net::URLRequestFileJob( |
| 496 request, | 505 request, |
| 497 network_delegate, | 506 network_delegate, |
| 498 base::FilePath(), | 507 base::FilePath(), |
| 499 content::BrowserThread::GetBlockingPool()-> | 508 content::BrowserThread::GetBlockingPool() |
| 500 GetTaskRunnerWithShutdownBehavior( | 509 ->GetTaskRunnerWithShutdownBehavior( |
| 501 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 510 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
| 502 delegate_(new DefaultDelegate()), | 511 delegate_(new DefaultDelegate()), |
| 503 weak_ptr_factory_(this) { | 512 was_started_as_preview_(false), |
| 504 } | 513 weak_ptr_factory_(this) {} |
| 505 | 514 |
| 506 OfflinePageRequestJob::~OfflinePageRequestJob() { | 515 OfflinePageRequestJob::~OfflinePageRequestJob() { |
| 507 } | 516 } |
| 508 | 517 |
| 509 void OfflinePageRequestJob::Start() { | 518 void OfflinePageRequestJob::Start() { |
| 510 base::ThreadTaskRunnerHandle::Get()->PostTask( | 519 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 511 FROM_HERE, base::Bind(&OfflinePageRequestJob::StartAsync, | 520 FROM_HERE, base::Bind(&OfflinePageRequestJob::StartAsync, |
| 512 weak_ptr_factory_.GetWeakPtr())); | 521 weak_ptr_factory_.GetWeakPtr())); |
| 513 } | 522 } |
| 514 | 523 |
| 515 void OfflinePageRequestJob::StartAsync() { | 524 void OfflinePageRequestJob::StartAsync() { |
| 516 std::string offline_header_value; | 525 std::string offline_header_value; |
| 517 request()->extra_request_headers().GetHeader( | 526 request()->extra_request_headers().GetHeader( |
| 518 kOfflinePageHeader, &offline_header_value); | 527 kOfflinePageHeader, &offline_header_value); |
| 519 // Note that |offline_header| will be empty if parsing from the header value | 528 // Note that |offline_header| will be empty if parsing from the header value |
| 520 // fails. | 529 // fails. |
| 521 OfflinePageHeader offline_header(offline_header_value); | 530 OfflinePageHeader offline_header(offline_header_value); |
| 522 | 531 |
| 523 NetworkState network_state = GetNetworkState(request(), offline_header); | 532 NetworkState network_state = GetNetworkState(request(), offline_header); |
| 533 was_started_as_preview_ = |
| 534 network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK; |
| 524 if (network_state == NetworkState::CONNECTED_NETWORK) { | 535 if (network_state == NetworkState::CONNECTED_NETWORK) { |
| 525 FallbackToDefault(); | 536 FallbackToDefault(); |
| 526 return; | 537 return; |
| 527 } | 538 } |
| 528 | 539 |
| 529 content::BrowserThread::PostTask( | 540 content::BrowserThread::PostTask( |
| 530 content::BrowserThread::UI, | 541 content::BrowserThread::UI, |
| 531 FROM_HERE, | 542 FROM_HERE, |
| 532 base::Bind(&SelectPage, | 543 base::Bind(&SelectPage, |
| 533 request()->url(), | 544 request()->url(), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 546 void OfflinePageRequestJob::FallbackToDefault() { | 557 void OfflinePageRequestJob::FallbackToDefault() { |
| 547 OfflinePageRequestInfo* info = | 558 OfflinePageRequestInfo* info = |
| 548 OfflinePageRequestInfo::GetFromRequest(request()); | 559 OfflinePageRequestInfo::GetFromRequest(request()); |
| 549 DCHECK(info); | 560 DCHECK(info); |
| 550 info->set_use_default(true); | 561 info->set_use_default(true); |
| 551 | 562 |
| 552 URLRequestJob::NotifyRestartRequired(); | 563 URLRequestJob::NotifyRestartRequired(); |
| 553 } | 564 } |
| 554 | 565 |
| 555 void OfflinePageRequestJob::OnOfflineFilePathAvailable( | 566 void OfflinePageRequestJob::OnOfflineFilePathAvailable( |
| 556 const base::FilePath& offline_file_path) { | 567 const base::FilePath& offline_file_path, |
| 568 std::unique_ptr<OfflinePageHeader> offline_header, |
| 569 std::unique_ptr<OfflinePageItem> offline_page) { |
| 557 // If offline file path is empty, it means that offline page cannot be found | 570 // If offline file path is empty, it means that offline page cannot be found |
| 558 // and we want to restart the job to fall back to the default handling. | 571 // and we want to restart the job to fall back to the default handling. |
| 559 if (offline_file_path.empty()) { | 572 if (offline_file_path.empty()) { |
| 560 FallbackToDefault(); | 573 FallbackToDefault(); |
| 561 return; | 574 return; |
| 562 } | 575 } |
| 563 | 576 |
| 577 // Add LoadedOfflinePageInfo to the request. |
| 578 if (offline_header && offline_page) { |
| 579 LoadedOfflinePageInfo::CreateInfoForRequest( |
| 580 request(), std::move(offline_page), std::move(offline_header), |
| 581 was_started_as_preview_); |
| 582 } |
| 583 |
| 564 // Sets the file path and lets URLRequestFileJob start to read from the file. | 584 // Sets the file path and lets URLRequestFileJob start to read from the file. |
| 565 file_path_ = offline_file_path; | 585 file_path_ = offline_file_path; |
| 566 URLRequestFileJob::Start(); | 586 URLRequestFileJob::Start(); |
| 567 } | 587 } |
| 568 | 588 |
| 569 void OfflinePageRequestJob::SetDelegateForTesting( | 589 void OfflinePageRequestJob::SetDelegateForTesting( |
| 570 std::unique_ptr<Delegate> delegate) { | 590 std::unique_ptr<Delegate> delegate) { |
| 571 delegate_ = std::move(delegate); | 591 delegate_ = std::move(delegate); |
| 572 } | 592 } |
| 573 | 593 |
| 574 } // namespace offline_pages | 594 } // namespace offline_pages |
| OLD | NEW |