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