| Index: chrome/browser/android/offline_pages/offline_page_tab_helper.cc
|
| diff --git a/chrome/browser/android/offline_pages/offline_page_tab_helper.cc b/chrome/browser/android/offline_pages/offline_page_tab_helper.cc
|
| index 94dcb0af30e83525939c8dd7a85fa6ca3ef32e19..9f1f868b35f9f2ba746c7b8026adb81ce07f3b86 100644
|
| --- a/chrome/browser/android/offline_pages/offline_page_tab_helper.cc
|
| +++ b/chrome/browser/android/offline_pages/offline_page_tab_helper.cc
|
| @@ -22,6 +22,18 @@
|
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinePageTabHelper);
|
|
|
| namespace offline_pages {
|
| +namespace {
|
| +
|
| +void ReportAccessedOfflinePage(content::BrowserContext* browser_context,
|
| + const GURL& navigated_url,
|
| + const GURL& online_url) {
|
| + // If there is a valid online URL for this navigated URL, then we are looking
|
| + // at an offline page.
|
| + if (online_url.is_valid())
|
| + OfflinePageUtils::MarkPageAccessed(browser_context, navigated_url);
|
| +}
|
| +
|
| +} // namespace
|
|
|
| OfflinePageTabHelper::OfflinePageTabHelper(content::WebContents* web_contents)
|
| : content::WebContentsObserver(web_contents),
|
| @@ -37,6 +49,10 @@ void OfflinePageTabHelper::DidStartNavigation(
|
| if (!navigation_handle->IsInMainFrame())
|
| return;
|
|
|
| + // This is a new navigation so we can invalidate any previously scheduled
|
| + // operations.
|
| + weak_ptr_factory_.InvalidateWeakPtrs();
|
| +
|
| // Ignore navigations that are forward or back transitions in the nav stack
|
| // which are not at the head of the stack.
|
| const content::NavigationController& controller =
|
| @@ -47,35 +63,18 @@ void OfflinePageTabHelper::DidStartNavigation(
|
| return;
|
| }
|
|
|
| - GURL redirect_url;
|
| + content::BrowserContext* context = web_contents()->GetBrowserContext();
|
| + GURL navigated_url = navigation_handle->GetURL();
|
| + auto redirect_url_callback =
|
| + base::Bind(&OfflinePageTabHelper::GotRedirectURLForStartedNavigation,
|
| + weak_ptr_factory_.GetWeakPtr(), navigated_url);
|
| if (net::NetworkChangeNotifier::IsOffline()) {
|
| - // When the network is disconnected, loading online page will result in
|
| - // immediate redirection to offline copy.
|
| - redirect_url = offline_pages::OfflinePageUtils::GetOfflineURLForOnlineURL(
|
| - web_contents()->GetBrowserContext(), navigation_handle->GetURL());
|
| + OfflinePageUtils::GetOfflineURLForOnlineURL(context, navigated_url,
|
| + redirect_url_callback);
|
| } else {
|
| - // When the network is connected, loading offline copy will result in
|
| - // immediate redirection to online page.
|
| - redirect_url = offline_pages::OfflinePageUtils::GetOnlineURLForOfflineURL(
|
| - web_contents()->GetBrowserContext(), navigation_handle->GetURL());
|
| + OfflinePageUtils::GetOnlineURLForOfflineURL(context, navigated_url,
|
| + redirect_url_callback);
|
| }
|
| -
|
| - // Bails out if no redirection is needed.
|
| - if (!redirect_url.is_valid())
|
| - return;
|
| -
|
| - // Avoids looping between online and offline redirections.
|
| - content::NavigationEntry* entry = controller.GetPendingEntry();
|
| - if (entry && !entry->GetRedirectChain().empty() &&
|
| - entry->GetRedirectChain().back() == redirect_url) {
|
| - return;
|
| - }
|
| -
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&OfflinePageTabHelper::Redirect,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - navigation_handle->GetURL(), redirect_url));
|
| }
|
|
|
| void OfflinePageTabHelper::DidFinishNavigation(
|
| @@ -84,17 +83,26 @@ void OfflinePageTabHelper::DidFinishNavigation(
|
| if (!navigation_handle->IsInMainFrame())
|
| return;
|
|
|
| - // If the offline page is being loaded successfully, set the access record.
|
| + GURL navigated_url = navigation_handle->GetURL();
|
| net::Error error_code = navigation_handle->GetNetErrorCode();
|
| - if (error_code == net::OK &&
|
| - OfflinePageUtils::IsOfflinePage(
|
| - web_contents()->GetBrowserContext(), navigation_handle->GetURL())) {
|
| - UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork", true);
|
| - OfflinePageUtils::MarkPageAccessed(
|
| - web_contents()->GetBrowserContext(), navigation_handle->GetURL());
|
| + content::BrowserContext* browser_context =
|
| + web_contents()->GetBrowserContext();
|
| +
|
| + // If the offline page is being loaded successfully, set the access record but
|
| + // no need to do anything else.
|
| + if (error_code == net::OK) {
|
| + OfflinePageUtils::GetOnlineURLForOfflineURL(
|
| + browser_context, navigated_url,
|
| + base::Bind(&ReportAccessedOfflinePage, browser_context, navigated_url));
|
| + return;
|
| }
|
|
|
| - // Skips load failure other than no network.
|
| + // When the navigation starts, we redirect immediately from online page to
|
| + // offline version on the case that there is no network connection. If there
|
| + // is still network connection but with no or poor network connectivity, the
|
| + // navigation will eventually fail and we want to redirect to offline copy
|
| + // in this case. If error code doesn't match this list, then we still show
|
| + // the error page and not an offline page, so do nothing.
|
| if (error_code != net::ERR_INTERNET_DISCONNECTED &&
|
| error_code != net::ERR_NAME_NOT_RESOLVED &&
|
| error_code != net::ERR_ADDRESS_UNREACHABLE &&
|
| @@ -102,30 +110,55 @@ void OfflinePageTabHelper::DidFinishNavigation(
|
| return;
|
| }
|
|
|
| - // On a forward or back transition, don't affect the order of the nav stack.
|
| - if (navigation_handle->GetPageTransition() ==
|
| - ui::PAGE_TRANSITION_FORWARD_BACK) {
|
| - UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork", false);
|
| + // Otherwise, get the offline URL for this url, and attempt a redirect if
|
| + // necessary.
|
| + OfflinePageUtils::GetOfflineURLForOnlineURL(
|
| + browser_context, navigated_url,
|
| + base::Bind(&OfflinePageTabHelper::GotRedirectURLForSupportedErrorCode,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + navigation_handle->GetPageTransition(), navigated_url));
|
| +}
|
| +
|
| +void OfflinePageTabHelper::GotRedirectURLForSupportedErrorCode(
|
| + ui::PageTransition transition,
|
| + const GURL& from_url,
|
| + const GURL& redirect_url) {
|
| + // If we didn't find an offline URL, or we are doing a forward/back
|
| + // transition, don't redirect.
|
| + bool do_redirect =
|
| + redirect_url.is_valid() && transition != ui::PAGE_TRANSITION_FORWARD_BACK;
|
| + UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork",
|
| + do_redirect);
|
| + if (!do_redirect)
|
| return;
|
| - }
|
|
|
| - // When the navigation starts, we redirect immediately from online page to
|
| - // offline version on the case that there is no network connection. If there
|
| - // is still network connection but with no or poor network connectivity, the
|
| - // navigation will eventually fail and we want to redirect to offline copy
|
| - // in this case.
|
| - GURL offline_url = offline_pages::OfflinePageUtils::GetOfflineURLForOnlineURL(
|
| - web_contents()->GetBrowserContext(), navigation_handle->GetURL());
|
| - if (!offline_url.is_valid()) {
|
| - UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork", false);
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&OfflinePageTabHelper::Redirect,
|
| + weak_ptr_factory_.GetWeakPtr(), from_url, redirect_url));
|
| +}
|
| +
|
| +void OfflinePageTabHelper::GotRedirectURLForStartedNavigation(
|
| + const GURL& from_url,
|
| + const GURL& redirect_url) {
|
| + // Bails out if no redirection is needed.
|
| + if (!redirect_url.is_valid())
|
| + return;
|
| +
|
| + const content::NavigationController& controller =
|
| + web_contents()->GetController();
|
| +
|
| + // Avoids looping between online and offline redirections.
|
| + content::NavigationEntry* entry = controller.GetPendingEntry();
|
| + if (entry && !entry->GetRedirectChain().empty() &&
|
| + entry->GetRedirectChain().back() == redirect_url) {
|
| return;
|
| }
|
|
|
| base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| FROM_HERE,
|
| base::Bind(&OfflinePageTabHelper::Redirect,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - navigation_handle->GetURL(), offline_url));
|
| + weak_ptr_factory_.GetWeakPtr(), from_url, redirect_url));
|
| }
|
|
|
| void OfflinePageTabHelper::Redirect(
|
|
|