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