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