Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/recent_tab_helper.h" | 5 #include "chrome/browser/android/offline_pages/recent_tab_helper.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h" | 18 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h" |
| 19 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" | 19 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" |
| 20 #include "chrome/browser/android/offline_pages/offline_page_utils.h" | 20 #include "chrome/browser/android/offline_pages/offline_page_utils.h" |
| 21 #include "components/offline_pages/client_namespace_constants.h" | 21 #include "components/offline_pages/client_namespace_constants.h" |
| 22 #include "components/offline_pages/offline_page_feature.h" | |
| 22 #include "components/offline_pages/offline_page_item.h" | 23 #include "components/offline_pages/offline_page_item.h" |
| 23 #include "components/offline_pages/offline_page_model.h" | 24 #include "components/offline_pages/offline_page_model.h" |
| 24 #include "content/public/browser/browser_context.h" | 25 #include "content/public/browser/browser_context.h" |
| 25 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
| 26 #include "content/public/browser/navigation_entry.h" | 27 #include "content/public/browser/navigation_entry.h" |
| 27 #include "content/public/browser/navigation_handle.h" | 28 #include "content/public/browser/navigation_handle.h" |
| 28 | 29 |
| 29 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::RecentTabHelper); | 30 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::RecentTabHelper); |
| 30 | 31 |
| 31 namespace { | 32 namespace { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 47 } | 48 } |
| 48 }; | 49 }; |
| 49 } // namespace | 50 } // namespace |
| 50 | 51 |
| 51 namespace offline_pages { | 52 namespace offline_pages { |
| 52 | 53 |
| 53 RecentTabHelper::RecentTabHelper(content::WebContents* web_contents) | 54 RecentTabHelper::RecentTabHelper(content::WebContents* web_contents) |
| 54 : content::WebContentsObserver(web_contents), | 55 : content::WebContentsObserver(web_contents), |
| 55 page_model_(nullptr), | 56 page_model_(nullptr), |
| 56 snapshots_enabled_(false), | 57 snapshots_enabled_(false), |
| 58 is_page_ready_for_snapshot_(false), | |
| 57 delegate_(new DefaultDelegate()), | 59 delegate_(new DefaultDelegate()), |
| 58 weak_ptr_factory_(this) { | 60 weak_ptr_factory_(this) { |
| 59 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 61 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 60 } | 62 } |
| 61 | 63 |
| 62 RecentTabHelper::~RecentTabHelper() { | 64 RecentTabHelper::~RecentTabHelper() { |
| 63 } | 65 } |
| 64 | 66 |
| 65 void RecentTabHelper::SetDelegate( | 67 void RecentTabHelper::SetDelegate( |
| 66 std::unique_ptr<RecentTabHelper::Delegate> delegate) { | 68 std::unique_ptr<RecentTabHelper::Delegate> delegate) { |
| 67 DCHECK(delegate); | 69 DCHECK(delegate); |
| 68 delegate_ = std::move(delegate); | 70 delegate_ = std::move(delegate); |
| 69 } | 71 } |
| 70 | 72 |
| 71 void RecentTabHelper::LazyInitialize() { | 73 // Initialize lazily. It needs TabAndroid for initialization, which is also a |
| 72 snapshot_controller_.reset(new SnapshotController(delegate_->GetTaskRunner(), | 74 // TabHelper - so can't initialize in constructor because of uncertain order |
| 73 this)); | 75 // of creation of TabHelpers. |
| 76 void RecentTabHelper::EnsureInitialized() { | |
| 77 if (snapshot_controller_) // Initialized already. | |
| 78 return; | |
| 79 | |
| 80 snapshot_controller_.reset( | |
| 81 new SnapshotController(delegate_->GetTaskRunner(), this)); | |
| 82 snapshot_controller_->Stop(); // It is reset when navigation commits. | |
|
dewittj
2016/08/24 23:01:39
perhaps the snapshot controller should initially b
Dmitry Titov
2016/08/25 00:36:09
Perhaps, but this is not the only user of it by no
dewittj
2016/08/25 01:35:22
Acknowledged.
| |
| 83 | |
| 74 int tab_id_number = 0; | 84 int tab_id_number = 0; |
| 75 tab_id_.clear(); | 85 tab_id_.clear(); |
| 76 | 86 |
| 77 if (delegate_->GetTabId(web_contents(), &tab_id_number)) | 87 if (delegate_->GetTabId(web_contents(), &tab_id_number)) |
| 78 tab_id_ = base::IntToString(tab_id_number); | 88 tab_id_ = base::IntToString(tab_id_number); |
| 79 | 89 |
| 80 page_model_ = OfflinePageModelFactory::GetForBrowserContext( | |
| 81 web_contents()->GetBrowserContext()); | |
| 82 | |
| 83 // TODO(dimich): When we have BackgroundOffliner, avoid capturing prerenderer | 90 // TODO(dimich): When we have BackgroundOffliner, avoid capturing prerenderer |
| 84 // WebContents with its origin as well. | 91 // WebContents with its origin as well. |
| 85 snapshots_enabled_ = page_model_ && | 92 snapshots_enabled_ = !tab_id_.empty() && |
| 86 !tab_id_.empty() && | |
| 87 !web_contents()->GetBrowserContext()->IsOffTheRecord(); | 93 !web_contents()->GetBrowserContext()->IsOffTheRecord(); |
| 88 | 94 |
| 89 if (!snapshots_enabled_) | 95 if (!snapshots_enabled_) |
| 90 snapshot_controller_->Stop(); | 96 return; |
| 97 | |
| 98 page_model_ = OfflinePageModelFactory::GetForBrowserContext( | |
| 99 web_contents()->GetBrowserContext()); | |
| 100 } | |
| 101 | |
| 102 void RecentTabHelper::DidStartNavigation( | |
|
dewittj
2016/08/24 23:01:39
This seems like it will change behavior for slower
Dmitry Titov
2016/08/25 00:36:09
Done. I guess I'm being too paranoid about DidFini
| |
| 103 content::NavigationHandle* navigation_handle) { | |
| 104 if (!navigation_handle->IsInMainFrame()) | |
| 105 return; | |
| 106 // Cancel tasks in flight that relate to the previous page. | |
| 107 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 108 is_page_ready_for_snapshot_ = false; | |
| 91 } | 109 } |
| 92 | 110 |
| 93 void RecentTabHelper::DidFinishNavigation( | 111 void RecentTabHelper::DidFinishNavigation( |
| 94 content::NavigationHandle* navigation_handle) { | 112 content::NavigationHandle* navigation_handle) { |
| 95 if (!navigation_handle->IsInMainFrame() || | 113 if (!navigation_handle->IsInMainFrame() || |
| 96 !navigation_handle->HasCommitted()) { | 114 !navigation_handle->HasCommitted()) { |
| 97 return; | 115 return; |
| 98 } | 116 } |
| 99 | 117 |
| 100 // Initialize lazily. It needs TabAndroid for initization, which is also a | 118 EnsureInitialized(); |
|
dewittj
2016/08/24 23:01:39
optional nit: conceptually it might make sense to
Dmitry Titov
2016/08/25 00:36:09
I think I'd need to cache the snapshots_enabled to
| |
| 101 // TabHelper - so can't initialize in constructor because of uncertain order | |
| 102 // of creation of TabHelpers. | |
| 103 if (!snapshot_controller_) | |
| 104 LazyInitialize(); | |
| 105 | |
| 106 if (!snapshots_enabled_) | 119 if (!snapshots_enabled_) |
| 107 return; | 120 return; |
| 108 | 121 |
| 109 // Cancel tasks in flight that relate to the previous page. | |
| 110 weak_ptr_factory_.InvalidateWeakPtrs(); | |
|
dewittj
2016/08/24 23:01:39
Why is this gone? It seems like there are still p
Dmitry Titov
2016/08/25 00:36:08
Moved back, and before initialization.
| |
| 111 | |
| 112 // New navigation, new snapshot session. | 122 // New navigation, new snapshot session. |
| 113 snapshot_url_ = GURL(); | 123 snapshot_url_ = web_contents()->GetLastCommittedURL(); |
| 114 GURL last_committed_url = web_contents()->GetLastCommittedURL(); | |
| 115 | 124 |
| 116 // Check for conditions that would cause us not to snapshot. | 125 // Check for conditions that would cause us not to snapshot. |
| 117 bool can_save = !navigation_handle->IsErrorPage() && | 126 bool can_save = !navigation_handle->IsErrorPage() && |
| 118 OfflinePageModel::CanSaveURL(last_committed_url); | 127 OfflinePageModel::CanSaveURL(snapshot_url_); |
| 119 | 128 |
| 120 UMA_HISTOGRAM_BOOLEAN("OfflinePages.CanSaveRecentPage", can_save); | 129 UMA_HISTOGRAM_BOOLEAN("OfflinePages.CanSaveRecentPage", can_save); |
| 121 | 130 |
| 122 // Always reset so that posted tasks get cancelled. | 131 // Always reset so that posted tasks get canceled. |
| 123 snapshot_controller_->Reset(); | 132 snapshot_controller_->Reset(); |
| 124 | 133 |
| 125 if (!can_save) | 134 if (!can_save) |
| 126 snapshot_controller_->Stop(); | 135 snapshot_controller_->Stop(); |
| 127 else | |
| 128 snapshot_url_ = last_committed_url; | |
| 129 } | 136 } |
| 130 | 137 |
| 131 void RecentTabHelper::DocumentAvailableInMainFrame() { | 138 void RecentTabHelper::DocumentAvailableInMainFrame() { |
| 132 if (!snapshots_enabled_) | 139 EnsureInitialized(); |
| 133 return; | |
| 134 snapshot_controller_->DocumentAvailableInMainFrame(); | 140 snapshot_controller_->DocumentAvailableInMainFrame(); |
| 135 } | 141 } |
| 136 | 142 |
| 137 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() { | 143 void RecentTabHelper::DocumentOnLoadCompletedInMainFrame() { |
| 138 // TODO(dimich): Figure out when this can fire before DidFinishNavigate(). | 144 EnsureInitialized(); |
| 139 // See bug 628716 for more info. | |
| 140 if (!snapshots_enabled_) | |
| 141 return; | |
| 142 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); | 145 snapshot_controller_->DocumentOnLoadCompletedInMainFrame(); |
| 143 } | 146 } |
| 144 | 147 |
| 145 // This starts a sequence of async operations chained through callbacks: | 148 // This starts a sequence of async operations chained through callbacks: |
| 146 // - compute the set of old 'last_n' pages that have to be purged | 149 // - compute the set of old 'last_n' pages that have to be purged |
| 147 // - delete the pages found in the previous step | 150 // - delete the pages found in the previous step |
| 148 // - snapshot the current web contents | 151 // - snapshot the current web contents |
| 149 // Along the chain, the original URL is passed and compared, to detect | 152 // Along the chain, the original URL is passed and compared, to detect |
| 150 // possible navigation and cancel snapshot in that case. | 153 // possible navigation and cancel snapshot in that case. |
| 151 void RecentTabHelper::StartSnapshot() { | 154 void RecentTabHelper::StartSnapshot() { |
| 152 if (!snapshots_enabled_) | 155 is_page_ready_for_snapshot_ = true; |
| 156 | |
| 157 if (!snapshots_enabled_ || | |
| 158 !page_model_ || | |
| 159 !offline_pages::IsOffliningRecentPagesEnabled()) { | |
| 160 ReportSnapshotCompleted(); | |
| 153 return; | 161 return; |
| 162 } | |
| 163 | |
| 154 // Remove previously captured pages for this tab. | 164 // Remove previously captured pages for this tab. |
| 155 page_model_->GetOfflineIdsForClientId( | 165 page_model_->GetOfflineIdsForClientId( |
| 156 client_id(), | 166 client_id(), |
| 157 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge, | 167 base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge, |
| 158 weak_ptr_factory_.GetWeakPtr())); | 168 weak_ptr_factory_.GetWeakPtr())); |
| 159 } | 169 } |
| 160 | 170 |
| 161 void RecentTabHelper::ContinueSnapshotWithIdsToPurge( | 171 void RecentTabHelper::ContinueSnapshotWithIdsToPurge( |
| 162 const std::vector<int64_t>& page_ids) { | 172 const std::vector<int64_t>& page_ids) { |
| 163 page_model_->DeletePagesByOfflineId( | 173 page_model_->DeletePagesByOfflineId( |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 bool RecentTabHelper::IsSamePage() const { | 206 bool RecentTabHelper::IsSamePage() const { |
| 197 return web_contents() && | 207 return web_contents() && |
| 198 (web_contents()->GetLastCommittedURL() == snapshot_url_); | 208 (web_contents()->GetLastCommittedURL() == snapshot_url_); |
| 199 } | 209 } |
| 200 | 210 |
| 201 ClientId RecentTabHelper::client_id() const { | 211 ClientId RecentTabHelper::client_id() const { |
| 202 return ClientId(kLastNNamespace, tab_id_); | 212 return ClientId(kLastNNamespace, tab_id_); |
| 203 } | 213 } |
| 204 | 214 |
| 205 } // namespace offline_pages | 215 } // namespace offline_pages |
| OLD | NEW |