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