// Copyright (c) 2010 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_ #include #include #include "base/lazy_instance.h" #include "chrome/browser/automation/automation_resource_message_filter.h" #include "chrome/browser/automation/automation_profile_impl.h" #include "chrome/browser/browser.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/views/frame/browser_bubble_host.h" #include "chrome/browser/views/infobars/infobar_container.h" #include "chrome/browser/views/unhandled_keyboard_event_handler.h" #include "chrome/common/navigation_types.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "views/accelerator.h" #include "views/widget/widget_win.h" class AutomationProvider; class Profile; class TabContentsContainer; class RenderViewContextMenuViews; namespace IPC { struct NavigationInfo; } // 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 TabContentsDelagate. class ExternalTabContainer : public TabContentsDelegate, public NotificationObserver, public views::WidgetWin, public base::RefCounted, public views::AcceleratorTarget, public InfoBarContainer::Delegate, public BrowserBubbleHost { public: typedef std::map > PendingTabs; ExternalTabContainer(AutomationProvider* automation, AutomationResourceMessageFilter* filter); TabContents* tab_contents() const { return tab_contents_; } // 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, TabContents* existing_tab_contents, const GURL& initial_url, const GURL& referrer, bool infobars_enabled); // 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 LoadingStateChanged(TabContents* source); virtual void CloseContents(TabContents* source); virtual void MoveContents(TabContents* source, const gfx::Rect& pos); virtual bool IsPopup(TabContents* source); virtual void URLStarredChanged(TabContents* source, bool starred); virtual void UpdateTargetURL(TabContents* source, const GURL& url); virtual void ContentsZoomChange(bool zoom_in); virtual void ToolbarSizeChanged(TabContents* source, bool is_animating); virtual void ForwardMessageToExternalHost(const std::string& message, const std::string& origin, const std::string& target); virtual bool IsExternalTabContainer() const { return true; }; 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); virtual Browser* GetBrowser() { return browser_.get(); } // 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); // 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); // 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 RemovePendingTab(uintptr_t cookie); // Enables extension automation (for e.g. UITests), with the current tab // used as a conduit for the extension API messages being handled by the // automation client. void SetEnableExtensionAutomation( const std::vector& functions_enabled); // 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; } // InfoBarContainer::Delegate overrides virtual void InfoBarSizeChanged(bool is_animating); virtual void TabContentsCreated(TabContents* new_contents); virtual bool infobars_enabled(); protected: // Overridden from views::WidgetWin: virtual LRESULT OnCreate(LPCREATESTRUCT create_struct); virtual void OnDestroy(); virtual void OnFinalMessage(HWND window); bool InitNavigationInfo(IPC::NavigationInfo* nav_info, NavigationType::Type nav_type, int relative_offset); void Navigate(const GURL& url, const GURL& referrer); // Initializes the request context to be used for automation HTTP requests. void InitializeAutomationRequestContext(int tab_handle); private: 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(); TabContents* tab_contents_; scoped_refptr 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 external_context_menu_; // A message filter to load resources via automation scoped_refptr 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_; // Contains ExternalTabContainers that have not been connected to as yet. static base::LazyInstance pending_tabs_; // True if this tab is currently the conduit for extension API automation. bool enabled_extension_automation_; // Allows us to run tasks on the ExternalTabContainer instance which are // bound by its lifetime. ScopedRunnableMethodFactory external_method_factory_; // The URL request context to be used for this tab. Can be NULL. scoped_refptr request_context_; UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; // A mapping between accelerators and commands. std::map accelerator_table_; // Set to true if the tab is waiting for the unload event to complete. bool waiting_for_unload_event_; // Pointer to the innermost ExternalTabContainer instance which is waiting // for the unload event listeners to finish. // Used to maintain a local global stack of containers. static ExternalTabContainer* innermost_tab_for_unload_event_; // Contains the list of URL requests which are pending waiting for an ack // from the external host. std::vector 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_; DISALLOW_COPY_AND_ASSIGN(ExternalTabContainer); }; #endif // CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_