Home | History | Annotate | Download | only in web_navigation
      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 // Defines the Chrome Extensions WebNavigation API functions for observing and
      6 // intercepting navigation events, as specified in the extension JSON API.
      7 
      8 #ifndef CHROME_BROWSER_EXTENSIONS_API_WEB_NAVIGATION_WEB_NAVIGATION_API_H_
      9 #define CHROME_BROWSER_EXTENSIONS_API_WEB_NAVIGATION_WEB_NAVIGATION_API_H_
     10 
     11 #include <map>
     12 #include <set>
     13 
     14 #include "base/compiler_specific.h"
     15 #include "chrome/browser/extensions/api/web_navigation/frame_navigation_state.h"
     16 #include "chrome/browser/extensions/chrome_extension_function.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/ui/browser_list_observer.h"
     19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     20 #include "content/public/browser/notification_observer.h"
     21 #include "content/public/browser/notification_registrar.h"
     22 #include "content/public/browser/web_contents_observer.h"
     23 #include "content/public/browser/web_contents_user_data.h"
     24 #include "extensions/browser/browser_context_keyed_api_factory.h"
     25 #include "extensions/browser/event_router.h"
     26 #include "url/gurl.h"
     27 
     28 struct RetargetingDetails;
     29 
     30 namespace extensions {
     31 
     32 // Tab contents observer that forwards navigation events to the event router.
     33 class WebNavigationTabObserver
     34     : public content::NotificationObserver,
     35       public content::WebContentsObserver,
     36       public content::WebContentsUserData<WebNavigationTabObserver> {
     37  public:
     38   virtual ~WebNavigationTabObserver();
     39 
     40   // Returns the object for the given |web_contents|.
     41   static WebNavigationTabObserver* Get(content::WebContents* web_contents);
     42 
     43   const FrameNavigationState& frame_navigation_state() const {
     44     return navigation_state_;
     45   }
     46 
     47   content::RenderViewHost* GetRenderViewHostInProcess(int process_id) const;
     48 
     49   // content::NotificationObserver implementation.
     50   virtual void Observe(int type,
     51                        const content::NotificationSource& source,
     52                        const content::NotificationDetails& details) OVERRIDE;
     53 
     54   // content::WebContentsObserver implementation.
     55   virtual void RenderViewDeleted(
     56       content::RenderViewHost* render_view_host) OVERRIDE;
     57   virtual void AboutToNavigateRenderView(
     58       content::RenderViewHost* render_view_host) OVERRIDE;
     59   virtual void DidStartProvisionalLoadForFrame(
     60       int64 frame_num,
     61       int64 parent_frame_num,
     62       bool is_main_frame,
     63       const GURL& validated_url,
     64       bool is_error_page,
     65       bool is_iframe_srcdoc,
     66       content::RenderViewHost* render_view_host) OVERRIDE;
     67   virtual void DidCommitProvisionalLoadForFrame(
     68       int64 frame_num,
     69       const base::string16& frame_unique_name,
     70       bool is_main_frame,
     71       const GURL& url,
     72       content::PageTransition transition_type,
     73       content::RenderViewHost* render_view_host) OVERRIDE;
     74   virtual void DidFailProvisionalLoad(
     75       int64 frame_num,
     76       const base::string16& frame_unique_name,
     77       bool is_main_frame,
     78       const GURL& validated_url,
     79       int error_code,
     80       const base::string16& error_description,
     81       content::RenderViewHost* render_view_host) OVERRIDE;
     82   virtual void DocumentLoadedInFrame(
     83       int64 frame_num,
     84       content::RenderViewHost* render_view_host) OVERRIDE;
     85   virtual void DidFinishLoad(
     86       int64 frame_num,
     87       const GURL& validated_url,
     88       bool is_main_frame,
     89       content::RenderViewHost* render_view_host) OVERRIDE;
     90   virtual void DidFailLoad(
     91       int64 frame_num,
     92       const GURL& validated_url,
     93       bool is_main_frame,
     94       int error_code,
     95       const base::string16& error_description,
     96       content::RenderViewHost* render_view_host) OVERRIDE;
     97   virtual void DidGetRedirectForResourceRequest(
     98       content::RenderViewHost* render_view_host,
     99       const content::ResourceRedirectDetails& details) OVERRIDE;
    100   virtual void DidOpenRequestedURL(content::WebContents* new_contents,
    101                                    const GURL& url,
    102                                    const content::Referrer& referrer,
    103                                    WindowOpenDisposition disposition,
    104                                    content::PageTransition transition,
    105                                    int64 source_frame_num) OVERRIDE;
    106   virtual void FrameDetached(content::RenderViewHost* render_view_host,
    107                              int64 frame_num) OVERRIDE;
    108   virtual void WebContentsDestroyed() OVERRIDE;
    109 
    110  private:
    111   explicit WebNavigationTabObserver(content::WebContents* web_contents);
    112   friend class content::WebContentsUserData<WebNavigationTabObserver>;
    113 
    114   // True if the transition and target url correspond to a reference fragment
    115   // navigation.
    116   bool IsReferenceFragmentNavigation(FrameNavigationState::FrameID frame_id,
    117                                      const GURL& url);
    118 
    119   // Creates and sends onErrorOccurred events for all on-going navigations. If
    120   // |render_view_host| is non-NULL, only generates events for frames in this
    121   // render view host. If |id_to_skip| is given, no events are sent for that
    122   // frame.
    123   void SendErrorEvents(content::WebContents* web_contents,
    124                        content::RenderViewHost* render_view_host,
    125                        FrameNavigationState::FrameID id_to_skip);
    126 
    127   // Tracks the state of the frames we are sending events for.
    128   FrameNavigationState navigation_state_;
    129 
    130   // Used for tracking registrations to redirect notifications.
    131   content::NotificationRegistrar registrar_;
    132 
    133   // The current RenderViewHost of the observed WebContents.
    134   content::RenderViewHost* render_view_host_;
    135 
    136   // During a cross site navigation, the WebContents has a second, pending
    137   // RenderViewHost.
    138   content::RenderViewHost* pending_render_view_host_;
    139 
    140   DISALLOW_COPY_AND_ASSIGN(WebNavigationTabObserver);
    141 };
    142 
    143 // Observes navigation notifications and routes them as events to the extension
    144 // system.
    145 class WebNavigationEventRouter : public TabStripModelObserver,
    146                                  public chrome::BrowserListObserver,
    147                                  public content::NotificationObserver {
    148  public:
    149   explicit WebNavigationEventRouter(Profile* profile);
    150   virtual ~WebNavigationEventRouter();
    151 
    152  private:
    153   // Used to cache the information about newly created WebContents objects.
    154   struct PendingWebContents{
    155     PendingWebContents();
    156     PendingWebContents(content::WebContents* source_web_contents,
    157                        int64 source_frame_id,
    158                        bool source_frame_is_main_frame,
    159                        content::WebContents* target_web_contents,
    160                        const GURL& target_url);
    161     ~PendingWebContents();
    162 
    163     content::WebContents* source_web_contents;
    164     int64 source_frame_id;
    165     bool source_frame_is_main_frame;
    166     content::WebContents* target_web_contents;
    167     GURL target_url;
    168   };
    169 
    170   // TabStripModelObserver implementation.
    171   virtual void TabReplacedAt(TabStripModel* tab_strip_model,
    172                              content::WebContents* old_contents,
    173                              content::WebContents* new_contents,
    174                              int index) OVERRIDE;
    175 
    176   // chrome::BrowserListObserver implementation.
    177   virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
    178   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
    179 
    180   // content::NotificationObserver implementation.
    181   virtual void Observe(int type,
    182                        const content::NotificationSource& source,
    183                        const content::NotificationDetails& details) OVERRIDE;
    184 
    185   // Handler for the NOTIFICATION_RETARGETING event. The method takes the
    186   // details of such an event and stores them for the later
    187   // NOTIFICATION_TAB_ADDED event.
    188   void Retargeting(const RetargetingDetails* details);
    189 
    190   // Handler for the NOTIFICATION_TAB_ADDED event. The method takes the details
    191   // of such an event and creates a JSON formated extension event from it.
    192   void TabAdded(content::WebContents* tab);
    193 
    194   // Handler for NOTIFICATION_WEB_CONTENTS_DESTROYED. If |tab| is in
    195   // |pending_web_contents_|, it is removed.
    196   void TabDestroyed(content::WebContents* tab);
    197 
    198   // Mapping pointers to WebContents objects to information about how they got
    199   // created.
    200   std::map<content::WebContents*, PendingWebContents> pending_web_contents_;
    201 
    202   // Used for tracking registrations to navigation notifications.
    203   content::NotificationRegistrar registrar_;
    204 
    205   // The profile that owns us via ExtensionService.
    206   Profile* profile_;
    207 
    208   DISALLOW_COPY_AND_ASSIGN(WebNavigationEventRouter);
    209 };
    210 
    211 // API function that returns the state of a given frame.
    212 class WebNavigationGetFrameFunction : public ChromeSyncExtensionFunction {
    213   virtual ~WebNavigationGetFrameFunction() {}
    214   virtual bool RunSync() OVERRIDE;
    215   DECLARE_EXTENSION_FUNCTION("webNavigation.getFrame", WEBNAVIGATION_GETFRAME)
    216 };
    217 
    218 // API function that returns the states of all frames in a given tab.
    219 class WebNavigationGetAllFramesFunction : public ChromeSyncExtensionFunction {
    220   virtual ~WebNavigationGetAllFramesFunction() {}
    221   virtual bool RunSync() OVERRIDE;
    222   DECLARE_EXTENSION_FUNCTION("webNavigation.getAllFrames",
    223                              WEBNAVIGATION_GETALLFRAMES)
    224 };
    225 
    226 class WebNavigationAPI : public BrowserContextKeyedAPI,
    227                          public extensions::EventRouter::Observer {
    228  public:
    229   explicit WebNavigationAPI(content::BrowserContext* context);
    230   virtual ~WebNavigationAPI();
    231 
    232   // KeyedService implementation.
    233   virtual void Shutdown() OVERRIDE;
    234 
    235   // BrowserContextKeyedAPI implementation.
    236   static BrowserContextKeyedAPIFactory<WebNavigationAPI>* GetFactoryInstance();
    237 
    238   // EventRouter::Observer implementation.
    239   virtual void OnListenerAdded(const extensions::EventListenerInfo& details)
    240       OVERRIDE;
    241 
    242  private:
    243   friend class BrowserContextKeyedAPIFactory<WebNavigationAPI>;
    244 
    245   content::BrowserContext* browser_context_;
    246 
    247   // BrowserContextKeyedAPI implementation.
    248   static const char* service_name() {
    249     return "WebNavigationAPI";
    250   }
    251   static const bool kServiceIsNULLWhileTesting = true;
    252 
    253   // Created lazily upon OnListenerAdded.
    254   scoped_ptr<WebNavigationEventRouter> web_navigation_event_router_;
    255 
    256   DISALLOW_COPY_AND_ASSIGN(WebNavigationAPI);
    257 };
    258 
    259 }  // namespace extensions
    260 
    261 #endif  // CHROME_BROWSER_EXTENSIONS_API_WEB_NAVIGATION_WEB_NAVIGATION_API_H_
    262