// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_ #define CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_ #pragma once #include <map> #include <string> #include <vector> #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/automation/automation_resource_message_filter.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/ui/views/frame/browser_bubble_host.h" #include "chrome/browser/ui/views/infobars/infobar_container.h" #include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" #include "content/browser/tab_contents/tab_contents_delegate.h" #include "content/common/navigation_types.h" #include "content/common/notification_observer.h" #include "content/common/notification_registrar.h" #include "views/accelerator.h" #include "views/widget/widget_win.h" class AutomationProvider; class Browser; class Profile; class TabContentsContainer; class TabContentsWrapper; class RenderViewContextMenuViews; struct NavigationInfo; namespace ui { class ViewProp; } // This class serves as the container window for an external tab. // An external tab is a Chrome tab that is meant to displayed in an // external process. This class provides the FocusManger needed by the // TabContents as well as an implementation of TabContentsDelegate. class ExternalTabContainer : public TabContentsDelegate, public NotificationObserver, public views::WidgetWin, public base::RefCounted<ExternalTabContainer>, public views::AcceleratorTarget, public InfoBarContainer::Delegate, public BrowserBubbleHost { public: typedef std::map<uintptr_t, scoped_refptr<ExternalTabContainer> > PendingTabs; ExternalTabContainer(AutomationProvider* automation, AutomationResourceMessageFilter* filter); TabContents* tab_contents() const; // Temporary hack so we can send notifications back void SetTabHandle(int handle); int tab_handle() const { return tab_handle_; } bool Init(Profile* profile, HWND parent, const gfx::Rect& bounds, DWORD style, bool load_requests_via_automation, bool handle_top_level_requests, TabContentsWrapper* existing_tab_contents, const GURL& initial_url, const GURL& referrer, bool infobars_enabled, bool supports_full_tab_mode); // Unhook the keystroke listener and notify about the closing TabContents. // This function gets called from three places, which is fine. // 1. OnFinalMessage // 2. In the destructor. // 3. In AutomationProvider::CreateExternalTab void Uninitialize(); // Used to reinitialize the automation channel and related information // for this container. Typically used when an ExternalTabContainer // instance is created by Chrome and attached to an automation client. bool Reinitialize(AutomationProvider* automation_provider, AutomationResourceMessageFilter* filter, gfx::NativeWindow parent_window); // This is invoked when the external host reflects back to us a keyboard // message it did not process void ProcessUnhandledAccelerator(const MSG& msg); // See TabContents::FocusThroughTabTraversal. Called from AutomationProvider. void FocusThroughTabTraversal(bool reverse, bool restore_focus_to_view); // A helper method that tests whether the given window is an // ExternalTabContainer window static bool IsExternalTabContainer(HWND window); // A helper function that returns a pointer to the ExternalTabContainer // instance associated with a native view. Returns NULL if the window // is not an ExternalTabContainer. static ExternalTabContainer* GetExternalContainerFromNativeWindow( gfx::NativeView native_window); // A helper method that retrieves the ExternalTabContainer object that // hosts the given tab window. static ExternalTabContainer* GetContainerForTab(HWND tab_window); // Overridden from TabContentsDelegate: virtual void OpenURLFromTab(TabContents* source, const GURL& url, const GURL& referrer, WindowOpenDisposition disposition, PageTransition::Type transition); virtual void NavigationStateChanged(const TabContents* source, unsigned changed_flags); virtual void AddNewContents(TabContents* source, TabContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture); virtual void ActivateContents(TabContents* contents); virtual void DeactivateContents(TabContents* contents); virtual void LoadingStateChanged(TabContents* source); virtual void CloseContents(TabContents* source); virtual void MoveContents(TabContents* source, const gfx::Rect& pos); virtual bool IsPopup(const TabContents* source) const; virtual void UpdateTargetURL(TabContents* source, const GURL& url); virtual void ContentsZoomChange(bool zoom_in); virtual void ForwardMessageToExternalHost(const std::string& message, const std::string& origin, const std::string& target); virtual bool IsExternalTabContainer() const; virtual gfx::NativeWindow GetFrameNativeWindow(); virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut); virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); virtual bool TakeFocus(bool reverse); virtual bool CanDownload(int request_id); virtual bool OnGoToEntryOffset(int offset); virtual void ShowPageInfo(Profile* profile, const GURL& url, const NavigationEntry::SSLStatus& ssl, bool show_history); // Handles the context menu display operation. This allows external // hosts to customize the menu. virtual bool HandleContextMenu(const ContextMenuParams& params); // Executes the context menu command identified by the command // parameter. virtual bool ExecuteContextMenuCommand(int command); // Show a dialog with HTML content. |delegate| contains a pointer to the // delegate who knows how to display the dialog (which file URL and JSON // string input to use during initialization). |parent_window| is the window // that should be parent of the dialog, or NULL for the default. virtual void ShowHtmlDialog(HtmlDialogUIDelegate* delegate, gfx::NativeWindow parent_window); virtual void BeforeUnloadFired(TabContents* tab, bool proceed, bool* proceed_to_fire_unload); void ShowRepostFormWarningDialog(TabContents* tab_contents); // Overriden from TabContentsDelegate::AutomationResourceRoutingDelegate virtual void RegisterRenderViewHost(RenderViewHost* render_view_host); virtual void UnregisterRenderViewHost(RenderViewHost* render_view_host); // Overridden from NotificationObserver: virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); // Returns the ExternalTabContainer instance associated with the cookie // passed in. It also erases the corresponding reference from the map. // Returns NULL if we fail to find the cookie in the map. static scoped_refptr<ExternalTabContainer> RemovePendingTab(uintptr_t cookie); // Overridden from views::WidgetWin: virtual views::Window* GetWindow(); // Handles the specified |accelerator| being pressed. bool AcceleratorPressed(const views::Accelerator& accelerator); bool pending() const { return pending_; } void set_pending(bool pending) { pending_ = pending; } void set_is_popup_window(bool is_popup_window) { is_popup_window_ = is_popup_window; } // InfoBarContainer::Delegate overrides virtual SkColor GetInfoBarSeparatorColor() const OVERRIDE; virtual void InfoBarContainerStateChanged(bool is_animating) OVERRIDE; virtual bool DrawInfoBarArrows(int* x) const OVERRIDE; virtual void TabContentsCreated(TabContents* new_contents); virtual bool infobars_enabled(); void RunUnloadHandlers(IPC::Message* reply_message); protected: ~ExternalTabContainer(); // Overridden from views::WidgetWin: virtual LRESULT OnCreate(LPCREATESTRUCT create_struct); virtual void OnDestroy(); virtual void OnFinalMessage(HWND window); bool InitNavigationInfo(NavigationInfo* nav_info, NavigationType::Type nav_type, int relative_offset); void Navigate(const GURL& url, const GURL& referrer); friend class base::RefCounted<ExternalTabContainer>; // Helper resource automation registration method, allowing registration of // pending RenderViewHosts. void RegisterRenderViewHostForAutomation(RenderViewHost* render_view_host, bool pending_view); // Top level navigations received for a tab while it is waiting for an ack // from the external host go here. Scenario is a window.open executes on a // page in ChromeFrame. A new TabContents is created and the current // ExternalTabContainer is notified via AddNewContents. At this point we // send off an attach tab request to the host browser. Before the host // browser sends over the ack, we receive a top level URL navigation for the // new tab, which needs to be routed over the correct automation channel. // We receive the automation channel only when the external host acks the // attach tab request. struct PendingTopLevelNavigation { GURL url; GURL referrer; WindowOpenDisposition disposition; PageTransition::Type transition; }; // Helper function for processing keystokes coming back from the renderer // process. bool ProcessUnhandledKeyStroke(HWND window, UINT message, WPARAM wparam, LPARAM lparam); void LoadAccelerators(); // Sends over pending Open URL requests to the external host. void ServicePendingOpenURLRequests(); // Scheduled as a task in ExternalTabContainer::Reinitialize void OnReinitialize(); // Creates and initializes the view hierarchy for this ExternalTabContainer. void SetupExternalTabView(); scoped_ptr<TabContentsWrapper> tab_contents_; scoped_refptr<AutomationProvider> automation_; NotificationRegistrar registrar_; // A view to handle focus cycling TabContentsContainer* tab_contents_container_; int tab_handle_; // A failed navigation like a 404 is followed in chrome with a success // navigation for the 404 page. We need to ignore the next navigation // to avoid confusing the clients of the external tab. This member variable // is set when we need to ignore the next load notification. bool ignore_next_load_notification_; scoped_ptr<RenderViewContextMenuViews> external_context_menu_; // A message filter to load resources via automation scoped_refptr<AutomationResourceMessageFilter> automation_resource_message_filter_; // If all the url requests for this tab are to be loaded via automation. bool load_requests_via_automation_; // whether top level URL requests are to be handled by the automation client. bool handle_top_level_requests_; // Scoped browser object for this ExternalTabContainer instance. scoped_ptr<Browser> browser_; // Contains ExternalTabContainers that have not been connected to as yet. static base::LazyInstance<PendingTabs> pending_tabs_; // Allows us to run tasks on the ExternalTabContainer instance which are // bound by its lifetime. ScopedRunnableMethodFactory<ExternalTabContainer> external_method_factory_; // The URL request context to be used for this tab. Can be NULL. scoped_refptr<ChromeURLRequestContextGetter> request_context_; UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; // A mapping between accelerators and commands. std::map<views::Accelerator, int> accelerator_table_; // Contains the list of URL requests which are pending waiting for an ack // from the external host. std::vector<PendingTopLevelNavigation> pending_open_url_requests_; // Set to true if the ExternalTabContainer instance is waiting for an ack // from the host. bool pending_; // Set to true if the ExternalTabContainer if infobars should be enabled. bool infobars_enabled_; views::FocusManager* focus_manager_; views::View* external_tab_view_; IPC::Message* unload_reply_message_; // set to true if the host needs to get notified of all top level navigations // in this page. This typically applies to hosts which would render the new // page without chrome frame. bool route_all_top_level_navigations_; scoped_ptr<ui::ViewProp> prop_; // if this tab is a popup bool is_popup_window_; DISALLOW_COPY_AND_ASSIGN(ExternalTabContainer); }; // This class is instantiated for handling requests to open popups for external // tabs hosted in browsers which need to be notified about all top level // navigations. An instance of this class is created for handling window.open // or link navigations with target blank, etc. class TemporaryPopupExternalTabContainer : public ExternalTabContainer { public: TemporaryPopupExternalTabContainer(AutomationProvider* automation, AutomationResourceMessageFilter* filter); virtual ~TemporaryPopupExternalTabContainer(); virtual bool OnGoToEntryOffset(int offset) { NOTREACHED(); return false; } virtual bool ProcessUnhandledKeyStroke(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { NOTREACHED(); return false; } virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) {} virtual void OpenURLFromTab(TabContents* source, const GURL& url, const GURL& referrer, WindowOpenDisposition disposition, PageTransition::Type transition); virtual void NavigationStateChanged(const TabContents* source, unsigned changed_flags) { NOTREACHED(); } virtual void CloseContents(TabContents* source) { NOTREACHED(); } virtual void UpdateTargetURL(TabContents* source, const GURL& url) { NOTREACHED(); } void ForwardMessageToExternalHost(const std::string& message, const std::string& origin, const std::string& target) { NOTREACHED(); } virtual bool TakeFocus(bool reverse) { NOTREACHED(); return false; } virtual bool HandleContextMenu(const ContextMenuParams& params) { NOTREACHED(); return false; } virtual void BeforeUnloadFired(TabContents* tab, bool proceed, bool* proceed_to_fire_unload) { NOTREACHED(); } }; #endif // CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_