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

Side by Side Diff: chrome/browser/captive_portal/captive_portal_tab_helper.cc

Issue 10837146: Fix how captive portals track which page is loading. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Inline GetProcessID, get rid of TestCaptivePortalTabHelper Created 8 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/captive_portal/captive_portal_tab_helper.h" 5 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "chrome/browser/captive_portal/captive_portal_login_detector.h" 8 #include "chrome/browser/captive_portal/captive_portal_login_detector.h"
9 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h" 9 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
10 #include "chrome/browser/captive_portal/captive_portal_service_factory.h" 10 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
11 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_finder.h" 12 #include "chrome/browser/ui/browser_finder.h"
13 #include "chrome/browser/ui/browser_tabstrip.h" 13 #include "chrome/browser/ui/browser_tabstrip.h"
14 #include "chrome/browser/ui/tab_contents/tab_contents.h" 14 #include "chrome/browser/ui/tab_contents/tab_contents.h"
15 #include "chrome/common/chrome_notification_types.h" 15 #include "chrome/common/chrome_notification_types.h"
16 #include "content/public/browser/notification_details.h" 16 #include "content/public/browser/notification_details.h"
17 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_source.h"
18 #include "content/public/browser/notification_types.h" 19 #include "content/public/browser/notification_types.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/resource_request_details.h" 22 #include "content/public/browser/resource_request_details.h"
23 #include "content/public/browser/web_contents.h"
20 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
21 25
22 namespace captive_portal { 26 namespace captive_portal {
23 27
24 CaptivePortalTabHelper::CaptivePortalTabHelper( 28 CaptivePortalTabHelper::CaptivePortalTabHelper(
25 Profile* profile, 29 Profile* profile,
26 content::WebContents* web_contents) 30 content::WebContents* web_contents)
27 : content::WebContentsObserver(web_contents), 31 : content::WebContentsObserver(web_contents),
28 tab_reloader_( 32 tab_reloader_(
29 new CaptivePortalTabReloader( 33 new CaptivePortalTabReloader(
30 profile, 34 profile,
31 web_contents, 35 web_contents,
32 base::Bind(&CaptivePortalTabHelper::OpenLoginTab, 36 base::Bind(&CaptivePortalTabHelper::OpenLoginTab,
33 base::Unretained(this)))), 37 base::Unretained(this)))),
34 login_detector_(new CaptivePortalLoginDetector(profile)), 38 login_detector_(new CaptivePortalLoginDetector(profile)),
35 profile_(profile), 39 profile_(profile),
36 pending_error_code_(net::OK), 40 pending_error_code_(net::OK),
37 provisional_main_frame_id_(-1) { 41 provisional_render_view_host_(NULL) {
38 registrar_.Add(this, 42 registrar_.Add(this,
39 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, 43 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
40 content::Source<Profile>(profile_)); 44 content::Source<Profile>(profile_));
41 registrar_.Add(this, 45 registrar_.Add(this,
42 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, 46 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
43 content::Source<content::WebContents>(web_contents)); 47 content::Source<content::WebContents>(web_contents));
48 registrar_.Add(this,
49 content::NOTIFICATION_RENDER_VIEW_HOST_DELETED,
50 content::NotificationService::AllSources());
44 } 51 }
45 52
46 CaptivePortalTabHelper::~CaptivePortalTabHelper() { 53 CaptivePortalTabHelper::~CaptivePortalTabHelper() {
47 } 54 }
48 55
49 void CaptivePortalTabHelper::DidStartProvisionalLoadForFrame( 56 void CaptivePortalTabHelper::DidStartProvisionalLoadForFrame(
50 int64 frame_id, 57 int64 frame_id,
51 bool is_main_frame, 58 bool is_main_frame,
52 const GURL& validated_url, 59 const GURL& validated_url,
53 bool is_error_page, 60 bool is_error_page,
54 content::RenderViewHost* render_view_host) { 61 content::RenderViewHost* render_view_host) {
55 DCHECK(CalledOnValidThread()); 62 DCHECK(CalledOnValidThread());
56 63
57 // Ignore subframes. 64 // Ignore subframes.
58 if (!is_main_frame) 65 if (!is_main_frame)
59 return; 66 return;
60 67
61 provisional_main_frame_id_ = frame_id; 68 if (provisional_render_view_host_) {
69 // If loading an error page for a previous failure, treat this as part of
70 // the previous load. Link Doctor pages act like two error page loads in a
71 // row. The second time, provisional_render_view_host_ will be NULL.
72 if (is_error_page && provisional_render_view_host_ == render_view_host)
73 return;
74 // Otherwise, abort the old load.
75 OnLoadAborted();
76 }
62 77
63 // If loading an error page for a previous failure, treat this as part of 78 provisional_render_view_host_ = render_view_host;
64 // the previous load. The second check is needed because Link Doctor pages
65 // result in two error page provisional loads in a row. Currently, the
66 // second load is treated as a normal load, rather than reusing old error
67 // codes.
68 if (is_error_page && pending_error_code_ != net::OK)
69 return;
70
71 // Makes the second load for Link Doctor pages act as a normal load.
72 // TODO(mmenke): Figure out if this affects any other cases.
73 pending_error_code_ = net::OK; 79 pending_error_code_ = net::OK;
74 80
75 tab_reloader_->OnLoadStart(validated_url.SchemeIsSecure()); 81 tab_reloader_->OnLoadStart(validated_url.SchemeIsSecure());
76 } 82 }
77 83
78 void CaptivePortalTabHelper::DidCommitProvisionalLoadForFrame( 84 void CaptivePortalTabHelper::DidCommitProvisionalLoadForFrame(
79 int64 frame_id, 85 int64 frame_id,
80 bool is_main_frame, 86 bool is_main_frame,
81 const GURL& url, 87 const GURL& url,
82 content::PageTransition transition_type, 88 content::PageTransition transition_type,
83 content::RenderViewHost* render_view_host) { 89 content::RenderViewHost* render_view_host) {
84 DCHECK(CalledOnValidThread()); 90 DCHECK(CalledOnValidThread());
85 91
86 // Ignore subframes. 92 // Ignore subframes.
87 if (!is_main_frame) 93 if (!is_main_frame)
88 return; 94 return;
89 95
90 provisional_main_frame_id_ = -1; 96 if (provisional_render_view_host_ == render_view_host) {
97 tab_reloader_->OnLoadCommitted(pending_error_code_);
98 } else {
99 // This may happen if the active RenderView commits a page before a cross
100 // process navigation cancels the old load. In this case, the commit of the
101 // old navigation will cancel the newer one.
102 OnLoadAborted();
91 103
92 tab_reloader_->OnLoadCommitted(pending_error_code_); 104 // Send information about the new load.
105 tab_reloader_->OnLoadStart(url.SchemeIsSecure());
106 tab_reloader_->OnLoadCommitted(net::OK);
107 }
108
109 provisional_render_view_host_ = NULL;
93 pending_error_code_ = net::OK; 110 pending_error_code_ = net::OK;
94 } 111 }
95 112
96 void CaptivePortalTabHelper::DidFailProvisionalLoad( 113 void CaptivePortalTabHelper::DidFailProvisionalLoad(
97 int64 frame_id, 114 int64 frame_id,
98 bool is_main_frame, 115 bool is_main_frame,
99 const GURL& validated_url, 116 const GURL& validated_url,
100 int error_code, 117 int error_code,
101 const string16& error_description, 118 const string16& error_description,
102 content::RenderViewHost* render_view_host) { 119 content::RenderViewHost* render_view_host) {
103 DCHECK(CalledOnValidThread()); 120 DCHECK(CalledOnValidThread());
104 121
105 // Ignore subframes. 122 // Ignore subframes and unexpected RenderViewHosts.
106 if (!is_main_frame) 123 if (!is_main_frame || render_view_host != provisional_render_view_host_)
107 return; 124 return;
108 125
109 provisional_main_frame_id_ = -1;
110
111 // Aborts generally aren't followed by loading an error page, so go ahead and 126 // Aborts generally aren't followed by loading an error page, so go ahead and
112 // reset the state now, to prevent any captive portal checks from triggering. 127 // reset the state now, to prevent any captive portal checks from triggering.
113 if (error_code == net::ERR_ABORTED) { 128 if (error_code == net::ERR_ABORTED) {
114 // May have been aborting the load of an error page. 129 OnLoadAborted();
115 pending_error_code_ = net::OK;
116
117 tab_reloader_->OnAbort();
118 return; 130 return;
119 } 131 }
120 132
121 pending_error_code_ = error_code; 133 pending_error_code_ = error_code;
122 } 134 }
123 135
124 void CaptivePortalTabHelper::DidStopLoading( 136 void CaptivePortalTabHelper::DidStopLoading(
125 content::RenderViewHost* render_view_host) { 137 content::RenderViewHost* render_view_host) {
126 DCHECK(CalledOnValidThread()); 138 DCHECK(CalledOnValidThread());
127 139
128 login_detector_->OnStoppedLoading(); 140 login_detector_->OnStoppedLoading();
129 } 141 }
130 142
131 void CaptivePortalTabHelper::Observe( 143 void CaptivePortalTabHelper::Observe(
132 int type, 144 int type,
133 const content::NotificationSource& source, 145 const content::NotificationSource& source,
134 const content::NotificationDetails& details) { 146 const content::NotificationDetails& details) {
135 DCHECK(CalledOnValidThread()); 147 DCHECK(CalledOnValidThread());
136 if (type == content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT) { 148 switch (type) {
137 DCHECK_EQ(web_contents(), 149 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
138 content::Source<content::WebContents>(source).ptr()); 150 DCHECK_EQ(web_contents(),
151 content::Source<content::WebContents>(source).ptr());
139 152
140 const content::ResourceRedirectDetails* redirect_details = 153 const content::ResourceRedirectDetails* redirect_details =
141 content::Details<content::ResourceRedirectDetails>(details).ptr(); 154 content::Details<content::ResourceRedirectDetails>(details).ptr();
142 155
143 if (redirect_details->resource_type == ResourceType::MAIN_FRAME) 156 OnRedirect(redirect_details->origin_child_id,
144 OnRedirect(redirect_details->frame_id, redirect_details->new_url); 157 redirect_details->resource_type,
145 } else if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) { 158 redirect_details->new_url);
146 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); 159 break;
160 }
161 case chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT: {
162 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
147 163
148 const CaptivePortalService::Results* results = 164 const CaptivePortalService::Results* results =
149 content::Details<CaptivePortalService::Results>(details).ptr(); 165 content::Details<CaptivePortalService::Results>(details).ptr();
150 166
151 OnCaptivePortalResults(results->previous_result, results->result); 167 OnCaptivePortalResults(results->previous_result, results->result);
152 } else { 168 break;
153 NOTREACHED(); 169 }
170 case content::NOTIFICATION_RENDER_VIEW_HOST_DELETED: {
171 content::RenderViewHost* render_view_host =
172 content::Source<content::RenderViewHost>(source).ptr();
173 // This can happen when a cross-process navigation is aborted, either by
174 // pressing stop or by starting a new cross-process navigation that can't
175 // re-use |provisional_render_view_host_|. May also happen on a crash.
176 if (render_view_host == provisional_render_view_host_)
177 OnLoadAborted();
178 break;
179 }
180 default:
181 NOTREACHED();
154 } 182 }
155 } 183 }
156 184
157 void CaptivePortalTabHelper::OnRedirect(int64 frame_id, const GURL& new_url) { 185 void CaptivePortalTabHelper::OnRedirect(int child_id,
158 // If the main frame's not currently loading, or the redirect is for some 186 ResourceType::Type resource_type,
159 // other frame, ignore the redirect. It's unclear if |frame_id| can ever be 187 const GURL& new_url) {
160 // -1 ("invalid/unknown"), but best to be careful. 188 // Only main frame redirects for the provisional RenderViewHost matter.
161 if (provisional_main_frame_id_ == -1 || 189 if (resource_type != ResourceType::MAIN_FRAME ||
162 provisional_main_frame_id_ != frame_id) { 190 !provisional_render_view_host_ ||
191 provisional_render_view_host_->GetProcess()->GetID() != child_id) {
163 return; 192 return;
164 } 193 }
165 194
166 tab_reloader_->OnRedirect(new_url.SchemeIsSecure()); 195 tab_reloader_->OnRedirect(new_url.SchemeIsSecure());
167 } 196 }
168 197
169 void CaptivePortalTabHelper::OnCaptivePortalResults(Result previous_result, 198 void CaptivePortalTabHelper::OnCaptivePortalResults(Result previous_result,
170 Result result) { 199 Result result) {
171 tab_reloader_->OnCaptivePortalResults(previous_result, result); 200 tab_reloader_->OnCaptivePortalResults(previous_result, result);
172 login_detector_->OnCaptivePortalResults(previous_result, result); 201 login_detector_->OnCaptivePortalResults(previous_result, result);
173 } 202 }
174 203
204 void CaptivePortalTabHelper::OnLoadAborted() {
205 // No further messages for the cancelled navigation will occur.
206 provisional_render_view_host_ = NULL;
207 // May have been aborting the load of an error page.
208 pending_error_code_ = net::OK;
209
210 tab_reloader_->OnAbort();
211 }
212
175 bool CaptivePortalTabHelper::IsLoginTab() const { 213 bool CaptivePortalTabHelper::IsLoginTab() const {
cbentzel 2012/08/16 19:15:05 Nit: This doesn't match ordering in header.
mmenke 2012/08/16 19:18:34 Done.
176 return login_detector_->is_login_tab(); 214 return login_detector_->is_login_tab();
177 } 215 }
178 216
179 void CaptivePortalTabHelper::SetIsLoginTab() { 217 void CaptivePortalTabHelper::SetIsLoginTab() {
180 login_detector_->set_is_login_tab(); 218 login_detector_->set_is_login_tab();
181 } 219 }
182 220
183 void CaptivePortalTabHelper::SetTabReloaderForTest( 221 void CaptivePortalTabHelper::SetTabReloaderForTest(
184 CaptivePortalTabReloader* tab_reloader) { 222 CaptivePortalTabReloader* tab_reloader) {
185 tab_reloader_.reset(tab_reloader); 223 tab_reloader_.reset(tab_reloader);
(...skipping 22 matching lines...) Expand all
208 // Otherwise, open a login tab. Only end up here when a captive portal result 246 // Otherwise, open a login tab. Only end up here when a captive portal result
209 // was received, so it's safe to assume |profile_| has a CaptivePortalService. 247 // was received, so it's safe to assume |profile_| has a CaptivePortalService.
210 TabContents* tab_contents = chrome::AddSelectedTabWithURL( 248 TabContents* tab_contents = chrome::AddSelectedTabWithURL(
211 browser, 249 browser,
212 CaptivePortalServiceFactory::GetForProfile(profile_)->test_url(), 250 CaptivePortalServiceFactory::GetForProfile(profile_)->test_url(),
213 content::PAGE_TRANSITION_TYPED); 251 content::PAGE_TRANSITION_TYPED);
214 tab_contents->captive_portal_tab_helper()->SetIsLoginTab(); 252 tab_contents->captive_portal_tab_helper()->SetIsLoginTab();
215 } 253 }
216 254
217 } // namespace captive_portal 255 } // namespace captive_portal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698