external_tab_container_win.h revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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_EXTERNAL_TAB_CONTAINER_WIN_H_
6#define CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_
7
8#include <vector>
9#include <map>
10#include "base/lazy_instance.h"
11#include "chrome/browser/automation/automation_resource_message_filter.h"
12#include "chrome/browser/automation/automation_profile_impl.h"
13#include "chrome/browser/browser.h"
14#include "chrome/browser/net/chrome_url_request_context.h"
15#include "chrome/browser/tab_contents/tab_contents_delegate.h"
16#include "chrome/browser/views/frame/browser_bubble_host.h"
17#include "chrome/browser/views/infobars/infobar_container.h"
18#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
19#include "chrome/common/navigation_types.h"
20#include "chrome/common/notification_observer.h"
21#include "chrome/common/notification_registrar.h"
22#include "views/accelerator.h"
23#include "views/widget/widget_win.h"
24
25class AutomationProvider;
26class Profile;
27class TabContentsContainer;
28class RenderViewContextMenuViews;
29
30namespace IPC {
31struct NavigationInfo;
32}
33
34// This class serves as the container window for an external tab.
35// An external tab is a Chrome tab that is meant to displayed in an
36// external process. This class provides the FocusManger needed by the
37// TabContents as well as an implementation of TabContentsDelagate.
38class ExternalTabContainer : public TabContentsDelegate,
39                             public NotificationObserver,
40                             public views::WidgetWin,
41                             public base::RefCounted<ExternalTabContainer>,
42                             public views::AcceleratorTarget,
43                             public InfoBarContainer::Delegate,
44                             public BrowserBubbleHost {
45 public:
46  typedef std::map<uintptr_t, scoped_refptr<ExternalTabContainer> > PendingTabs;
47
48  ExternalTabContainer(AutomationProvider* automation,
49      AutomationResourceMessageFilter* filter);
50
51  TabContents* tab_contents() const { return tab_contents_; }
52
53  // Temporary hack so we can send notifications back
54  void SetTabHandle(int handle);
55
56  int tab_handle() const {
57    return tab_handle_;
58  }
59
60  bool Init(Profile* profile,
61            HWND parent,
62            const gfx::Rect& bounds,
63            DWORD style,
64            bool load_requests_via_automation,
65            bool handle_top_level_requests,
66            TabContents* existing_tab_contents,
67            const GURL& initial_url,
68            const GURL& referrer,
69            bool infobars_enabled);
70
71  // Unhook the keystroke listener and notify about the closing TabContents.
72  // This function gets called from three places, which is fine.
73  // 1. OnFinalMessage
74  // 2. In the destructor.
75  // 3. In AutomationProvider::CreateExternalTab
76  void Uninitialize();
77
78  // Used to reinitialize the automation channel and related information
79  // for this container. Typically used when an ExternalTabContainer
80  // instance is created by Chrome and attached to an automation client.
81  bool Reinitialize(AutomationProvider* automation_provider,
82                    AutomationResourceMessageFilter* filter,
83                    gfx::NativeWindow parent_window);
84
85  // This is invoked when the external host reflects back to us a keyboard
86  // message it did not process
87  void ProcessUnhandledAccelerator(const MSG& msg);
88
89  // See TabContents::FocusThroughTabTraversal.  Called from AutomationProvider.
90  void FocusThroughTabTraversal(bool reverse, bool restore_focus_to_view);
91
92  // A helper method that tests whether the given window is an
93  // ExternalTabContainer window
94  static bool IsExternalTabContainer(HWND window);
95
96  // A helper function that returns a pointer to the ExternalTabContainer
97  // instance associated with a native view.  Returns NULL if the window
98  // is not an ExternalTabContainer.
99  static ExternalTabContainer* GetExternalContainerFromNativeWindow(
100      gfx::NativeView native_window);
101
102  // A helper method that retrieves the ExternalTabContainer object that
103  // hosts the given tab window.
104  static ExternalTabContainer* GetContainerForTab(HWND tab_window);
105
106  // Overridden from TabContentsDelegate:
107  virtual void OpenURLFromTab(TabContents* source,
108                              const GURL& url,
109                              const GURL& referrer,
110                              WindowOpenDisposition disposition,
111                              PageTransition::Type transition);
112  virtual void NavigationStateChanged(const TabContents* source,
113                                      unsigned changed_flags);
114  virtual void AddNewContents(TabContents* source,
115                              TabContents* new_contents,
116                              WindowOpenDisposition disposition,
117                              const gfx::Rect& initial_pos,
118                              bool user_gesture);
119  virtual void ActivateContents(TabContents* contents);
120  virtual void LoadingStateChanged(TabContents* source);
121  virtual void CloseContents(TabContents* source);
122  virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
123  virtual bool IsPopup(TabContents* source);
124  virtual void URLStarredChanged(TabContents* source, bool starred);
125  virtual void UpdateTargetURL(TabContents* source, const GURL& url);
126  virtual void ContentsZoomChange(bool zoom_in);
127  virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
128  virtual void ForwardMessageToExternalHost(const std::string& message,
129                                            const std::string& origin,
130                                            const std::string& target);
131  virtual bool IsExternalTabContainer() const {
132    return true;
133  };
134  virtual gfx::NativeWindow GetFrameNativeWindow();
135
136  virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
137                                      bool* is_keyboard_shortcut);
138  virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
139
140  virtual bool TakeFocus(bool reverse);
141
142  virtual bool CanDownload(int request_id);
143
144  virtual bool OnGoToEntryOffset(int offset);
145
146  virtual void ShowPageInfo(Profile* profile,
147                            const GURL& url,
148                            const NavigationEntry::SSLStatus& ssl,
149                            bool show_history);
150
151  virtual Browser* GetBrowser() { return browser_.get(); }
152
153  // Overriden from TabContentsDelegate::AutomationResourceRoutingDelegate
154  virtual void RegisterRenderViewHost(RenderViewHost* render_view_host);
155  virtual void UnregisterRenderViewHost(RenderViewHost* render_view_host);
156
157  // Overridden from NotificationObserver:
158  virtual void Observe(NotificationType type,
159                       const NotificationSource& source,
160                       const NotificationDetails& details);
161
162  // Handles the context menu display operation. This allows external
163  // hosts to customize the menu.
164  virtual bool HandleContextMenu(const ContextMenuParams& params);
165
166  // Executes the context menu command identified by the command
167  // parameter.
168  virtual bool ExecuteContextMenuCommand(int command);
169
170  // Show a dialog with HTML content. |delegate| contains a pointer to the
171  // delegate who knows how to display the dialog (which file URL and JSON
172  // string input to use during initialization). |parent_window| is the window
173  // that should be parent of the dialog, or NULL for the default.
174  virtual void ShowHtmlDialog(HtmlDialogUIDelegate* delegate,
175                              gfx::NativeWindow parent_window);
176
177  // Returns the ExternalTabContainer instance associated with the cookie
178  // passed in. It also erases the corresponding reference from the map.
179  // Returns NULL if we fail to find the cookie in the map.
180  static scoped_refptr<ExternalTabContainer> RemovePendingTab(uintptr_t cookie);
181
182  // Enables extension automation (for e.g. UITests), with the current tab
183  // used as a conduit for the extension API messages being handled by the
184  // automation client.
185  void SetEnableExtensionAutomation(
186      const std::vector<std::string>& functions_enabled);
187
188  // Overridden from views::WidgetWin:
189  virtual views::Window* GetWindow();
190
191  // Handles the specified |accelerator| being pressed.
192  bool AcceleratorPressed(const views::Accelerator& accelerator);
193
194  bool pending() const {
195    return pending_;
196  }
197
198  void set_pending(bool pending) {
199    pending_ = pending;
200  }
201
202  // InfoBarContainer::Delegate overrides
203  virtual void InfoBarSizeChanged(bool is_animating);
204
205  virtual void TabContentsCreated(TabContents* new_contents);
206
207  virtual bool infobars_enabled();
208
209  void RunUnloadHandlers(gfx::NativeWindow notification_window,
210                         int notification_message);
211
212 protected:
213  // Overridden from views::WidgetWin:
214  virtual LRESULT OnCreate(LPCREATESTRUCT create_struct);
215  virtual void OnDestroy();
216  virtual void OnFinalMessage(HWND window);
217
218  bool InitNavigationInfo(IPC::NavigationInfo* nav_info,
219                          NavigationType::Type nav_type,
220                          int relative_offset);
221  void Navigate(const GURL& url, const GURL& referrer);
222
223  // Initializes the request context to be used for automation HTTP requests.
224  void InitializeAutomationRequestContext(int tab_handle);
225
226 private:
227  friend class base::RefCounted<ExternalTabContainer>;
228
229  ~ExternalTabContainer();
230
231  // Helper resource automation registration method, allowing registration of
232  // pending RenderViewHosts.
233  void RegisterRenderViewHostForAutomation(RenderViewHost* render_view_host,
234                                           bool pending_view);
235
236  // Top level navigations received for a tab while it is waiting for an ack
237  // from the external host go here. Scenario is a window.open executes on a
238  // page in ChromeFrame. A new TabContents is created and the current
239  // ExternalTabContainer is notified via AddNewContents. At this point we
240  // send off an attach tab request to the host browser. Before the host
241  // browser sends over the ack, we receive a top level URL navigation for the
242  // new tab, which needs to be routed over the correct automation channel.
243  // We receive the automation channel only when the external host acks the
244  // attach tab request.
245  struct PendingTopLevelNavigation {
246    GURL url;
247    GURL referrer;
248    WindowOpenDisposition disposition;
249    PageTransition::Type transition;
250  };
251
252  // Helper function for processing keystokes coming back from the renderer
253  // process.
254  bool ProcessUnhandledKeyStroke(HWND window, UINT message, WPARAM wparam,
255                                 LPARAM lparam);
256
257  void LoadAccelerators();
258
259  // Sends over pending Open URL requests to the external host.
260  void ServicePendingOpenURLRequests();
261
262  // Scheduled as a task in ExternalTabContainer::Reinitialize
263  void OnReinitialize();
264
265  // Creates and initializes the view hierarchy for this ExternalTabContainer.
266  void SetupExternalTabView();
267
268  TabContents* tab_contents_;
269  scoped_refptr<AutomationProvider> automation_;
270
271  NotificationRegistrar registrar_;
272
273  // A view to handle focus cycling
274  TabContentsContainer* tab_contents_container_;
275
276  int tab_handle_;
277  // A failed navigation like a 404 is followed in chrome with a success
278  // navigation for the 404 page. We need to ignore the next navigation
279  // to avoid confusing the clients of the external tab. This member variable
280  // is set when we need to ignore the next load notification.
281  bool ignore_next_load_notification_;
282
283  scoped_ptr<RenderViewContextMenuViews> external_context_menu_;
284
285  // A message filter to load resources via automation
286  scoped_refptr<AutomationResourceMessageFilter>
287      automation_resource_message_filter_;
288
289  // If all the url requests for this tab are to be loaded via automation.
290  bool load_requests_via_automation_;
291
292  // whether top level URL requests are to be handled by the automation client.
293  bool handle_top_level_requests_;
294
295  // Scoped browser object for this ExternalTabContainer instance.
296  scoped_ptr<Browser> browser_;
297
298  // Contains ExternalTabContainers that have not been connected to as yet.
299  static base::LazyInstance<PendingTabs> pending_tabs_;
300
301  // True if this tab is currently the conduit for extension API automation.
302  bool enabled_extension_automation_;
303
304  // Allows us to run tasks on the ExternalTabContainer instance which are
305  // bound by its lifetime.
306  ScopedRunnableMethodFactory<ExternalTabContainer> external_method_factory_;
307
308  // The URL request context to be used for this tab. Can be NULL.
309  scoped_refptr<ChromeURLRequestContextGetter> request_context_;
310
311  UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
312
313  // A mapping between accelerators and commands.
314  std::map<views::Accelerator, int> accelerator_table_;
315
316  // Set to true if the tab is waiting for the unload event to complete.
317  bool waiting_for_unload_event_;
318
319  // Contains the list of URL requests which are pending waiting for an ack
320  // from the external host.
321  std::vector<PendingTopLevelNavigation> pending_open_url_requests_;
322
323  // Set to true if the ExternalTabContainer instance is waiting for an ack
324  // from the host.
325  bool pending_;
326
327  // Set to true if the ExternalTabContainer if infobars should be enabled.
328  bool infobars_enabled_;
329
330  views::FocusManager* focus_manager_;
331
332  views::View* external_tab_view_;
333
334  gfx::NativeWindow notification_window_;
335  int notification_message_;
336
337  DISALLOW_COPY_AND_ASSIGN(ExternalTabContainer);
338};
339
340#endif  // CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_
341