Home | History | Annotate | Download | only in captive_portal
      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