| // Copyright (c) 2012 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/compiler_specific.h" |
| #include "base/lazy_instance.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "chrome/browser/automation/automation_resource_message_filter.h" |
| #include "chrome/browser/infobars/infobar_container.h" |
| #include "chrome/browser/net/chrome_url_request_context.h" |
| #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper_delegate.h" |
| #include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" |
| #include "content/public/browser/navigation_type.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| #include "content/public/browser/web_contents_delegate.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "ui/base/accelerators/accelerator.h" |
| #include "ui/views/widget/native_widget_win.h" |
| |
| class AutomationProvider; |
| class Browser; |
| class Profile; |
| class TabContentsContainer; |
| class TabContentsWrapper; |
| class RenderViewContextMenuViews; |
| struct NavigationInfo; |
| |
| namespace content { |
| class WebIntentsDispatcher; |
| } |
| |
| 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 content::WebContentsDelegate. |
| class ExternalTabContainer : public content::WebContentsDelegate, |
| public content::WebContentsObserver, |
| public content::NotificationObserver, |
| public views::NativeWidgetWin, |
| public base::RefCounted<ExternalTabContainer>, |
| public ui::AcceleratorTarget, |
| public InfoBarContainer::Delegate, |
| public BlockedContentTabHelperDelegate { |
| public: |
| typedef std::map<uintptr_t, scoped_refptr<ExternalTabContainer> > PendingTabs; |
| |
| ExternalTabContainer(AutomationProvider* automation, |
| AutomationResourceMessageFilter* filter); |
| |
| content::WebContents* web_contents() const; |
| TabContentsWrapper* tab_contents_wrapper() { return tab_contents_.get(); } |
| |
| // 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 content::WebContentsDelegate: |
| virtual content::WebContents* OpenURLFromTab( |
| content::WebContents* source, |
| const content::OpenURLParams& params) OVERRIDE; |
| virtual void NavigationStateChanged(const content::WebContents* source, |
| unsigned changed_flags) OVERRIDE; |
| virtual void AddNewContents(content::WebContents* source, |
| content::WebContents* new_contents, |
| WindowOpenDisposition disposition, |
| const gfx::Rect& initial_pos, |
| bool user_gesture) OVERRIDE; |
| virtual void CloseContents(content::WebContents* source) OVERRIDE; |
| virtual void MoveContents(content::WebContents* source, |
| const gfx::Rect& pos) OVERRIDE; |
| virtual bool IsPopupOrPanel( |
| const content::WebContents* source) const OVERRIDE; |
| virtual void UpdateTargetURL(content::WebContents* source, int32 page_id, |
| const GURL& url) OVERRIDE; |
| virtual void ContentsZoomChange(bool zoom_in) OVERRIDE; |
| virtual gfx::NativeWindow GetFrameNativeWindow() OVERRIDE; |
| virtual void WebContentsCreated(content::WebContents* source_contents, |
| int64 source_frame_id, |
| const GURL& target_url, |
| content::WebContents* new_contents) OVERRIDE; |
| virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, |
| bool* is_keyboard_shortcut) OVERRIDE; |
| virtual void HandleKeyboardEvent( |
| const NativeWebKeyboardEvent& event) OVERRIDE; |
| virtual bool TakeFocus(bool reverse) OVERRIDE; |
| virtual bool CanDownload(content::RenderViewHost* render_view_host, |
| int request_id, |
| const std::string& request_method) OVERRIDE; |
| virtual bool OnGoToEntryOffset(int offset) OVERRIDE; |
| virtual bool HandleContextMenu( |
| const content::ContextMenuParams& params) OVERRIDE; |
| virtual bool ExecuteContextMenuCommand(int command) OVERRIDE; |
| virtual void BeforeUnloadFired(content::WebContents* tab, |
| bool proceed, |
| bool* proceed_to_fire_unload) OVERRIDE; |
| virtual content::JavaScriptDialogCreator* |
| GetJavaScriptDialogCreator() OVERRIDE; |
| virtual void ShowRepostFormWarningDialog( |
| content::WebContents* source) OVERRIDE; |
| virtual void RunFileChooser( |
| content::WebContents* tab, |
| const content::FileChooserParams& params) OVERRIDE; |
| virtual void EnumerateDirectory(content::WebContents* tab, |
| int request_id, |
| const FilePath& path) OVERRIDE; |
| virtual void JSOutOfMemory(content::WebContents* tab); |
| virtual void RegisterProtocolHandler(content::WebContents* tab, |
| const std::string& protocol, |
| const GURL& url, |
| const string16& title) OVERRIDE; |
| virtual void RegisterIntentHandler(content::WebContents* tab, |
| const string16& action, |
| const string16& type, |
| const string16& href, |
| const string16& title, |
| const string16& disposition) OVERRIDE; |
| virtual void WebIntentDispatch( |
| content::WebContents* tab, |
| content::WebIntentsDispatcher* intents_dispatcher) OVERRIDE; |
| virtual void FindReply(content::WebContents* tab, |
| int request_id, |
| int number_of_matches, |
| const gfx::Rect& selection_rect, |
| int active_match_ordinal, |
| bool final_update) OVERRIDE; |
| virtual void CrashedPlugin(content::WebContents* tab, |
| const FilePath& plugin_path) OVERRIDE; |
| |
| void RegisterRenderViewHost(content::RenderViewHost* render_view_host); |
| void UnregisterRenderViewHost(content::RenderViewHost* render_view_host); |
| |
| // Overridden from content::WebContentsObserver: |
| virtual bool OnMessageReceived(const IPC::Message& message); |
| virtual void DidFailProvisionalLoad( |
| int64 frame_id, |
| bool is_main_frame, |
| const GURL& validated_url, |
| int error_code, |
| const string16& error_description) OVERRIDE; |
| |
| // Message handlers |
| void OnForwardMessageToExternalHost(const std::string& message, |
| const std::string& origin, |
| const std::string& target); |
| |
| // Overridden from content::NotificationObserver: |
| virtual void Observe(int type, |
| const content::NotificationSource& source, |
| const content::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); |
| |
| // ui::AcceleratorTarget |
| bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; |
| bool CanHandleAccelerators() const OVERRIDE; |
| |
| 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; |
| |
| void RunUnloadHandlers(IPC::Message* reply_message); |
| |
| // Overridden from BlockedContentTabHelperDelegate: |
| virtual TabContentsWrapper* GetConstrainingContentsWrapper( |
| TabContentsWrapper* source) OVERRIDE; |
| |
| protected: |
| ~ExternalTabContainer(); |
| // Overridden from views::NativeWidgetWin: |
| virtual LRESULT OnCreate(LPCREATESTRUCT create_struct); |
| virtual void OnDestroy(); |
| virtual void OnFinalMessage(HWND window); |
| |
| bool InitNavigationInfo(NavigationInfo* nav_info, |
| content::NavigationType 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( |
| content::RenderViewHost* render_view_host, |
| bool pending_view); |
| |
| // 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_; |
| |
| content::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_; |
| |
| // 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. |
| base::WeakPtrFactory<ExternalTabContainer> weak_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<ui::Accelerator, int> accelerator_table_; |
| |
| // 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. |
| // Contains the list of URL requests which are pending waiting for an ack |
| // from the external host. |
| std::vector<content::OpenURLParams> pending_open_url_requests_; |
| |
| // Set to true if the ExternalTabContainer instance is waiting for an ack |
| // from the host. |
| bool pending_; |
| |
| 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(int type, const content::NotificationSource& source, |
| const content::NotificationDetails& details) {} |
| |
| virtual content::WebContents* OpenURLFromTab( |
| content::WebContents* source, |
| const content::OpenURLParams& params) OVERRIDE; |
| |
| virtual void NavigationStateChanged(const content::WebContents* source, |
| unsigned changed_flags) { |
| NOTREACHED(); |
| } |
| |
| virtual void CloseContents(TabContents* source) { |
| NOTREACHED(); |
| } |
| |
| virtual void UpdateTargetURL(content::WebContents* source, int32 page_id, |
| 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 content::ContextMenuParams& params) { |
| NOTREACHED(); |
| return false; |
| } |
| |
| virtual void BeforeUnloadFired(content::WebContents* tab, bool proceed, |
| bool* proceed_to_fire_unload) { |
| NOTREACHED(); |
| } |
| }; |
| |
| #endif // CHROME_BROWSER_EXTERNAL_TAB_CONTAINER_WIN_H_ |