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