Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 error page loads in a | |
|
cbentzel
2012/08/15 17:00:38
"Link Doctor pages act like error page loads in a
mmenke
2012/08/16 14:30:03
Correct. "two" added
| |
| 71 // row. The second time, provisional_render_view_host_ will be NULL. | |
|
cbentzel
2012/08/15 17:00:38
Why will provisional_render_view_host_ be NULL? Wi
mmenke
2012/08/16 14:30:03
It's:
- provisional load
- provisional load fails
| |
| 72 if (is_error_page && provisional_render_view_host_ == render_view_host) | |
| 73 return; | |
| 74 // Otherwise, abort the old load. | |
| 75 tab_reloader_->OnAbort(); | |
| 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 tab_reloader_->OnAbort(); | |
| 91 | 103 |
| 92 tab_reloader_->OnLoadCommitted(pending_error_code_); | 104 // Send information about the new load. |
|
cbentzel
2012/08/15 17:00:38
Why do you need to do this? Just for stats?
mmenke
2012/08/16 14:30:03
To make TabReloader's interface a bit better defin
cbentzel
2012/08/16 19:15:04
I think this is fine.
| |
| 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) { |
| 129 // No further messages for the cancelled navigation will occur. | |
| 130 provisional_render_view_host_ = NULL; | |
| 114 // May have been aborting the load of an error page. | 131 // May have been aborting the load of an error page. |
| 115 pending_error_code_ = net::OK; | 132 pending_error_code_ = net::OK; |
| 116 | 133 |
| 117 tab_reloader_->OnAbort(); | 134 tab_reloader_->OnAbort(); |
| 118 return; | 135 return; |
| 119 } | 136 } |
| 120 | 137 |
| 121 pending_error_code_ = error_code; | 138 pending_error_code_ = error_code; |
| 122 } | 139 } |
| 123 | 140 |
| 124 void CaptivePortalTabHelper::DidStopLoading( | 141 void CaptivePortalTabHelper::DidStopLoading( |
| 125 content::RenderViewHost* render_view_host) { | 142 content::RenderViewHost* render_view_host) { |
| 126 DCHECK(CalledOnValidThread()); | 143 DCHECK(CalledOnValidThread()); |
| 127 | 144 |
| 128 login_detector_->OnStoppedLoading(); | 145 login_detector_->OnStoppedLoading(); |
| 129 } | 146 } |
| 130 | 147 |
| 131 void CaptivePortalTabHelper::Observe( | 148 void CaptivePortalTabHelper::Observe( |
| 132 int type, | 149 int type, |
| 133 const content::NotificationSource& source, | 150 const content::NotificationSource& source, |
| 134 const content::NotificationDetails& details) { | 151 const content::NotificationDetails& details) { |
| 135 DCHECK(CalledOnValidThread()); | 152 DCHECK(CalledOnValidThread()); |
| 136 if (type == content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT) { | 153 switch (type) { |
| 137 DCHECK_EQ(web_contents(), | 154 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: { |
| 138 content::Source<content::WebContents>(source).ptr()); | 155 DCHECK_EQ(web_contents(), |
| 156 content::Source<content::WebContents>(source).ptr()); | |
| 139 | 157 |
| 140 const content::ResourceRedirectDetails* redirect_details = | 158 const content::ResourceRedirectDetails* redirect_details = |
| 141 content::Details<content::ResourceRedirectDetails>(details).ptr(); | 159 content::Details<content::ResourceRedirectDetails>(details).ptr(); |
| 142 | 160 |
| 143 if (redirect_details->resource_type == ResourceType::MAIN_FRAME) | 161 OnRedirect(redirect_details->origin_child_id, |
| 144 OnRedirect(redirect_details->frame_id, redirect_details->new_url); | 162 redirect_details->resource_type, |
| 145 } else if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) { | 163 redirect_details->new_url); |
| 146 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); | 164 break; |
| 165 } | |
| 166 case chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT: { | |
| 167 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); | |
| 147 | 168 |
| 148 const CaptivePortalService::Results* results = | 169 const CaptivePortalService::Results* results = |
| 149 content::Details<CaptivePortalService::Results>(details).ptr(); | 170 content::Details<CaptivePortalService::Results>(details).ptr(); |
| 150 | 171 |
| 151 OnCaptivePortalResults(results->previous_result, results->result); | 172 OnCaptivePortalResults(results->previous_result, results->result); |
| 152 } else { | 173 break; |
| 153 NOTREACHED(); | 174 } |
| 175 case content::NOTIFICATION_RENDER_VIEW_HOST_DELETED: { | |
| 176 content::RenderViewHost* render_view_host = | |
| 177 content::Source<content::RenderViewHost>(source).ptr(); | |
| 178 // This can happen when a cross-process navigation is aborted, either by | |
| 179 // pressing stop or by starting a new cross-process navigation that can't | |
| 180 // re-use |provisional_render_view_host_|. May also happen on a crash. | |
| 181 if (render_view_host == provisional_render_view_host_) { | |
| 182 provisional_render_view_host_ = NULL; | |
|
cbentzel
2012/08/15 17:00:38
Should you share this logic with the error_code ==
mmenke
2012/08/16 14:30:03
Done. Went ahead and used the same function for t
| |
| 183 pending_error_code_ = net::OK; | |
| 184 tab_reloader_->OnAbort(); | |
| 185 } | |
| 186 break; | |
| 187 } | |
| 188 default: | |
| 189 NOTREACHED(); | |
| 154 } | 190 } |
| 155 } | 191 } |
| 156 | 192 |
| 157 void CaptivePortalTabHelper::OnRedirect(int64 frame_id, const GURL& new_url) { | 193 void CaptivePortalTabHelper::OnRedirect(int child_id, |
| 158 // If the main frame's not currently loading, or the redirect is for some | 194 ResourceType::Type resource_type, |
| 159 // other frame, ignore the redirect. It's unclear if |frame_id| can ever be | 195 const GURL& new_url) { |
| 160 // -1 ("invalid/unknown"), but best to be careful. | 196 // Only main frame redirects for the provisional RenderViewHost matter. |
| 161 if (provisional_main_frame_id_ == -1 || | 197 if (resource_type != ResourceType::MAIN_FRAME || |
|
cbentzel
2012/08/15 17:00:38
Would child_id ever be -1 here?
mmenke
2012/08/16 14:30:03
Since the id is actually used to lookup the Render
| |
| 162 provisional_main_frame_id_ != frame_id) { | 198 child_id != GetProvisionalChildID()) { |
| 163 return; | 199 return; |
| 164 } | 200 } |
| 165 | 201 |
| 166 tab_reloader_->OnRedirect(new_url.SchemeIsSecure()); | 202 tab_reloader_->OnRedirect(new_url.SchemeIsSecure()); |
| 167 } | 203 } |
| 168 | 204 |
| 169 void CaptivePortalTabHelper::OnCaptivePortalResults(Result previous_result, | 205 void CaptivePortalTabHelper::OnCaptivePortalResults(Result previous_result, |
| 170 Result result) { | 206 Result result) { |
| 171 tab_reloader_->OnCaptivePortalResults(previous_result, result); | 207 tab_reloader_->OnCaptivePortalResults(previous_result, result); |
| 172 login_detector_->OnCaptivePortalResults(previous_result, result); | 208 login_detector_->OnCaptivePortalResults(previous_result, result); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 | 243 |
| 208 // Otherwise, open a login tab. Only end up here when a captive portal result | 244 // 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. | 245 // was received, so it's safe to assume |profile_| has a CaptivePortalService. |
| 210 TabContents* tab_contents = chrome::AddSelectedTabWithURL( | 246 TabContents* tab_contents = chrome::AddSelectedTabWithURL( |
| 211 browser, | 247 browser, |
| 212 CaptivePortalServiceFactory::GetForProfile(profile_)->test_url(), | 248 CaptivePortalServiceFactory::GetForProfile(profile_)->test_url(), |
| 213 content::PAGE_TRANSITION_TYPED); | 249 content::PAGE_TRANSITION_TYPED); |
| 214 tab_contents->captive_portal_tab_helper()->SetIsLoginTab(); | 250 tab_contents->captive_portal_tab_helper()->SetIsLoginTab(); |
| 215 } | 251 } |
| 216 | 252 |
| 253 int CaptivePortalTabHelper::GetProvisionalChildID() const { | |
| 254 if (!provisional_render_view_host_) | |
| 255 return -1; | |
| 256 return provisional_render_view_host_->GetProcess()->GetID(); | |
| 257 } | |
| 258 | |
| 217 } // namespace captive_portal | 259 } // namespace captive_portal |
| OLD | NEW |