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