| 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_tab_helper.h" | 5 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/strings/string_number_conversions.h" | |
| 12 #include "base/threading/thread_task_runner_handle.h" | 11 #include "base/threading/thread_task_runner_handle.h" |
| 13 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 14 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" | 13 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" |
| 15 #include "chrome/browser/android/offline_pages/offline_page_utils.h" | 14 #include "chrome/browser/android/offline_pages/offline_page_utils.h" |
| 16 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" | 15 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" |
| 17 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" | 16 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 19 #include "components/offline_pages/client_namespace_constants.h" | 18 #include "components/offline_pages/client_namespace_constants.h" |
| 20 #include "components/offline_pages/offline_page_model.h" | 19 #include "components/offline_pages/offline_page_model.h" |
| 21 #include "components/previews/previews_experiments.h" | 20 #include "components/previews/previews_experiments.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 nqe_service->GetEffectiveConnectionType(); | 57 nqe_service->GetEffectiveConnectionType(); |
| 59 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && | 58 return effective_connection_type >= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE && |
| 60 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; | 59 effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; |
| 61 } | 60 } |
| 62 | 61 |
| 63 class DefaultDelegate : public OfflinePageTabHelper::Delegate { | 62 class DefaultDelegate : public OfflinePageTabHelper::Delegate { |
| 64 public: | 63 public: |
| 65 DefaultDelegate() {} | 64 DefaultDelegate() {} |
| 66 // offline_pages::OfflinePageTabHelper::Delegate implementation: | 65 // offline_pages::OfflinePageTabHelper::Delegate implementation: |
| 67 bool GetTabId(content::WebContents* web_contents, | 66 bool GetTabId(content::WebContents* web_contents, |
| 68 std::string* tab_id) const override { | 67 int* tab_id) const override { |
| 69 int temp_tab_id; | 68 return OfflinePageUtils::GetTabId(web_contents, tab_id); |
| 70 if (!OfflinePageUtils::GetTabId(web_contents, &temp_tab_id)) | |
| 71 return false; | |
| 72 *tab_id = base::IntToString(temp_tab_id); | |
| 73 return true; | |
| 74 } | 69 } |
| 75 base::Time Now() const override { return base::Time::Now(); } | 70 base::Time Now() const override { return base::Time::Now(); } |
| 76 }; | 71 }; |
| 77 } // namespace | 72 } // namespace |
| 78 | 73 |
| 79 OfflinePageTabHelper::OfflinePageTabHelper(content::WebContents* web_contents) | 74 OfflinePageTabHelper::OfflinePageTabHelper(content::WebContents* web_contents) |
| 80 : content::WebContentsObserver(web_contents), | 75 : content::WebContentsObserver(web_contents), |
| 81 delegate_(new DefaultDelegate()), | 76 delegate_(new DefaultDelegate()), |
| 82 weak_ptr_factory_(this) { | 77 weak_ptr_factory_(this) { |
| 83 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 78 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 112 // TODO(dimich): Not sure this is needed. Clarify and remove. Bug 624216. | 107 // TODO(dimich): Not sure this is needed. Clarify and remove. Bug 624216. |
| 113 const content::NavigationController& controller = | 108 const content::NavigationController& controller = |
| 114 web_contents()->GetController(); | 109 web_contents()->GetController(); |
| 115 if (controller.GetEntryCount() > 0 && | 110 if (controller.GetEntryCount() > 0 && |
| 116 controller.GetCurrentEntryIndex() != -1 && | 111 controller.GetCurrentEntryIndex() != -1 && |
| 117 controller.GetCurrentEntryIndex() < controller.GetEntryCount() - 1) { | 112 controller.GetCurrentEntryIndex() < controller.GetEntryCount() - 1) { |
| 118 return; | 113 return; |
| 119 } | 114 } |
| 120 | 115 |
| 121 if (net::NetworkChangeNotifier::IsOffline()) { | 116 if (net::NetworkChangeNotifier::IsOffline()) { |
| 122 GetPagesForRedirectToOffline( | 117 GetBestPageForRedirectToOffline( |
| 123 RedirectResult::REDIRECTED_ON_DISCONNECTED_NETWORK, navigated_url); | 118 RedirectResult::REDIRECTED_ON_DISCONNECTED_NETWORK, navigated_url); |
| 124 return; | 119 return; |
| 125 } | 120 } |
| 126 | 121 |
| 127 content::BrowserContext* context = web_contents()->GetBrowserContext(); | 122 content::BrowserContext* context = web_contents()->GetBrowserContext(); |
| 128 if (ShouldUseOfflineForSlowNetwork(context)) { | 123 if (ShouldUseOfflineForSlowNetwork(context)) { |
| 129 GetPagesForRedirectToOffline( | 124 GetBestPageForRedirectToOffline( |
| 130 RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK, | 125 RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK, |
| 131 navigated_url); | 126 navigated_url); |
| 132 return; | 127 return; |
| 133 } | 128 } |
| 134 | 129 |
| 135 OfflinePageModel* offline_page_model = | 130 OfflinePageModel* offline_page_model = |
| 136 OfflinePageModelFactory::GetForBrowserContext(context); | 131 OfflinePageModelFactory::GetForBrowserContext(context); |
| 137 if (!offline_page_model) | 132 if (!offline_page_model) |
| 138 return; | 133 return; |
| 139 | 134 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 | 173 |
| 179 // Don't actually want to redirect on a forward/back nav. | 174 // Don't actually want to redirect on a forward/back nav. |
| 180 // TODO(dimich): Clarify and possibly redirect as well. Bug 624216. | 175 // TODO(dimich): Clarify and possibly redirect as well. Bug 624216. |
| 181 if (ui::PageTransitionTypeIncludingQualifiersIs( | 176 if (ui::PageTransitionTypeIncludingQualifiersIs( |
| 182 navigation_handle->GetPageTransition(), | 177 navigation_handle->GetPageTransition(), |
| 183 ui::PAGE_TRANSITION_FORWARD_BACK)) { | 178 ui::PAGE_TRANSITION_FORWARD_BACK)) { |
| 184 ReportRedirectResultUMA(RedirectResult::IGNORED_FLAKY_NETWORK_FORWARD_BACK); | 179 ReportRedirectResultUMA(RedirectResult::IGNORED_FLAKY_NETWORK_FORWARD_BACK); |
| 185 return; | 180 return; |
| 186 } | 181 } |
| 187 | 182 |
| 188 GetPagesForRedirectToOffline( | 183 GetBestPageForRedirectToOffline( |
| 189 RedirectResult::REDIRECTED_ON_FLAKY_NETWORK, navigated_url); | 184 RedirectResult::REDIRECTED_ON_FLAKY_NETWORK, navigated_url); |
| 190 } | 185 } |
| 191 | 186 |
| 192 void OfflinePageTabHelper::RedirectToOnline( | 187 void OfflinePageTabHelper::RedirectToOnline( |
| 193 const GURL& navigated_url, | 188 const GURL& navigated_url, |
| 194 const OfflinePageItem* offline_page) { | 189 const OfflinePageItem* offline_page) { |
| 195 // Bails out if no redirection is needed. No UMA reporting since all regular | 190 // Bails out if no redirection is needed. No UMA reporting since all regular |
| 196 // navigations will be here and it'll dwarf the useful reporting. | 191 // navigations will be here and it'll dwarf the useful reporting. |
| 197 if (!offline_page) | 192 if (!offline_page) |
| 198 return; | 193 return; |
| 199 | 194 |
| 200 GURL redirect_url = offline_page->url; | 195 GURL redirect_url = offline_page->url; |
| 201 if (IsInRedirectLoop(redirect_url)) { | 196 if (IsInRedirectLoop(redirect_url)) { |
| 202 ReportRedirectResultUMA(RedirectResult::REDIRECT_LOOP_ONLINE); | 197 ReportRedirectResultUMA(RedirectResult::REDIRECT_LOOP_ONLINE); |
| 203 return; | 198 return; |
| 204 } | 199 } |
| 205 | 200 |
| 206 Redirect(navigated_url, redirect_url); | 201 Redirect(navigated_url, redirect_url); |
| 207 // Clear the offline page since we are redirecting to online. | 202 // Clear the offline page since we are redirecting to online. |
| 208 offline_page_ = nullptr; | 203 offline_page_ = nullptr; |
| 209 | 204 |
| 210 ReportRedirectResultUMA(RedirectResult::REDIRECTED_ON_CONNECTED_NETWORK); | 205 ReportRedirectResultUMA(RedirectResult::REDIRECTED_ON_CONNECTED_NETWORK); |
| 211 } | 206 } |
| 212 | 207 |
| 213 void OfflinePageTabHelper::GetPagesForRedirectToOffline( | 208 void OfflinePageTabHelper::GetBestPageForRedirectToOffline( |
| 214 RedirectResult result, const GURL& online_url) { | 209 RedirectResult result, const GURL& online_url) { |
| 215 OfflinePageModel* offline_page_model = | |
| 216 OfflinePageModelFactory::GetForBrowserContext( | |
| 217 web_contents()->GetBrowserContext()); | |
| 218 if (!offline_page_model) | |
| 219 return; | |
| 220 | |
| 221 offline_page_model->GetPagesByOnlineURL( | |
| 222 online_url, | |
| 223 base::Bind(&OfflinePageTabHelper::SelectBestPageForRedirectToOffline, | |
| 224 weak_ptr_factory_.GetWeakPtr(), result, online_url)); | |
| 225 } | |
| 226 | |
| 227 void OfflinePageTabHelper::SelectBestPageForRedirectToOffline( | |
| 228 RedirectResult result, | |
| 229 const GURL& online_url, | |
| 230 const MultipleOfflinePageItemResult& pages) { | |
| 231 DCHECK(result == RedirectResult::REDIRECTED_ON_FLAKY_NETWORK || | |
| 232 result == RedirectResult::REDIRECTED_ON_DISCONNECTED_NETWORK || | |
| 233 result == RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK); | |
| 234 | |
| 235 // When there is no valid tab android there is nowhere to show the offline | 210 // When there is no valid tab android there is nowhere to show the offline |
| 236 // page, so we can leave. | 211 // page, so we can leave. |
| 237 std::string tab_id; | 212 int tab_id; |
| 238 if (!delegate_->GetTabId(web_contents(), &tab_id)) { | 213 if (!delegate_->GetTabId(web_contents(), &tab_id)) { |
| 239 ReportRedirectResultUMA(RedirectResult::NO_TAB_ID); | 214 ReportRedirectResultUMA(RedirectResult::NO_TAB_ID); |
| 240 return; | 215 return; |
| 241 } | 216 } |
| 242 | 217 |
| 243 const OfflinePageItem* selected_page = nullptr; | 218 OfflinePageUtils::SelectPageForOnlineURL( |
| 244 for (const auto& offline_page : pages) { | 219 web_contents()->GetBrowserContext(), |
| 245 if ((offline_page.client_id.name_space == kBookmarkNamespace) || | 220 online_url, |
| 246 (offline_page.client_id.name_space == kAsyncNamespace) || | 221 tab_id, |
| 247 (offline_page.client_id.name_space == kLastNNamespace && | 222 base::Bind(&OfflinePageTabHelper::SelectPageForOnlineURLDone, |
| 248 offline_page.client_id.id == tab_id)) { | 223 weak_ptr_factory_.GetWeakPtr(), result, online_url)); |
| 249 if (!selected_page || | 224 } |
| 250 offline_page.creation_time > selected_page->creation_time) { | |
| 251 selected_page = &offline_page; | |
| 252 } | |
| 253 } | |
| 254 } | |
| 255 | 225 |
| 256 if (!selected_page) { | 226 void OfflinePageTabHelper::SelectPageForOnlineURLDone( |
| 227 RedirectResult result, |
| 228 const GURL& online_url, |
| 229 const OfflinePageItem* offline_page) { |
| 230 DCHECK(result == RedirectResult::REDIRECTED_ON_FLAKY_NETWORK || |
| 231 result == RedirectResult::REDIRECTED_ON_DISCONNECTED_NETWORK || |
| 232 result == RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK); |
| 233 |
| 234 if (!offline_page) { |
| 257 switch (result) { | 235 switch (result) { |
| 258 case RedirectResult::REDIRECTED_ON_FLAKY_NETWORK: | 236 case RedirectResult::REDIRECTED_ON_FLAKY_NETWORK: |
| 259 ReportRedirectResultUMA( | 237 ReportRedirectResultUMA( |
| 260 RedirectResult::PAGE_NOT_FOUND_ON_FLAKY_NETWORK); | 238 RedirectResult::PAGE_NOT_FOUND_ON_FLAKY_NETWORK); |
| 261 return; | 239 return; |
| 262 case RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK: | 240 case RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK: |
| 263 ReportRedirectResultUMA( | 241 ReportRedirectResultUMA( |
| 264 RedirectResult::PAGE_NOT_FOUND_ON_PROHIBITIVELY_SLOW_NETWORK); | 242 RedirectResult::PAGE_NOT_FOUND_ON_PROHIBITIVELY_SLOW_NETWORK); |
| 265 return; | 243 return; |
| 266 case RedirectResult::REDIRECTED_ON_DISCONNECTED_NETWORK: | 244 case RedirectResult::REDIRECTED_ON_DISCONNECTED_NETWORK: |
| 267 ReportRedirectResultUMA( | 245 ReportRedirectResultUMA( |
| 268 RedirectResult::PAGE_NOT_FOUND_ON_DISCONNECTED_NETWORK); | 246 RedirectResult::PAGE_NOT_FOUND_ON_DISCONNECTED_NETWORK); |
| 269 return; | 247 return; |
| 270 default: | 248 default: |
| 271 NOTREACHED(); | 249 NOTREACHED(); |
| 272 return; | 250 return; |
| 273 } | 251 } |
| 274 } | 252 } |
| 275 | 253 |
| 276 // If the page is being loaded on a slow network, only use the offline page | 254 // If the page is being loaded on a slow network, only use the offline page |
| 277 // if it was created within the past 7 days. | 255 // if it was created within the past 7 days. |
| 278 if (result == RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK && | 256 if (result == RedirectResult::REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK && |
| 279 delegate_->Now() - selected_page->creation_time > | 257 delegate_->Now() - offline_page->creation_time > |
| 280 base::TimeDelta::FromDays(7)) { | 258 base::TimeDelta::FromDays(7)) { |
| 281 ReportRedirectResultUMA( | 259 ReportRedirectResultUMA( |
| 282 RedirectResult::PAGE_NOT_FRESH_ON_PROHIBITIVELY_SLOW_NETWORK); | 260 RedirectResult::PAGE_NOT_FRESH_ON_PROHIBITIVELY_SLOW_NETWORK); |
| 283 return; | 261 return; |
| 284 } | 262 } |
| 285 | 263 |
| 286 TryRedirectToOffline(result, online_url, *selected_page); | 264 TryRedirectToOffline(result, online_url, *offline_page); |
| 287 } | 265 } |
| 288 | 266 |
| 289 void OfflinePageTabHelper::TryRedirectToOffline( | 267 void OfflinePageTabHelper::TryRedirectToOffline( |
| 290 RedirectResult result, | 268 RedirectResult result, |
| 291 const GURL& from_url, | 269 const GURL& from_url, |
| 292 const OfflinePageItem& offline_page) { | 270 const OfflinePageItem& offline_page) { |
| 293 GURL redirect_url = offline_page.GetOfflineURL(); | 271 GURL redirect_url = offline_page.GetOfflineURL(); |
| 294 if (!redirect_url.is_valid()) | 272 if (!redirect_url.is_valid()) |
| 295 return; | 273 return; |
| 296 | 274 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 321 entry->GetRedirectChain().back() == to_url; | 299 entry->GetRedirectChain().back() == to_url; |
| 322 } | 300 } |
| 323 | 301 |
| 324 void OfflinePageTabHelper::ReportRedirectResultUMA(RedirectResult result) { | 302 void OfflinePageTabHelper::ReportRedirectResultUMA(RedirectResult result) { |
| 325 UMA_HISTOGRAM_ENUMERATION("OfflinePages.RedirectResult", | 303 UMA_HISTOGRAM_ENUMERATION("OfflinePages.RedirectResult", |
| 326 static_cast<int>(result), | 304 static_cast<int>(result), |
| 327 static_cast<int>(RedirectResult::REDIRECT_RESULT_MAX)); | 305 static_cast<int>(RedirectResult::REDIRECT_RESULT_MAX)); |
| 328 } | 306 } |
| 329 | 307 |
| 330 } // namespace offline_pages | 308 } // namespace offline_pages |
| OLD | NEW |