Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: chrome/browser/android/offline_pages/offline_page_tab_helper.cc

Issue 2040573002: [Offlining] Updates the tab helper to use the async OfflinePageModel API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address jianli's nits. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
11 #include "chrome/browser/android/offline_pages/offline_page_utils.h" 11 #include "chrome/browser/android/offline_pages/offline_page_utils.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/navigation_controller.h" 13 #include "content/public/browser/navigation_controller.h"
14 #include "content/public/browser/navigation_entry.h" 14 #include "content/public/browser/navigation_entry.h"
15 #include "content/public/browser/navigation_handle.h" 15 #include "content/public/browser/navigation_handle.h"
16 #include "content/public/browser/render_frame_host.h" 16 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/web_contents.h" 17 #include "content/public/browser/web_contents.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/base/network_change_notifier.h" 19 #include "net/base/network_change_notifier.h"
20 #include "ui/base/page_transition_types.h" 20 #include "ui/base/page_transition_types.h"
21 21
22 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinePageTabHelper); 22 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinePageTabHelper);
23 23
24 namespace offline_pages { 24 namespace offline_pages {
25 namespace {
26
27 void ReportAccessedOfflinePage(content::BrowserContext* browser_context,
28 const GURL& navigated_url,
29 const GURL& online_url) {
30 // If there is a valid online URL for this navigated URL, then we are looking
31 // at an offline page.
32 if (online_url.is_valid())
33 OfflinePageUtils::MarkPageAccessed(browser_context, navigated_url);
34 }
35
36 } // namespace
25 37
26 OfflinePageTabHelper::OfflinePageTabHelper(content::WebContents* web_contents) 38 OfflinePageTabHelper::OfflinePageTabHelper(content::WebContents* web_contents)
27 : content::WebContentsObserver(web_contents), 39 : content::WebContentsObserver(web_contents),
28 weak_ptr_factory_(this) { 40 weak_ptr_factory_(this) {
29 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 41 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
30 } 42 }
31 43
32 OfflinePageTabHelper::~OfflinePageTabHelper() {} 44 OfflinePageTabHelper::~OfflinePageTabHelper() {}
33 45
34 void OfflinePageTabHelper::DidStartNavigation( 46 void OfflinePageTabHelper::DidStartNavigation(
35 content::NavigationHandle* navigation_handle) { 47 content::NavigationHandle* navigation_handle) {
36 // Skips non-main frame. 48 // Skips non-main frame.
37 if (!navigation_handle->IsInMainFrame()) 49 if (!navigation_handle->IsInMainFrame())
38 return; 50 return;
39 51
52 // This is a new navigation so we can invalidate any previously scheduled
53 // operations.
54 weak_ptr_factory_.InvalidateWeakPtrs();
55
40 // Ignore navigations that are forward or back transitions in the nav stack 56 // Ignore navigations that are forward or back transitions in the nav stack
41 // which are not at the head of the stack. 57 // which are not at the head of the stack.
42 const content::NavigationController& controller = 58 const content::NavigationController& controller =
43 web_contents()->GetController(); 59 web_contents()->GetController();
44 if (controller.GetEntryCount() > 0 && 60 if (controller.GetEntryCount() > 0 &&
45 controller.GetCurrentEntryIndex() != -1 && 61 controller.GetCurrentEntryIndex() != -1 &&
46 controller.GetCurrentEntryIndex() < controller.GetEntryCount() - 1) { 62 controller.GetCurrentEntryIndex() < controller.GetEntryCount() - 1) {
47 return; 63 return;
48 } 64 }
49 65
50 GURL redirect_url; 66 content::BrowserContext* context = web_contents()->GetBrowserContext();
67 GURL navigated_url = navigation_handle->GetURL();
68 auto redirect_url_callback =
69 base::Bind(&OfflinePageTabHelper::GotRedirectURLForStartedNavigation,
70 weak_ptr_factory_.GetWeakPtr(), navigated_url);
51 if (net::NetworkChangeNotifier::IsOffline()) { 71 if (net::NetworkChangeNotifier::IsOffline()) {
52 // When the network is disconnected, loading online page will result in 72 OfflinePageUtils::GetOfflineURLForOnlineURL(context, navigated_url,
53 // immediate redirection to offline copy. 73 redirect_url_callback);
54 redirect_url = offline_pages::OfflinePageUtils::GetOfflineURLForOnlineURL(
55 web_contents()->GetBrowserContext(), navigation_handle->GetURL());
56 } else { 74 } else {
57 // When the network is connected, loading offline copy will result in 75 OfflinePageUtils::GetOnlineURLForOfflineURL(context, navigated_url,
58 // immediate redirection to online page. 76 redirect_url_callback);
59 redirect_url = offline_pages::OfflinePageUtils::GetOnlineURLForOfflineURL(
60 web_contents()->GetBrowserContext(), navigation_handle->GetURL());
61 } 77 }
62
63 // Bails out if no redirection is needed.
64 if (!redirect_url.is_valid())
65 return;
66
67 // Avoids looping between online and offline redirections.
68 content::NavigationEntry* entry = controller.GetPendingEntry();
69 if (entry && !entry->GetRedirectChain().empty() &&
70 entry->GetRedirectChain().back() == redirect_url) {
71 return;
72 }
73
74 base::ThreadTaskRunnerHandle::Get()->PostTask(
75 FROM_HERE,
76 base::Bind(&OfflinePageTabHelper::Redirect,
77 weak_ptr_factory_.GetWeakPtr(),
78 navigation_handle->GetURL(), redirect_url));
79 } 78 }
80 79
81 void OfflinePageTabHelper::DidFinishNavigation( 80 void OfflinePageTabHelper::DidFinishNavigation(
82 content::NavigationHandle* navigation_handle) { 81 content::NavigationHandle* navigation_handle) {
83 // Skips non-main frame. 82 // Skips non-main frame.
84 if (!navigation_handle->IsInMainFrame()) 83 if (!navigation_handle->IsInMainFrame())
85 return; 84 return;
86 85
87 // If the offline page is being loaded successfully, set the access record. 86 GURL navigated_url = navigation_handle->GetURL();
88 net::Error error_code = navigation_handle->GetNetErrorCode(); 87 net::Error error_code = navigation_handle->GetNetErrorCode();
89 if (error_code == net::OK && 88 content::BrowserContext* browser_context =
90 OfflinePageUtils::IsOfflinePage( 89 web_contents()->GetBrowserContext();
91 web_contents()->GetBrowserContext(), navigation_handle->GetURL())) { 90
92 UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork", true); 91 // If the offline page is being loaded successfully, set the access record but
93 OfflinePageUtils::MarkPageAccessed( 92 // no need to do anything else.
94 web_contents()->GetBrowserContext(), navigation_handle->GetURL()); 93 if (error_code == net::OK) {
94 OfflinePageUtils::GetOnlineURLForOfflineURL(
95 browser_context, navigated_url,
96 base::Bind(&ReportAccessedOfflinePage, browser_context, navigated_url));
97 return;
95 } 98 }
96 99
97 // Skips load failure other than no network. 100 // When the navigation starts, we redirect immediately from online page to
101 // offline version on the case that there is no network connection. If there
102 // is still network connection but with no or poor network connectivity, the
103 // navigation will eventually fail and we want to redirect to offline copy
104 // in this case. If error code doesn't match this list, then we still show
105 // the error page and not an offline page, so do nothing.
98 if (error_code != net::ERR_INTERNET_DISCONNECTED && 106 if (error_code != net::ERR_INTERNET_DISCONNECTED &&
99 error_code != net::ERR_NAME_NOT_RESOLVED && 107 error_code != net::ERR_NAME_NOT_RESOLVED &&
100 error_code != net::ERR_ADDRESS_UNREACHABLE && 108 error_code != net::ERR_ADDRESS_UNREACHABLE &&
101 error_code != net::ERR_PROXY_CONNECTION_FAILED) { 109 error_code != net::ERR_PROXY_CONNECTION_FAILED) {
102 return; 110 return;
103 } 111 }
104 112
105 // On a forward or back transition, don't affect the order of the nav stack. 113 // Otherwise, get the offline URL for this url, and attempt a redirect if
106 if (navigation_handle->GetPageTransition() == 114 // necessary.
107 ui::PAGE_TRANSITION_FORWARD_BACK) { 115 OfflinePageUtils::GetOfflineURLForOnlineURL(
108 UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork", false); 116 browser_context, navigated_url,
117 base::Bind(&OfflinePageTabHelper::GotRedirectURLForSupportedErrorCode,
118 weak_ptr_factory_.GetWeakPtr(),
119 navigation_handle->GetPageTransition(), navigated_url));
120 }
121
122 void OfflinePageTabHelper::GotRedirectURLForSupportedErrorCode(
123 ui::PageTransition transition,
124 const GURL& from_url,
125 const GURL& redirect_url) {
126 // If we didn't find an offline URL, or we are doing a forward/back
127 // transition, don't redirect.
128 bool do_redirect =
129 redirect_url.is_valid() && transition != ui::PAGE_TRANSITION_FORWARD_BACK;
130 UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork",
131 do_redirect);
132 if (!do_redirect)
109 return; 133 return;
110 }
111 134
112 // When the navigation starts, we redirect immediately from online page to 135 base::ThreadTaskRunnerHandle::Get()->PostTask(
113 // offline version on the case that there is no network connection. If there 136 FROM_HERE,
114 // is still network connection but with no or poor network connectivity, the 137 base::Bind(&OfflinePageTabHelper::Redirect,
115 // navigation will eventually fail and we want to redirect to offline copy 138 weak_ptr_factory_.GetWeakPtr(), from_url, redirect_url));
116 // in this case. 139 }
117 GURL offline_url = offline_pages::OfflinePageUtils::GetOfflineURLForOnlineURL( 140
118 web_contents()->GetBrowserContext(), navigation_handle->GetURL()); 141 void OfflinePageTabHelper::GotRedirectURLForStartedNavigation(
119 if (!offline_url.is_valid()) { 142 const GURL& from_url,
120 UMA_HISTOGRAM_BOOLEAN("OfflinePages.ShowOfflinePageOnBadNetwork", false); 143 const GURL& redirect_url) {
144 // Bails out if no redirection is needed.
145 if (!redirect_url.is_valid())
146 return;
147
148 const content::NavigationController& controller =
149 web_contents()->GetController();
150
151 // Avoids looping between online and offline redirections.
152 content::NavigationEntry* entry = controller.GetPendingEntry();
153 if (entry && !entry->GetRedirectChain().empty() &&
154 entry->GetRedirectChain().back() == redirect_url) {
121 return; 155 return;
122 } 156 }
123 157
124 base::ThreadTaskRunnerHandle::Get()->PostTask( 158 base::ThreadTaskRunnerHandle::Get()->PostTask(
125 FROM_HERE, 159 FROM_HERE,
126 base::Bind(&OfflinePageTabHelper::Redirect, 160 base::Bind(&OfflinePageTabHelper::Redirect,
127 weak_ptr_factory_.GetWeakPtr(), 161 weak_ptr_factory_.GetWeakPtr(), from_url, redirect_url));
128 navigation_handle->GetURL(), offline_url));
129 } 162 }
130 163
131 void OfflinePageTabHelper::Redirect( 164 void OfflinePageTabHelper::Redirect(
132 const GURL& from_url, const GURL& to_url) { 165 const GURL& from_url, const GURL& to_url) {
133 if (to_url.SchemeIsFile()) { 166 if (to_url.SchemeIsFile()) {
134 UMA_HISTOGRAM_COUNTS("OfflinePages.RedirectToOfflineCount", 1); 167 UMA_HISTOGRAM_COUNTS("OfflinePages.RedirectToOfflineCount", 1);
135 } else { 168 } else {
136 UMA_HISTOGRAM_COUNTS("OfflinePages.RedirectToOnlineCount", 1); 169 UMA_HISTOGRAM_COUNTS("OfflinePages.RedirectToOnlineCount", 1);
137 } 170 }
138 171
139 content::NavigationController::LoadURLParams load_params(to_url); 172 content::NavigationController::LoadURLParams load_params(to_url);
140 load_params.transition_type = ui::PAGE_TRANSITION_CLIENT_REDIRECT; 173 load_params.transition_type = ui::PAGE_TRANSITION_CLIENT_REDIRECT;
141 load_params.redirect_chain.push_back(from_url); 174 load_params.redirect_chain.push_back(from_url);
142 web_contents()->GetController().LoadURLWithParams(load_params); 175 web_contents()->GetController().LoadURLWithParams(load_params);
143 } 176 }
144 177
145 } // namespace offline_pages 178 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698