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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_TAB_HELPER_H_ 6 #define CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_TAB_HELPER_H_ 7 8 #include "base/basictypes.h" 9 #include "base/compiler_specific.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/threading/non_thread_safe.h" 12 #include "chrome/browser/captive_portal/captive_portal_service.h" 13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/notification_registrar.h" 15 #include "content/public/browser/web_contents_observer.h" 16 #include "content/public/browser/web_contents_user_data.h" 17 #include "webkit/common/resource_type.h" 18 19 class GURL; 20 class Profile; 21 22 namespace content { 23 class WebContents; 24 } 25 26 namespace net { 27 class SSLInfo; 28 } 29 30 class CaptivePortalLoginDetector; 31 class CaptivePortalTabReloader; 32 33 // Along with the classes it owns, responsible for detecting page loads broken 34 // by a captive portal, triggering captive portal checks on navigation events 35 // that may indicate a captive portal is present, or has been removed / logged 36 // in to, and taking any correcting actions. 37 // 38 // It acts as a WebContentsObserver for its CaptivePortalLoginDetector and 39 // CaptivePortalTabReloader. It filters out non-main-frame resource loads, and 40 // treats the commit of an error page as a single event, rather than as 3 41 // (ProvisionalLoadFail, DidStartProvisionalLoad, DidCommit), which simplifies 42 // the CaptivePortalTabReloader. It is also needed by CaptivePortalTabReloaders 43 // to inform the tab's CaptivePortalLoginDetector when the tab is at a captive 44 // portal's login page. 45 // 46 // The TabHelper assumes that a WebContents can only have one RenderViewHost 47 // with a provisional load at a time, and tracks only that navigation. This 48 // assumption can be violated in rare cases, for example, a same-site 49 // navigation interrupted by a cross-process navigation started from the 50 // omnibox, may commit before it can be cancelled. In these cases, this class 51 // may pass incorrect messages to the TabReloader, which will, at worst, result 52 // in not opening up a login tab until a second load fails or not automatically 53 // reloading a tab after logging in. 54 // 55 // For the design doc, see: 56 // https://docs.google.com/document/d/1k-gP2sswzYNvryu9NcgN7q5XrsMlUdlUdoW9WRaEmfM/edit 57 class CaptivePortalTabHelper 58 : public content::WebContentsObserver, 59 public content::NotificationObserver, 60 public base::NonThreadSafe, 61 public content::WebContentsUserData<CaptivePortalTabHelper> { 62 public: 63 virtual ~CaptivePortalTabHelper(); 64 65 // content::WebContentsObserver: 66 virtual void RenderViewDeleted( 67 content::RenderViewHost* render_view_host) OVERRIDE; 68 69 virtual void DidStartProvisionalLoadForFrame( 70 int64 frame_id, 71 int64 parent_frame_id, 72 bool is_main_frame, 73 const GURL& validated_url, 74 bool is_error_page, 75 bool is_iframe_srcdoc, 76 content::RenderViewHost* render_view_host) OVERRIDE; 77 78 virtual void DidCommitProvisionalLoadForFrame( 79 int64 frame_id, 80 const base::string16& frame_unique_name, 81 bool is_main_frame, 82 const GURL& url, 83 content::PageTransition transition_type, 84 content::RenderViewHost* render_view_host) OVERRIDE; 85 86 virtual void DidFailProvisionalLoad( 87 int64 frame_id, 88 const base::string16& frame_unique_name, 89 bool is_main_frame, 90 const GURL& validated_url, 91 int error_code, 92 const base::string16& error_description, 93 content::RenderViewHost* render_view_host) OVERRIDE; 94 95 virtual void DidStopLoading( 96 content::RenderViewHost* render_view_host) OVERRIDE; 97 98 // content::NotificationObserver: 99 virtual void Observe( 100 int type, 101 const content::NotificationSource& source, 102 const content::NotificationDetails& details) OVERRIDE; 103 104 // Called when a certificate interstitial error page is about to be shown. 105 void OnSSLCertError(const net::SSLInfo& ssl_info); 106 107 // A "Login Tab" is a tab that was originally at a captive portal login 108 // page. This is set to false when a captive portal is no longer detected. 109 bool IsLoginTab() const; 110 111 private: 112 friend class CaptivePortalBrowserTest; 113 friend class CaptivePortalTabHelperTest; 114 115 friend class content::WebContentsUserData<CaptivePortalTabHelper>; 116 explicit CaptivePortalTabHelper(content::WebContents* web_contents); 117 118 // Called by Observe in response to the corresponding event. 119 void OnRedirect(int child_id, 120 ResourceType::Type resource_type, 121 const GURL& new_url); 122 123 // Called by Observe in response to the corresponding event. 124 void OnCaptivePortalResults( 125 captive_portal::CaptivePortalResult previous_result, 126 captive_portal::CaptivePortalResult result); 127 128 void OnLoadAborted(); 129 130 // Called to indicate a tab is at, or is navigating to, the captive portal 131 // login page. 132 void SetIsLoginTab(); 133 134 // |this| takes ownership of |tab_reloader|. 135 void SetTabReloaderForTest(CaptivePortalTabReloader* tab_reloader); 136 137 const content::RenderViewHost* provisional_render_view_host() const { 138 return provisional_render_view_host_; 139 } 140 141 CaptivePortalTabReloader* GetTabReloaderForTest(); 142 143 // Opens a login tab if the profile's active window doesn't have one already. 144 void OpenLoginTab(); 145 146 Profile* profile_; 147 148 // Neither of these will ever be NULL. 149 scoped_ptr<CaptivePortalTabReloader> tab_reloader_; 150 scoped_ptr<CaptivePortalLoginDetector> login_detector_; 151 152 content::WebContents* web_contents_; 153 154 // If a provisional load has failed, and the tab is loading an error page, the 155 // error code associated with the error page we're loading. 156 // net::OK, otherwise. 157 int pending_error_code_; 158 159 // The RenderViewHost with a provisional load, if any. Can either be 160 // the currently displayed RenderViewHost or a pending RenderViewHost for 161 // cross-process navitations. NULL when there's currently no provisional 162 // load. 163 content::RenderViewHost* provisional_render_view_host_; 164 165 content::NotificationRegistrar registrar_; 166 167 DISALLOW_COPY_AND_ASSIGN(CaptivePortalTabHelper); 168 }; 169 170 #endif // CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_TAB_HELPER_H_ 171