blob: 7c9d7b39cd02cc6af11b59500badb97dfb528e02 [file] [log] [blame]
[email protected]9e790bd2011-01-10 23:48:541// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]4bdde602010-06-16 03:17:355#include "chrome/browser/external_tab_container_win.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]4c540ee2009-07-07 17:15:557#include <string>
8
[email protected]58580352010-10-26 04:07:509#include "base/debug/trace_event.h"
[email protected]7cf1b6ce2010-03-20 06:37:0110#include "base/i18n/rtl.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/logging.h"
[email protected]944b4212010-12-14 00:00:3312#include "base/utf_string_conversions.h"
[email protected]a8e20582010-12-31 17:18:5013#include "base/win/win_util.h"
[email protected]1a3aba82010-11-08 23:52:5414#include "chrome/app/chrome_command_ids.h"
[email protected]0f8df8672010-11-09 00:36:3215#include "chrome/app/chrome_dll_resource.h"
[email protected]b3841c502011-03-09 01:21:3116#include "chrome/browser/automation/automation_provider.h"
[email protected]52933842009-09-29 03:44:0617#include "chrome/browser/debugger/devtools_manager.h"
[email protected]2a8a98122010-07-16 11:58:4818#include "chrome/browser/debugger/devtools_toggle_action.h"
[email protected]91a79232010-11-10 18:15:0819#include "chrome/browser/google/google_util.h"
[email protected]ec0b6c42010-08-26 03:16:5820#include "chrome/browser/history/history_types.h"
[email protected]33ee8da2009-04-16 17:45:3721#include "chrome/browser/load_notification_details.h"
[email protected]21e302e2009-09-12 23:10:4122#include "chrome/browser/page_info_window.h"
[email protected]8ecad5e2010-12-02 21:18:3323#include "chrome/browser/profiles/profile.h"
[email protected]a8c229cc2011-01-13 22:31:5824#include "chrome/browser/ui/browser.h"
[email protected]00070c732011-04-09 15:31:3325#include "chrome/browser/ui/browser_window.h"
[email protected]ddb85052011-05-18 14:40:2726#include "chrome/browser/ui/download/download_tab_helper.h"
[email protected]7b8d4a22011-02-10 20:57:5427#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
[email protected]9e790bd2011-01-10 23:48:5428#include "chrome/browser/ui/views/browser_dialogs.h"
[email protected]6c6614f12011-03-31 18:51:4229#include "chrome/browser/ui/views/infobars/infobar_container_view.h"
[email protected]9e790bd2011-01-10 23:48:5430#include "chrome/browser/ui/views/page_info_bubble_view.h"
31#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
32#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
[email protected]a8ba6362010-11-10 20:02:2533#include "chrome/common/automation_messages.h"
initial.commit09911bf2008-07-26 23:55:2934#include "chrome/common/chrome_constants.h"
[email protected]15b2c6a2011-05-16 23:54:4035#include "chrome/common/render_messages.h"
[email protected]91a79232010-11-10 18:15:0836#include "chrome/common/url_constants.h"
[email protected]5de634712011-03-02 00:20:1937#include "content/browser/renderer_host/render_process_host.h"
38#include "content/browser/renderer_host/render_view_host.h"
39#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
[email protected]299425b2011-03-02 07:45:2040#include "content/browser/tab_contents/provisional_load_details.h"
[email protected]9966325b2011-04-18 05:00:1041#include "content/common/bindings_policy.h"
[email protected]4dd57932011-03-17 06:06:1242#include "content/common/native_web_keyboard_event.h"
[email protected]b3841c502011-03-09 01:21:3143#include "content/common/notification_service.h"
[email protected]4dd57932011-03-17 06:06:1244#include "content/common/page_transition_types.h"
[email protected]216813952011-05-19 22:21:2645#include "content/common/page_zoom.h"
[email protected]0aed2f52011-03-23 18:06:3646#include "content/common/view_messages.h"
[email protected]e943d6662009-06-12 03:50:3947#include "grit/generated_resources.h"
[email protected]0b7a012d2010-10-19 23:49:2648#include "grit/locale_settings.h"
[email protected]c051a1b2011-01-21 23:30:1749#include "ui/base/l10n/l10n_util.h"
[email protected]9ac174e92011-04-16 00:58:5650#include "ui/base/resource/resource_bundle.h"
[email protected]9dd7e3d72011-01-20 18:27:0651#include "ui/base/view_prop.h"
[email protected]9ef7d4b2011-01-27 02:17:2152#include "views/layout/grid_layout.h"
[email protected]ab861b42010-02-05 19:13:4453#include "views/widget/root_view.h"
[email protected]21e302e2009-09-12 23:10:4154#include "views/window/window.h"
[email protected]e943d6662009-06-12 03:50:3955
[email protected]9dd7e3d72011-01-20 18:27:0656using ui::ViewProp;
[email protected]3b8a7f8e2010-11-21 22:44:2157
58static const char kWindowObjectKey[] = "ChromeWindowObject";
initial.commit09911bf2008-07-26 23:55:2959
[email protected]5168c72c2011-04-25 17:30:2360// This class overrides the LinkClicked function in the PageInfoBubbleView
[email protected]0b7a012d2010-10-19 23:49:2661// class and routes the help center link navigation to the host browser.
62class ExternalTabPageInfoBubbleView : public PageInfoBubbleView {
63 public:
64 ExternalTabPageInfoBubbleView(ExternalTabContainer* container,
65 gfx::NativeWindow parent_window,
66 Profile* profile,
67 const GURL& url,
68 const NavigationEntry::SSLStatus& ssl,
69 bool show_history)
70 : PageInfoBubbleView(parent_window, profile, url, ssl, show_history),
71 container_(container) {
[email protected]5044da82010-10-27 01:09:1672 DVLOG(1) << __FUNCTION__;
[email protected]0b7a012d2010-10-19 23:49:2673 }
74 virtual ~ExternalTabPageInfoBubbleView() {
[email protected]5044da82010-10-27 01:09:1675 DVLOG(1) << __FUNCTION__;
[email protected]0b7a012d2010-10-19 23:49:2676 }
[email protected]5168c72c2011-04-25 17:30:2377 // LinkListener methods:
78 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE {
[email protected]91a79232010-11-10 18:15:0879 GURL url = google_util::AppendGoogleLocaleParam(
80 GURL(chrome::kPageInfoHelpCenterURL));
[email protected]0b7a012d2010-10-19 23:49:2681 container_->OpenURLFromTab(container_->tab_contents(), url, GURL(),
82 NEW_FOREGROUND_TAB, PageTransition::LINK);
83 }
84 private:
85 scoped_refptr<ExternalTabContainer> container_;
86};
87
[email protected]d0ed50d2010-06-22 01:01:3288base::LazyInstance<ExternalTabContainer::PendingTabs>
89 ExternalTabContainer::pending_tabs_(base::LINKER_INITIALIZED);
90
initial.commit09911bf2008-07-26 23:55:2991ExternalTabContainer::ExternalTabContainer(
[email protected]2e4633c2009-07-09 16:58:0692 AutomationProvider* automation, AutomationResourceMessageFilter* filter)
[email protected]2fc66722011-05-19 14:43:1293 : views::NativeWidgetWin(new views::Widget),
[email protected]9a56a0d2011-05-13 19:03:3194 automation_(automation),
[email protected]2e39d2e2009-02-19 18:41:3195 tab_contents_container_(NULL),
[email protected]15b2c6a2011-05-16 23:54:4096 ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_registrar_(this)),
[email protected]eac83f02009-05-08 18:44:4497 tab_handle_(0),
[email protected]2e4633c2009-07-09 16:58:0698 ignore_next_load_notification_(false),
99 automation_resource_message_filter_(filter),
[email protected]a50a4902009-08-14 22:39:01100 load_requests_via_automation_(false),
[email protected]24f98bba2009-10-14 18:47:49101 handle_top_level_requests_(false),
[email protected]4cfc1d922009-11-08 14:02:58102 external_method_factory_(this),
[email protected]f7019302010-03-26 19:58:32103 pending_(false),
[email protected]ba67fd82010-07-09 18:30:31104 focus_manager_(NULL),
[email protected]1f71d5882010-07-15 20:39:07105 external_tab_view_(NULL),
[email protected]9eeb35e2010-09-30 21:38:50106 unload_reply_message_(NULL),
[email protected]326d3b72011-03-29 20:38:24107 route_all_top_level_navigations_(false),
108 is_popup_window_(false) {
initial.commit09911bf2008-07-26 23:55:29109}
110
111ExternalTabContainer::~ExternalTabContainer() {
[email protected]632fbb12009-09-06 15:27:14112 Uninitialize();
initial.commit09911bf2008-07-26 23:55:29113}
114
[email protected]7b8d4a22011-02-10 20:57:54115TabContents* ExternalTabContainer::tab_contents() const {
116 return tab_contents_.get() ? tab_contents_->tab_contents() : NULL;
117}
118
[email protected]9095e982009-05-27 17:28:24119bool ExternalTabContainer::Init(Profile* profile,
120 HWND parent,
121 const gfx::Rect& bounds,
[email protected]95c3c592009-07-14 22:09:03122 DWORD style,
[email protected]5f450e52009-07-28 13:28:11123 bool load_requests_via_automation,
[email protected]a50a4902009-08-14 22:39:01124 bool handle_top_level_requests,
[email protected]7b8d4a22011-02-10 20:57:54125 TabContentsWrapper* existing_contents,
[email protected]7de487c2009-12-18 21:07:53126 const GURL& initial_url,
[email protected]f7019302010-03-26 19:58:32127 const GURL& referrer,
[email protected]9eeb35e2010-09-30 21:38:50128 bool infobars_enabled,
129 bool route_all_top_level_navigations) {
initial.commit09911bf2008-07-26 23:55:29130 if (IsWindow()) {
131 NOTREACHED();
132 return false;
133 }
[email protected]0498f7f82009-02-24 03:04:12134
[email protected]95c3c592009-07-14 22:09:03135 load_requests_via_automation_ = load_requests_via_automation;
[email protected]a50a4902009-08-14 22:39:01136 handle_top_level_requests_ = handle_top_level_requests;
[email protected]9eeb35e2010-09-30 21:38:50137 route_all_top_level_navigations_ = route_all_top_level_navigations;
[email protected]95c3c592009-07-14 22:09:03138
[email protected]6603fe92009-08-05 17:05:57139 set_window_style(WS_POPUP | WS_CLIPCHILDREN);
[email protected]af1fde02011-04-26 17:43:05140
[email protected]243d16c2011-04-26 19:31:24141 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
[email protected]af1fde02011-04-26 17:43:05142 params.bounds = bounds;
[email protected]9a56a0d2011-05-13 19:03:31143 params.native_widget = this;
[email protected]af1fde02011-04-26 17:43:05144 GetWidget()->Init(params);
[email protected]08ed00a2009-05-28 20:48:14145 if (!IsWindow()) {
146 NOTREACHED();
147 return false;
148 }
[email protected]f5cde2b2009-09-11 22:33:58149
[email protected]82166b62009-06-30 18:48:00150 // TODO(jcampan): limit focus traversal to contents.
initial.commit09911bf2008-07-26 23:55:29151
[email protected]3b8a7f8e2010-11-21 22:44:21152 prop_.reset(new ViewProp(GetNativeView(), kWindowObjectKey, this));
initial.commit09911bf2008-07-26 23:55:29153
[email protected]632fbb12009-09-06 15:27:14154 if (existing_contents) {
[email protected]7b8d4a22011-02-10 20:57:54155 tab_contents_.reset(existing_contents);
[email protected]632fbb12009-09-06 15:27:14156 tab_contents_->controller().set_profile(profile);
157 } else {
[email protected]7b8d4a22011-02-10 20:57:54158 TabContents* new_contents = new TabContents(profile, NULL, MSG_ROUTING_NONE,
159 NULL, NULL);
160 tab_contents_.reset(new TabContentsWrapper(new_contents));
[email protected]632fbb12009-09-06 15:27:14161 }
[email protected]a50a4902009-08-14 22:39:01162
[email protected]7abc95292011-05-18 00:18:09163 if (!infobars_enabled)
164 tab_contents_->set_infobars_enabled(false);
165
[email protected]7b8d4a22011-02-10 20:57:54166 tab_contents_->tab_contents()->set_delegate(this);
[email protected]ddb85052011-05-18 14:40:27167 tab_contents_->download_tab_helper()->set_delegate(this);
[email protected]632fbb12009-09-06 15:27:14168
[email protected]7b8d4a22011-02-10 20:57:54169 tab_contents_->tab_contents()->
170 GetMutableRendererPrefs()->browser_handles_top_level_requests =
171 handle_top_level_requests;
[email protected]a50a4902009-08-14 22:39:01172
173 if (!existing_contents) {
174 tab_contents_->render_view_host()->AllowBindings(
175 BindingsPolicy::EXTERNAL_HOST);
176 }
[email protected]18cb2572008-08-21 20:34:45177
[email protected]ce3fa3c2009-04-20 19:55:57178 NavigationController* controller = &tab_contents_->controller();
[email protected]bfd04a62009-02-01 18:16:56179 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]0e8db942008-09-24 21:21:48180 Source<NavigationController>(controller));
[email protected]2e39d2e2009-02-19 18:41:31181 registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
182 Source<NavigationController>(controller));
[email protected]33ee8da2009-04-16 17:45:37183 registrar_.Add(this, NotificationType::LOAD_STOP,
184 Source<NavigationController>(controller));
[email protected]2e4633c2009-07-09 16:58:06185 registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
[email protected]7b8d4a22011-02-10 20:57:54186 Source<TabContents>(tab_contents_->tab_contents()));
[email protected]2e4633c2009-07-09 16:58:06187 registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
[email protected]6b5b0cd2011-03-31 21:11:41188 NotificationService::AllSources());
[email protected]2e4633c2009-07-09 16:58:06189
[email protected]bfd04a62009-02-01 18:16:56190 NotificationService::current()->Notify(
191 NotificationType::EXTERNAL_TAB_CREATED,
192 Source<NavigationController>(controller),
193 NotificationService::NoDetails());
[email protected]31fb110522009-01-28 21:50:39194
[email protected]15b2c6a2011-05-16 23:54:40195 tab_contents_registrar_.Observe(tab_contents_->tab_contents());
196
[email protected]f5cde2b2009-09-11 22:33:58197 // Start loading initial URL
198 if (!initial_url.is_empty()) {
199 // Navigate out of context since we don't have a 'tab_handle_' yet.
[email protected]24f98bba2009-10-14 18:47:49200 MessageLoop::current()->PostTask(
201 FROM_HERE,
202 external_method_factory_.NewRunnableMethod(
[email protected]7de487c2009-12-18 21:07:53203 &ExternalTabContainer::Navigate, initial_url, referrer));
[email protected]f5cde2b2009-09-11 22:33:58204 }
205
[email protected]0498f7f82009-02-24 03:04:12206 // We need WS_POPUP to be on the window during initialization, but
207 // once initialized we apply the requested style which may or may not
208 // include the popup bit.
209 // Note that it's important to do this before we call SetParent since
210 // during the SetParent call we will otherwise get a WA_ACTIVATE call
211 // that causes us to steal the current focus.
[email protected]9095e982009-05-27 17:28:24212 SetWindowLong(GWL_STYLE, (GetWindowLong(GWL_STYLE) & ~WS_POPUP) | style);
[email protected]0498f7f82009-02-24 03:04:12213
[email protected]31fb110522009-01-28 21:50:39214 // Now apply the parenting and style
215 if (parent)
[email protected]9095e982009-05-27 17:28:24216 SetParent(GetNativeView(), parent);
[email protected]7e503122009-02-04 21:52:48217
[email protected]7b8d4a22011-02-10 20:57:54218 ::ShowWindow(tab_contents_->tab_contents()->GetNativeView(), SW_SHOWNA);
[email protected]e943d6662009-06-12 03:50:39219
[email protected]3f70c1e12010-01-12 20:38:49220 LoadAccelerators();
[email protected]ab861b42010-02-05 19:13:44221 SetupExternalTabView();
initial.commit09911bf2008-07-26 23:55:29222 return true;
223}
224
[email protected]632fbb12009-09-06 15:27:14225void ExternalTabContainer::Uninitialize() {
226 registrar_.RemoveAll();
[email protected]7b8d4a22011-02-10 20:57:54227 if (tab_contents_.get()) {
[email protected]39ec12f2011-03-25 23:02:28228 UnregisterRenderViewHost(tab_contents_->render_view_host());
[email protected]52933842009-09-29 03:44:06229
[email protected]9a56a0d2011-05-13 19:03:31230 if (GetWidget()->GetRootView())
231 GetWidget()->GetRootView()->RemoveAllChildViews(true);
[email protected]482a2d92011-02-10 00:34:28232
[email protected]632fbb12009-09-06 15:27:14233 NotificationService::current()->Notify(
234 NotificationType::EXTERNAL_TAB_CLOSED,
235 Source<NavigationController>(&tab_contents_->controller()),
236 Details<ExternalTabContainer>(this));
237
[email protected]7b8d4a22011-02-10 20:57:54238 tab_contents_.reset(NULL);
[email protected]632fbb12009-09-06 15:27:14239 }
[email protected]1a98a932009-11-17 00:12:52240
[email protected]93685472010-04-23 00:57:50241 if (focus_manager_) {
242 focus_manager_->UnregisterAccelerators(this);
[email protected]f1c74ec2010-05-21 22:20:37243 focus_manager_ = NULL;
[email protected]3f70c1e12010-01-12 20:38:49244 }
245
[email protected]ba67fd82010-07-09 18:30:31246 external_tab_view_ = NULL;
[email protected]13c30922009-11-19 03:43:19247 request_context_ = NULL;
[email protected]ab861b42010-02-05 19:13:44248 tab_contents_container_ = NULL;
[email protected]632fbb12009-09-06 15:27:14249}
250
251bool ExternalTabContainer::Reinitialize(
252 AutomationProvider* automation_provider,
[email protected]6e47f2f2010-07-12 17:30:58253 AutomationResourceMessageFilter* filter,
254 gfx::NativeWindow parent_window) {
[email protected]632fbb12009-09-06 15:27:14255 if (!automation_provider || !filter) {
256 NOTREACHED();
257 return false;
258 }
259
260 automation_ = automation_provider;
261 automation_resource_message_filter_ = filter;
[email protected]6c2e45b2010-05-07 00:55:25262 // Wait for the automation channel to be initialized before resuming pending
263 // render views and sending in the navigation state.
[email protected]24f98bba2009-10-14 18:47:49264 MessageLoop::current()->PostTask(
265 FROM_HERE,
266 external_method_factory_.NewRunnableMethod(
[email protected]18290eb2010-01-30 00:47:06267 &ExternalTabContainer::OnReinitialize));
[email protected]6e47f2f2010-07-12 17:30:58268
269 if (parent_window)
270 SetParent(GetNativeView(), parent_window);
[email protected]632fbb12009-09-06 15:27:14271 return true;
272}
273
[email protected]1a98a932009-11-17 00:12:52274void ExternalTabContainer::SetTabHandle(int handle) {
275 tab_handle_ = handle;
[email protected]1a98a932009-11-17 00:12:52276}
277
[email protected]9095e982009-05-27 17:28:24278void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) {
[email protected]3f70c1e12010-01-12 20:38:49279 NativeWebKeyboardEvent keyboard_event(msg.hwnd, msg.message, msg.wParam,
280 msg.lParam);
281 unhandled_keyboard_event_handler_.HandleKeyboardEvent(keyboard_event,
[email protected]93685472010-04-23 00:57:50282 focus_manager_);
[email protected]9095e982009-05-27 17:28:24283}
284
[email protected]1fd45692010-04-19 21:01:18285void ExternalTabContainer::FocusThroughTabTraversal(
286 bool reverse, bool restore_focus_to_view) {
[email protected]7b8d4a22011-02-10 20:57:54287 DCHECK(tab_contents_.get());
288 if (tab_contents_.get())
289 tab_contents_->tab_contents()->Focus();
[email protected]6331e0b2010-02-23 19:36:10290
291 // The tab_contents_ member can get destroyed in the context of the call to
[email protected]7e2cef52011-04-11 21:47:23292 // TabContentsViewViews::Focus() above. This method eventually calls SetFocus
[email protected]6331e0b2010-02-23 19:36:10293 // on the native window, which could end up dispatching messages like
294 // WM_DESTROY for the external tab.
[email protected]7b8d4a22011-02-10 20:57:54295 if (tab_contents_.get() && restore_focus_to_view)
296 tab_contents_->tab_contents()->FocusThroughTabTraversal(reverse);
initial.commit09911bf2008-07-26 23:55:29297}
298
[email protected]9095e982009-05-27 17:28:24299// static
300bool ExternalTabContainer::IsExternalTabContainer(HWND window) {
[email protected]3b8a7f8e2010-11-21 22:44:21301 return ViewProp::GetValue(window, kWindowObjectKey) != NULL;
initial.commit09911bf2008-07-26 23:55:29302}
303
[email protected]9095e982009-05-27 17:28:24304// static
305ExternalTabContainer* ExternalTabContainer::GetContainerForTab(
306 HWND tab_window) {
307 HWND parent_window = ::GetParent(tab_window);
308 if (!::IsWindow(parent_window)) {
309 return NULL;
initial.commit09911bf2008-07-26 23:55:29310 }
[email protected]9095e982009-05-27 17:28:24311 if (!IsExternalTabContainer(parent_window)) {
312 return NULL;
313 }
314 ExternalTabContainer* container = reinterpret_cast<ExternalTabContainer*>(
[email protected]3b8a7f8e2010-11-21 22:44:21315 ViewProp::GetValue(parent_window, kWindowObjectKey));
[email protected]9095e982009-05-27 17:28:24316 return container;
initial.commit09911bf2008-07-26 23:55:29317}
318
[email protected]2b19e2fe2010-02-16 02:24:18319// static
320ExternalTabContainer*
321 ExternalTabContainer::GetExternalContainerFromNativeWindow(
322 gfx::NativeView native_window) {
323 ExternalTabContainer* tab_container = NULL;
324 if (native_window) {
[email protected]3b8a7f8e2010-11-21 22:44:21325 tab_container = reinterpret_cast<ExternalTabContainer*>(
326 ViewProp::GetValue(native_window, kWindowObjectKey));
[email protected]2b19e2fe2010-02-16 02:24:18327 }
328 return tab_container;
329}
[email protected]9095e982009-05-27 17:28:24330////////////////////////////////////////////////////////////////////////////////
331// ExternalTabContainer, TabContentsDelegate implementation:
[email protected]72baf6762009-05-06 18:45:33332
[email protected]e38f40152008-09-12 23:08:30333void ExternalTabContainer::OpenURLFromTab(TabContents* source,
[email protected]ec0b6c42010-08-26 03:16:58334 const GURL& url,
335 const GURL& referrer,
336 WindowOpenDisposition disposition,
337 PageTransition::Type transition) {
[email protected]18290eb2010-01-30 00:47:06338 if (pending()) {
339 PendingTopLevelNavigation url_request;
340 url_request.disposition = disposition;
341 url_request.transition = transition;
342 url_request.url = url;
343 url_request.referrer = referrer;
344
345 pending_open_url_requests_.push_back(url_request);
346 return;
347 }
348
initial.commit09911bf2008-07-26 23:55:29349 switch (disposition) {
350 case CURRENT_TAB:
[email protected]fba16f52009-04-02 22:30:35351 case SINGLETON_TAB:
initial.commit09911bf2008-07-26 23:55:29352 case NEW_FOREGROUND_TAB:
353 case NEW_BACKGROUND_TAB:
[email protected]5f450e52009-07-28 13:28:11354 case NEW_POPUP:
initial.commit09911bf2008-07-26 23:55:29355 case NEW_WINDOW:
[email protected]5f450e52009-07-28 13:28:11356 case SAVE_TO_DISK:
initial.commit09911bf2008-07-26 23:55:29357 if (automation_) {
[email protected]f5494d42010-12-23 22:15:34358 automation_->Send(new AutomationMsg_OpenURL(tab_handle_,
[email protected]b36a9f92009-10-19 17:34:57359 url, referrer,
360 disposition));
[email protected]898f59212010-07-22 00:35:26361 // TODO(ananta)
362 // We should populate other fields in the
363 // ViewHostMsg_FrameNavigate_Params structure. Another option could be
364 // to refactor the UpdateHistoryForNavigation function in TabContents.
365 ViewHostMsg_FrameNavigate_Params params;
366 params.referrer = referrer;
367 params.url = url;
368 params.page_id = -1;
369 params.transition = PageTransition::LINK;
370
371 NavigationController::LoadCommittedDetails details;
372 details.did_replace_entry = false;
373
[email protected]ec0b6c42010-08-26 03:16:58374 scoped_refptr<history::HistoryAddPageArgs> add_page_args(
[email protected]7b8d4a22011-02-10 20:57:54375 tab_contents_->tab_contents()->
376 CreateHistoryAddPageArgs(url, details, params));
377 tab_contents_->tab_contents()->
378 UpdateHistoryForNavigation(add_page_args);
initial.commit09911bf2008-07-26 23:55:29379 }
380 break;
381 default:
[email protected]5f450e52009-07-28 13:28:11382 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29383 break;
[email protected]6dfed102009-04-28 03:09:53384 }
initial.commit09911bf2008-07-26 23:55:29385}
386
387void ExternalTabContainer::NavigationStateChanged(const TabContents* source,
[email protected]b9d227492009-02-10 15:20:27388 unsigned changed_flags) {
initial.commit09911bf2008-07-26 23:55:29389 if (automation_) {
[email protected]f5494d42010-12-23 22:15:34390 NavigationInfo nav_info;
[email protected]6c908bb2009-08-21 19:03:50391 if (InitNavigationInfo(&nav_info, NavigationType::NAV_IGNORE, 0))
392 automation_->Send(new AutomationMsg_NavigationStateChanged(
[email protected]f5494d42010-12-23 22:15:34393 tab_handle_, changed_flags, nav_info));
initial.commit09911bf2008-07-26 23:55:29394 }
395}
396
initial.commit09911bf2008-07-26 23:55:29397void ExternalTabContainer::AddNewContents(TabContents* source,
398 TabContents* new_contents,
399 WindowOpenDisposition disposition,
400 const gfx::Rect& initial_pos,
401 bool user_gesture) {
[email protected]e478e212010-07-17 00:31:29402 if (!automation_) {
403 DCHECK(pending_);
404 LOG(ERROR) << "Invalid automation provider. Dropping new contents notify";
405 delete new_contents;
406 return;
407 }
[email protected]a50a4902009-08-14 22:39:01408
[email protected]9eeb35e2010-09-30 21:38:50409 scoped_refptr<ExternalTabContainer> new_container;
410 // If the host is a browser like IE8, then the URL being navigated to in the
411 // new tab contents could potentially navigate back to Chrome from a new
412 // IE process. We support full tab mode only for IE and hence we use that as
413 // a determining factor in whether the new ExternalTabContainer instance is
414 // created as pending or not.
415 if (!route_all_top_level_navigations_) {
416 new_container = new ExternalTabContainer(NULL, NULL);
417 } else {
418 // Reuse the same tab handle here as the new container instance is a dummy
419 // instance which does not have an automation client connected at the other
420 // end.
421 new_container = new TemporaryPopupExternalTabContainer(
422 automation_, automation_resource_message_filter_.get());
423 new_container->SetTabHandle(tab_handle_);
424 }
[email protected]a50a4902009-08-14 22:39:01425
[email protected]6f526082010-01-28 19:36:58426 // Make sure that ExternalTabContainer instance is initialized with
427 // an unwrapped Profile.
[email protected]7b8d4a22011-02-10 20:57:54428 scoped_ptr<TabContentsWrapper> wrapper(new TabContentsWrapper(new_contents));
[email protected]6f526082010-01-28 19:36:58429 bool result = new_container->Init(
430 new_contents->profile()->GetOriginalProfile(),
431 NULL,
432 initial_pos,
433 WS_CHILD,
434 load_requests_via_automation_,
435 handle_top_level_requests_,
[email protected]7b8d4a22011-02-10 20:57:54436 wrapper.get(),
[email protected]6f526082010-01-28 19:36:58437 GURL(),
[email protected]f7019302010-03-26 19:58:32438 GURL(),
[email protected]9eeb35e2010-09-30 21:38:50439 true,
440 route_all_top_level_navigations_);
[email protected]a50a4902009-08-14 22:39:01441
[email protected]6f526082010-01-28 19:36:58442 if (result) {
[email protected]7b8d4a22011-02-10 20:57:54443 wrapper.release(); // Ownership has been transferred.
[email protected]9eeb35e2010-09-30 21:38:50444 if (route_all_top_level_navigations_) {
445 return;
446 }
[email protected]b1c55638612010-03-08 16:26:11447 uintptr_t cookie = reinterpret_cast<uintptr_t>(new_container.get());
[email protected]d0ed50d2010-06-22 01:01:32448 pending_tabs_.Get()[cookie] = new_container;
[email protected]18290eb2010-01-30 00:47:06449 new_container->set_pending(true);
[email protected]326d3b72011-03-29 20:38:24450 new_container->set_is_popup_window(disposition == NEW_POPUP);
[email protected]f5494d42010-12-23 22:15:34451 AttachExternalTabParams attach_params_;
[email protected]b1c55638612010-03-08 16:26:11452 attach_params_.cookie = static_cast<uint64>(cookie);
453 attach_params_.dimensions = initial_pos;
454 attach_params_.user_gesture = user_gesture;
455 attach_params_.disposition = disposition;
[email protected]8103c7f2010-09-08 22:36:09456 attach_params_.profile_name = WideToUTF8(
457 tab_contents()->profile()->GetPath().DirName().BaseName().value());
[email protected]f5494d42010-12-23 22:15:34458 automation_->Send(new AutomationMsg_AttachExternalTab(
[email protected]b1c55638612010-03-08 16:26:11459 tab_handle_, attach_params_));
[email protected]6f526082010-01-28 19:36:58460 } else {
461 NOTREACHED();
[email protected]9f5b80a2009-04-08 01:26:07462 }
initial.commit09911bf2008-07-26 23:55:29463}
464
[email protected]5951b5c12010-02-22 18:15:34465void ExternalTabContainer::TabContentsCreated(TabContents* new_contents) {
466 RenderViewHost* rvh = new_contents->render_view_host();
467 DCHECK(rvh != NULL);
[email protected]fd571bb2010-03-19 01:23:54468
469 // Register this render view as a pending render view, i.e. any network
470 // requests initiated by this render view would be serviced when the
471 // external host connects to the new external tab instance.
472 RegisterRenderViewHostForAutomation(rvh, true);
[email protected]5951b5c12010-02-22 18:15:34473}
474
initial.commit09911bf2008-07-26 23:55:29475void ExternalTabContainer::ActivateContents(TabContents* contents) {
476}
477
[email protected]ea42e7782010-08-23 23:58:12478void ExternalTabContainer::DeactivateContents(TabContents* contents) {
479}
480
initial.commit09911bf2008-07-26 23:55:29481void ExternalTabContainer::LoadingStateChanged(TabContents* source) {
482}
483
484void ExternalTabContainer::CloseContents(TabContents* source) {
[email protected]d9d8f0c2010-09-17 21:47:16485 if (!automation_)
486 return;
[email protected]e56e96f82010-02-03 21:38:08487
[email protected]d9d8f0c2010-09-17 21:47:16488 if (unload_reply_message_) {
489 AutomationMsg_RunUnloadHandlers::WriteReplyParams(unload_reply_message_,
490 true);
491 automation_->Send(unload_reply_message_);
492 unload_reply_message_ = NULL;
[email protected]e16dd1672010-06-07 21:40:29493 } else {
[email protected]f5494d42010-12-23 22:15:34494 automation_->Send(new AutomationMsg_CloseExternalTab(tab_handle_));
[email protected]085d9cf2010-01-27 01:11:02495 }
initial.commit09911bf2008-07-26 23:55:29496}
497
[email protected]b9d227492009-02-10 15:20:27498void ExternalTabContainer::MoveContents(TabContents* source,
499 const gfx::Rect& pos) {
[email protected]326d3b72011-03-29 20:38:24500 if (automation_ && is_popup_window_)
501 automation_->Send(new AutomationMsg_MoveWindow(tab_handle_, pos));
502}
503
504bool ExternalTabContainer::IsPopup(const TabContents* source) const {
505 return is_popup_window_;
initial.commit09911bf2008-07-26 23:55:29506}
507
initial.commit09911bf2008-07-26 23:55:29508void ExternalTabContainer::UpdateTargetURL(TabContents* source,
509 const GURL& url) {
510 if (automation_) {
511 std::wstring url_string = CA2W(url.spec().c_str());
512 automation_->Send(
[email protected]f5494d42010-12-23 22:15:34513 new AutomationMsg_UpdateTargetUrl(tab_handle_, url_string));
initial.commit09911bf2008-07-26 23:55:29514 }
515}
516
517void ExternalTabContainer::ContentsZoomChange(bool zoom_in) {
518}
519
[email protected]dec76e802010-09-23 22:43:53520bool ExternalTabContainer::IsExternalTabContainer() const {
521 return true;
522}
523
[email protected]a95631cb2009-12-10 01:59:11524gfx::NativeWindow ExternalTabContainer::GetFrameNativeWindow() {
525 return hwnd();
526}
527
[email protected]1e0a02d62009-04-23 22:55:56528bool ExternalTabContainer::TakeFocus(bool reverse) {
529 if (automation_) {
[email protected]f5494d42010-12-23 22:15:34530 automation_->Send(new AutomationMsg_TabbedOut(tab_handle_,
[email protected]a8e20582010-12-31 17:18:50531 base::win::IsShiftPressed()));
[email protected]1e0a02d62009-04-23 22:55:56532 }
533
534 return true;
535}
536
[email protected]21e302e2009-09-12 23:10:41537void ExternalTabContainer::ShowPageInfo(Profile* profile,
538 const GURL& url,
539 const NavigationEntry::SSLStatus& ssl,
540 bool show_history) {
[email protected]0b7a012d2010-10-19 23:49:26541 POINT cursor_pos = {0};
542 GetCursorPos(&cursor_pos);
543
544 gfx::Rect bounds;
545 bounds.set_origin(gfx::Point(cursor_pos));
546
547 PageInfoBubbleView* page_info_bubble =
548 new ExternalTabPageInfoBubbleView(this, NULL, profile, url,
549 ssl, show_history);
[email protected]9a56a0d2011-05-13 19:03:31550 Bubble* bubble = Bubble::Show(GetWidget(), bounds, BubbleBorder::TOP_LEFT,
[email protected]cb7f12f2011-04-14 15:10:23551 page_info_bubble, page_info_bubble);
552 page_info_bubble->set_bubble(bubble);
[email protected]21e302e2009-09-12 23:10:41553}
554
[email protected]fd571bb2010-03-19 01:23:54555void ExternalTabContainer::RegisterRenderViewHostForAutomation(
556 RenderViewHost* render_view_host, bool pending_view) {
557 if (render_view_host) {
558 AutomationResourceMessageFilter::RegisterRenderView(
559 render_view_host->process()->id(),
560 render_view_host->routing_id(),
561 tab_handle(),
562 automation_resource_message_filter_,
563 pending_view);
564 }
565}
566
[email protected]fd571bb2010-03-19 01:23:54567void ExternalTabContainer::RegisterRenderViewHost(
568 RenderViewHost* render_view_host) {
569 // RenderViewHost instances that are to be associated with this
570 // ExternalTabContainer should share the same resource request automation
571 // settings.
572 RegisterRenderViewHostForAutomation(
573 render_view_host,
574 false); // Network requests should not be handled later.
575}
576
577void ExternalTabContainer::UnregisterRenderViewHost(
578 RenderViewHost* render_view_host) {
579 // Undo the resource automation registration performed in
580 // ExternalTabContainer::RegisterRenderViewHost.
581 if (render_view_host) {
582 AutomationResourceMessageFilter::UnRegisterRenderView(
583 render_view_host->process()->id(),
584 render_view_host->routing_id());
585 }
586}
587
[email protected]e943d6662009-06-12 03:50:39588bool ExternalTabContainer::HandleContextMenu(const ContextMenuParams& params) {
589 if (!automation_) {
590 NOTREACHED();
591 return false;
592 }
[email protected]e943d6662009-06-12 03:50:39593 external_context_menu_.reset(
[email protected]14831ef2010-05-11 23:51:20594 new RenderViewContextMenuViews(tab_contents(), params));
595 external_context_menu_->SetExternal();
[email protected]e943d6662009-06-12 03:50:39596 external_context_menu_->Init();
[email protected]a5e04ea2010-06-08 13:37:08597 external_context_menu_->UpdateMenuItemStates();
[email protected]e943d6662009-06-12 03:50:39598
599 POINT screen_pt = { params.x, params.y };
600 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1);
601
[email protected]f5494d42010-12-23 22:15:34602 MiniContextMenuParams ipc_params(
[email protected]0f1afed2010-12-15 17:22:28603 screen_pt.x,
604 screen_pt.y,
605 params.link_url,
606 params.unfiltered_link_url,
607 params.src_url,
608 params.page_url,
609 params.frame_url);
[email protected]35f13ab2009-12-16 23:59:17610
[email protected]7cf1b6ce2010-03-20 06:37:01611 bool rtl = base::i18n::IsRTL();
[email protected]e943d6662009-06-12 03:50:39612 automation_->Send(
[email protected]f5494d42010-12-23 22:15:34613 new AutomationMsg_ForwardContextMenuToExternalHost(tab_handle_,
[email protected]35f13ab2009-12-16 23:59:17614 external_context_menu_->GetMenuHandle(),
615 rtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN, ipc_params));
[email protected]e943d6662009-06-12 03:50:39616
617 return true;
618}
619
620bool ExternalTabContainer::ExecuteContextMenuCommand(int command) {
621 if (!external_context_menu_.get()) {
622 NOTREACHED();
623 return false;
624 }
625
[email protected]35f13ab2009-12-16 23:59:17626 switch (command) {
627 case IDS_CONTENT_CONTEXT_SAVEAUDIOAS:
628 case IDS_CONTENT_CONTEXT_SAVEVIDEOAS:
629 case IDS_CONTENT_CONTEXT_SAVEIMAGEAS:
630 case IDS_CONTENT_CONTEXT_SAVELINKAS: {
631 NOTREACHED(); // Should be handled in host.
632 break;
633 }
634 }
635
[email protected]e943d6662009-06-12 03:50:39636 external_context_menu_->ExecuteCommand(command);
637 return true;
638}
639
[email protected]867125a02009-12-10 06:01:48640bool ExternalTabContainer::PreHandleKeyboardEvent(
641 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
642 return false;
643}
644
645void ExternalTabContainer::HandleKeyboardEvent(
[email protected]334a105b2009-07-14 03:42:55646 const NativeWebKeyboardEvent& event) {
[email protected]867125a02009-12-10 06:01:48647 ProcessUnhandledKeyStroke(event.os_event.hwnd, event.os_event.message,
648 event.os_event.wParam, event.os_event.lParam);
[email protected]334a105b2009-07-14 03:42:55649}
650
[email protected]d9d8f0c2010-09-17 21:47:16651void ExternalTabContainer::BeforeUnloadFired(TabContents* tab,
652 bool proceed,
653 bool* proceed_to_fire_unload) {
[email protected]d9d8f0c2010-09-17 21:47:16654 *proceed_to_fire_unload = true;
655
656 if (!automation_) {
657 delete unload_reply_message_;
658 unload_reply_message_ = NULL;
659 return;
660 }
661
[email protected]b5e0a192011-03-22 19:15:32662 if (!unload_reply_message_) {
663 NOTREACHED() << "**** NULL unload reply message pointer.";
664 return;
665 }
666
[email protected]d9d8f0c2010-09-17 21:47:16667 if (!proceed) {
668 AutomationMsg_RunUnloadHandlers::WriteReplyParams(unload_reply_message_,
669 false);
670 automation_->Send(unload_reply_message_);
671 unload_reply_message_ = NULL;
672 *proceed_to_fire_unload = false;
673 }
674}
675
[email protected]2fc22d12010-12-02 23:08:16676void ExternalTabContainer::ShowRepostFormWarningDialog(
677 TabContents* tab_contents) {
678 browser::ShowRepostFormWarningDialog(GetNativeView(), tab_contents);
679}
680
[email protected]15b2c6a2011-05-16 23:54:40681bool ExternalTabContainer::OnMessageReceived(const IPC::Message& message) {
682 bool handled = true;
683 IPC_BEGIN_MESSAGE_MAP(ExternalTabContainer, message)
684 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardMessageToExternalHost,
685 OnForwardMessageToExternalHost)
686 IPC_MESSAGE_UNHANDLED(handled = false)
687 IPC_END_MESSAGE_MAP()
688 return handled;
689}
690
691void ExternalTabContainer::OnForwardMessageToExternalHost(
692 const std::string& message,
693 const std::string& origin,
694 const std::string& target) {
695 if (automation_) {
696 automation_->Send(new AutomationMsg_ForwardMessageToExternalHost(
697 tab_handle_, message, origin, target));
698 }
699}
700
[email protected]9095e982009-05-27 17:28:24701////////////////////////////////////////////////////////////////////////////////
702// ExternalTabContainer, NotificationObserver implementation:
703
initial.commit09911bf2008-07-26 23:55:29704void ExternalTabContainer::Observe(NotificationType type,
705 const NotificationSource& source,
706 const NotificationDetails& details) {
[email protected]33ee8da2009-04-16 17:45:37707 if (!automation_)
708 return;
709
[email protected]2e39d2e2009-02-19 18:41:31710 static const int kHttpClientErrorStart = 400;
711 static const int kHttpServerErrorEnd = 510;
712
[email protected]bfd04a62009-02-01 18:16:56713 switch (type.value) {
[email protected]33ee8da2009-04-16 17:45:37714 case NotificationType::LOAD_STOP: {
715 const LoadNotificationDetails* load =
716 Details<LoadNotificationDetails>(details).ptr();
[email protected]d86153f2009-05-18 21:10:52717 if (load != NULL && PageTransition::IsMainFrame(load->origin())) {
[email protected]366ae242011-05-10 02:23:58718 TRACE_EVENT_END_ETW("ExternalTabContainer::Navigate", 0,
719 load->url().spec());
[email protected]f5494d42010-12-23 22:15:34720 automation_->Send(new AutomationMsg_TabLoaded(tab_handle_,
[email protected]eac83f02009-05-08 18:44:44721 load->url()));
[email protected]33ee8da2009-04-16 17:45:37722 }
723 break;
[email protected]2e39d2e2009-02-19 18:41:31724 }
[email protected]33ee8da2009-04-16 17:45:37725 case NotificationType::NAV_ENTRY_COMMITTED: {
726 if (ignore_next_load_notification_) {
727 ignore_next_load_notification_ = false;
728 return;
729 }
[email protected]2e39d2e2009-02-19 18:41:31730
[email protected]0e8db942008-09-24 21:21:48731 const NavigationController::LoadCommittedDetails* commit =
732 Details<NavigationController::LoadCommittedDetails>(details).ptr();
733
[email protected]f0a51fb52009-03-05 12:46:38734 if (commit->http_status_code >= kHttpClientErrorStart &&
[email protected]2e39d2e2009-02-19 18:41:31735 commit->http_status_code <= kHttpServerErrorEnd) {
736 automation_->Send(new AutomationMsg_NavigationFailed(
[email protected]f5494d42010-12-23 22:15:34737 tab_handle_, commit->http_status_code, commit->entry->url()));
[email protected]2e39d2e2009-02-19 18:41:31738
739 ignore_next_load_notification_ = true;
740 } else {
[email protected]f5494d42010-12-23 22:15:34741 NavigationInfo navigation_info;
[email protected]2e39d2e2009-02-19 18:41:31742 // When the previous entry index is invalid, it will be -1, which
743 // will still make the computation come out right (navigating to the
744 // 0th entry will be +1).
[email protected]6c908bb2009-08-21 19:03:50745 if (InitNavigationInfo(&navigation_info, commit->type,
746 commit->previous_entry_index -
747 tab_contents_->controller().last_committed_entry_index()))
[email protected]f5494d42010-12-23 22:15:34748 automation_->Send(new AutomationMsg_DidNavigate(tab_handle_,
[email protected]6c908bb2009-08-21 19:03:50749 navigation_info));
[email protected]2e39d2e2009-02-19 18:41:31750 }
[email protected]33ee8da2009-04-16 17:45:37751 break;
[email protected]0e8db942008-09-24 21:21:48752 }
[email protected]2e39d2e2009-02-19 18:41:31753 case NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR: {
[email protected]33ee8da2009-04-16 17:45:37754 const ProvisionalLoadDetails* load_details =
755 Details<ProvisionalLoadDetails>(details).ptr();
756 automation_->Send(new AutomationMsg_NavigationFailed(
[email protected]f5494d42010-12-23 22:15:34757 tab_handle_, load_details->error_code(), load_details->url()));
[email protected]2e39d2e2009-02-19 18:41:31758
[email protected]33ee8da2009-04-16 17:45:37759 ignore_next_load_notification_ = true;
[email protected]2e39d2e2009-02-19 18:41:31760 break;
761 }
[email protected]2e4633c2009-07-09 16:58:06762 case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
763 if (load_requests_via_automation_) {
764 RenderViewHost* rvh = Details<RenderViewHost>(details).ptr();
[email protected]fd571bb2010-03-19 01:23:54765 RegisterRenderViewHostForAutomation(rvh, false);
[email protected]2e4633c2009-07-09 16:58:06766 }
767 break;
768 }
769 case NotificationType::RENDER_VIEW_HOST_DELETED: {
770 if (load_requests_via_automation_) {
[email protected]6b5b0cd2011-03-31 21:11:41771 RenderViewHost* rvh = Source<RenderViewHost>(source).ptr();
[email protected]fd571bb2010-03-19 01:23:54772 UnregisterRenderViewHost(rvh);
[email protected]2e4633c2009-07-09 16:58:06773 }
774 break;
775 }
[email protected]0e8db942008-09-24 21:21:48776 default:
777 NOTREACHED();
778 }
initial.commit09911bf2008-07-26 23:55:29779}
780
[email protected]9095e982009-05-27 17:28:24781////////////////////////////////////////////////////////////////////////////////
[email protected]ddb85052011-05-18 14:40:27782// ExternalTabContainer, DownloadTabHelperDelegate overrides:
783
784bool ExternalTabContainer::CanDownload(int request_id) {
785 if (load_requests_via_automation_) {
786 if (automation_) {
787 // In case the host needs to show UI that needs to take the focus.
788 ::AllowSetForegroundWindow(ASFW_ANY);
789
790 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
791 NewRunnableMethod(automation_resource_message_filter_.get(),
792 &AutomationResourceMessageFilter::SendDownloadRequestToHost,
793 0, tab_handle_, request_id));
794 }
795 } else {
796 DLOG(WARNING) << "Downloads are only supported with host browser network "
797 "stack enabled.";
798 }
799
800 // Never allow downloads.
801 return false;
802}
803
804void ExternalTabContainer::OnStartDownload(DownloadItem* download,
805 TabContentsWrapper* tab) {
806 // Downloads are handled by Automation.
807}
808
809
810////////////////////////////////////////////////////////////////////////////////
[email protected]2fc66722011-05-19 14:43:12811// ExternalTabContainer, views::NativeWidgetWin overrides:
[email protected]9095e982009-05-27 17:28:24812
[email protected]632fbb12009-09-06 15:27:14813LRESULT ExternalTabContainer::OnCreate(LPCREATESTRUCT create_struct) {
[email protected]2fc66722011-05-19 14:43:12814 LRESULT result = views::NativeWidgetWin::OnCreate(create_struct);
[email protected]632fbb12009-09-06 15:27:14815 if (result == 0) {
816 // Grab a reference here which will be released in OnFinalMessage
817 AddRef();
818 }
819 return result;
820}
821
[email protected]9095e982009-05-27 17:28:24822void ExternalTabContainer::OnDestroy() {
[email protected]7c9d8292010-11-01 16:57:13823 prop_.reset();
[email protected]632fbb12009-09-06 15:27:14824 Uninitialize();
[email protected]2fc66722011-05-19 14:43:12825 NativeWidgetWin::OnDestroy();
[email protected]36cf19b92009-07-22 18:07:51826 if (browser_.get()) {
827 ::DestroyWindow(browser_->window()->GetNativeHandle());
828 }
initial.commit09911bf2008-07-26 23:55:29829}
830
[email protected]632fbb12009-09-06 15:27:14831void ExternalTabContainer::OnFinalMessage(HWND window) {
832 // Release the reference which we grabbed in WM_CREATE.
833 Release();
[email protected]334a105b2009-07-14 03:42:55834}
835
[email protected]d9d8f0c2010-09-17 21:47:16836void ExternalTabContainer::RunUnloadHandlers(IPC::Message* reply_message) {
837 if (!automation_) {
838 delete reply_message;
839 return;
[email protected]1f71d5882010-07-15 20:39:07840 }
[email protected]d9d8f0c2010-09-17 21:47:16841
842 // If we have a pending unload message, then just respond back to this
843 // request and continue processing the previous unload message.
844 if (unload_reply_message_) {
845 AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message, true);
846 automation_->Send(reply_message);
847 return;
848 }
[email protected]b5e0a192011-03-22 19:15:32849
850 unload_reply_message_ = reply_message;
851 bool wait_for_unload_handlers =
852 tab_contents_.get() &&
853 Browser::RunUnloadEventsHelper(tab_contents_->tab_contents());
854 if (!wait_for_unload_handlers) {
[email protected]d9d8f0c2010-09-17 21:47:16855 AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message, true);
856 automation_->Send(reply_message);
[email protected]b5e0a192011-03-22 19:15:32857 unload_reply_message_ = NULL;
[email protected]1f71d5882010-07-15 20:39:07858 }
859}
860
[email protected]632fbb12009-09-06 15:27:14861////////////////////////////////////////////////////////////////////////////////
862// ExternalTabContainer, private:
[email protected]334a105b2009-07-14 03:42:55863bool ExternalTabContainer::ProcessUnhandledKeyStroke(HWND window,
864 UINT message,
865 WPARAM wparam,
866 LPARAM lparam) {
initial.commit09911bf2008-07-26 23:55:29867 if (!automation_) {
868 return false;
869 }
[email protected]a8e20582010-12-31 17:18:50870 if ((wparam == VK_TAB) && !base::win::IsCtrlPressed()) {
initial.commit09911bf2008-07-26 23:55:29871 // Tabs are handled separately (except if this is Ctrl-Tab or
872 // Ctrl-Shift-Tab)
873 return false;
874 }
[email protected]060254c2009-05-02 16:45:27875
[email protected]01dba672010-02-12 21:55:48876 // Send this keystroke to the external host as it could be processed as an
877 // accelerator there. If the host does not handle this accelerator, it will
878 // reflect the accelerator back to us via the ProcessUnhandledAccelerator
879 // method.
880 MSG msg = {0};
881 msg.hwnd = window;
882 msg.message = message;
883 msg.wParam = wparam;
884 msg.lParam = lparam;
[email protected]f5494d42010-12-23 22:15:34885 automation_->Send(new AutomationMsg_HandleAccelerator(tab_handle_, msg));
[email protected]01dba672010-02-12 21:55:48886 return true;
initial.commit09911bf2008-07-26 23:55:29887}
[email protected]4150ef02009-08-19 23:14:26888
[email protected]f5494d42010-12-23 22:15:34889bool ExternalTabContainer::InitNavigationInfo(NavigationInfo* nav_info,
[email protected]4150ef02009-08-19 23:14:26890 NavigationType::Type nav_type,
891 int relative_offset) {
[email protected]4150ef02009-08-19 23:14:26892 DCHECK(nav_info);
[email protected]6c908bb2009-08-21 19:03:50893 NavigationEntry* entry = tab_contents_->controller().GetActiveEntry();
894 // If this is very early in the game then we may not have an entry.
895 if (!entry)
896 return false;
[email protected]4150ef02009-08-19 23:14:26897
898 nav_info->navigation_type = nav_type;
899 nav_info->relative_offset = relative_offset;
900 nav_info->navigation_index =
901 tab_contents_->controller().GetCurrentEntryIndex();
[email protected]4150ef02009-08-19 23:14:26902 nav_info->url = entry->url();
[email protected]a1955adf2010-08-02 17:59:39903 nav_info->referrer = entry->referrer();
[email protected]6b2f7a82011-04-25 19:30:51904 nav_info->title = UTF16ToWideHack(entry->title());
[email protected]24f98bba2009-10-14 18:47:49905 if (nav_info->title.empty())
906 nav_info->title = UTF8ToWide(nav_info->url.spec());
907
[email protected]f5cde2b2009-09-11 22:33:58908 nav_info->security_style = entry->ssl().security_style();
[email protected]b4e75c12010-05-18 18:28:48909 nav_info->displayed_insecure_content =
910 entry->ssl().displayed_insecure_content();
911 nav_info->ran_insecure_content = entry->ssl().ran_insecure_content();
[email protected]6c908bb2009-08-21 19:03:50912 return true;
[email protected]4150ef02009-08-19 23:14:26913}
914
[email protected]cd0dec62010-02-11 02:33:18915scoped_refptr<ExternalTabContainer> ExternalTabContainer::RemovePendingTab(
[email protected]b1c55638612010-03-08 16:26:11916 uintptr_t cookie) {
[email protected]d0ed50d2010-06-22 01:01:32917 ExternalTabContainer::PendingTabs& pending_tabs = pending_tabs_.Get();
918 PendingTabs::iterator index = pending_tabs.find(cookie);
919 if (index != pending_tabs.end()) {
[email protected]632fbb12009-09-06 15:27:14920 scoped_refptr<ExternalTabContainer> container = (*index).second;
[email protected]d0ed50d2010-06-22 01:01:32921 pending_tabs.erase(index);
[email protected]cd0dec62010-02-11 02:33:18922 return container;
[email protected]632fbb12009-09-06 15:27:14923 }
924
925 NOTREACHED() << "Failed to find ExternalTabContainer for cookie: "
926 << cookie;
927 return NULL;
928}
929
[email protected]9ac174e92011-04-16 00:58:56930SkColor ExternalTabContainer::GetInfoBarSeparatorColor() const {
931 return ResourceBundle::toolbar_separator_color;
932}
933
[email protected]4f2d40d2011-05-05 01:33:30934void ExternalTabContainer::InfoBarContainerStateChanged(bool is_animating) {
[email protected]f4f50ef2011-01-21 19:01:19935 if (external_tab_view_)
[email protected]ba67fd82010-07-09 18:30:31936 external_tab_view_->Layout();
[email protected]ab861b42010-02-05 19:13:44937}
938
[email protected]ee120872011-04-15 01:37:06939bool ExternalTabContainer::DrawInfoBarArrows(int* x) const {
940 return false;
941}
942
[email protected]a95631cb2009-12-10 01:59:11943// ExternalTabContainer instances do not have a window.
[email protected]cdc05ec2011-05-18 15:15:59944views::Window* ExternalTabContainer::GetContainingWindow() {
945 return NULL;
946}
947
948const views::Window* ExternalTabContainer::GetContainingWindow() const {
[email protected]a95631cb2009-12-10 01:59:11949 return NULL;
950}
951
[email protected]3f70c1e12010-01-12 20:38:49952bool ExternalTabContainer::AcceleratorPressed(
953 const views::Accelerator& accelerator) {
954 std::map<views::Accelerator, int>::const_iterator iter =
955 accelerator_table_.find(accelerator);
956 DCHECK(iter != accelerator_table_.end());
957
[email protected]7b8d4a22011-02-10 20:57:54958 if (!tab_contents_.get() || !tab_contents_->render_view_host()) {
[email protected]3f70c1e12010-01-12 20:38:49959 NOTREACHED();
960 return false;
961 }
962
[email protected]216813952011-05-19 22:21:26963 RenderViewHost* host = tab_contents_->render_view_host();
[email protected]3f70c1e12010-01-12 20:38:49964 int command_id = iter->second;
965 switch (command_id) {
966 case IDC_ZOOM_PLUS:
[email protected]216813952011-05-19 22:21:26967 host->Send(new ViewMsg_Zoom(host->routing_id(), PageZoom::ZOOM_IN));
[email protected]3f70c1e12010-01-12 20:38:49968 break;
969 case IDC_ZOOM_NORMAL:
[email protected]216813952011-05-19 22:21:26970 host->Send(new ViewMsg_Zoom(host->routing_id(), PageZoom::RESET));
[email protected]3f70c1e12010-01-12 20:38:49971 break;
972 case IDC_ZOOM_MINUS:
[email protected]216813952011-05-19 22:21:26973 host->Send(new ViewMsg_Zoom(host->routing_id(), PageZoom::ZOOM_OUT));
[email protected]3f70c1e12010-01-12 20:38:49974 break;
975 case IDC_DEV_TOOLS:
976 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
[email protected]2a8a98122010-07-16 11:58:48977 tab_contents_->render_view_host(), DEVTOOLS_TOGGLE_ACTION_NONE);
[email protected]3f70c1e12010-01-12 20:38:49978 break;
979 case IDC_DEV_TOOLS_CONSOLE:
980 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
[email protected]2a8a98122010-07-16 11:58:48981 tab_contents_->render_view_host(),
982 DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
983 break;
984 case IDC_DEV_TOOLS_INSPECT:
985 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
986 tab_contents_->render_view_host(),
987 DEVTOOLS_TOGGLE_ACTION_INSPECT);
[email protected]3f70c1e12010-01-12 20:38:49988 break;
989 default:
990 NOTREACHED() << "Unsupported accelerator: " << command_id;
991 return false;
992 }
993 return true;
994}
995
[email protected]f5cde2b2009-09-11 22:33:58996void ExternalTabContainer::Navigate(const GURL& url, const GURL& referrer) {
[email protected]7b8d4a22011-02-10 20:57:54997 if (!tab_contents_.get()) {
[email protected]f5cde2b2009-09-11 22:33:58998 NOTREACHED();
999 return;
1000 }
1001
[email protected]366ae242011-05-10 02:23:581002 TRACE_EVENT_BEGIN_ETW("ExternalTabContainer::Navigate", 0, url.spec());
[email protected]a872ea1f2010-08-11 04:45:331003
[email protected]f5cde2b2009-09-11 22:33:581004 tab_contents_->controller().LoadURL(url, referrer,
1005 PageTransition::START_PAGE);
1006}
[email protected]f9cc4c452009-10-13 14:56:381007
1008bool ExternalTabContainer::OnGoToEntryOffset(int offset) {
1009 if (load_requests_via_automation_) {
1010 automation_->Send(new AutomationMsg_RequestGoToHistoryEntryOffset(
[email protected]f5494d42010-12-23 22:15:341011 tab_handle_, offset));
[email protected]f9cc4c452009-10-13 14:56:381012 return false;
1013 }
1014
1015 return true;
1016}
[email protected]1a98a932009-11-17 00:12:521017
[email protected]3f70c1e12010-01-12 20:38:491018void ExternalTabContainer::LoadAccelerators() {
1019 HACCEL accelerator_table = AtlLoadAccelerators(IDR_CHROMEFRAME);
1020 DCHECK(accelerator_table);
1021
1022 // We have to copy the table to access its contents.
1023 int count = CopyAcceleratorTable(accelerator_table, 0, 0);
1024 if (count == 0) {
1025 // Nothing to do in that case.
1026 return;
1027 }
1028
1029 scoped_ptr<ACCEL> scoped_accelerators(new ACCEL[count]);
1030 ACCEL* accelerators = scoped_accelerators.get();
1031 DCHECK(accelerators != NULL);
1032
1033 CopyAcceleratorTable(accelerator_table, accelerators, count);
1034
[email protected]9a56a0d2011-05-13 19:03:311035 focus_manager_ = GetWidget()->GetFocusManager();
[email protected]93685472010-04-23 00:57:501036 DCHECK(focus_manager_);
[email protected]3f70c1e12010-01-12 20:38:491037
1038 // Let's fill our own accelerator table.
1039 for (int i = 0; i < count; ++i) {
1040 bool alt_down = (accelerators[i].fVirt & FALT) == FALT;
1041 bool ctrl_down = (accelerators[i].fVirt & FCONTROL) == FCONTROL;
1042 bool shift_down = (accelerators[i].fVirt & FSHIFT) == FSHIFT;
1043 views::Accelerator accelerator(
[email protected]b6d81262011-01-13 17:36:091044 static_cast<ui::KeyboardCode>(accelerators[i].key),
[email protected]3f70c1e12010-01-12 20:38:491045 shift_down, ctrl_down, alt_down);
1046 accelerator_table_[accelerator] = accelerators[i].cmd;
1047
1048 // Also register with the focus manager.
[email protected]93685472010-04-23 00:57:501049 if (focus_manager_)
1050 focus_manager_->RegisterAccelerator(accelerator, this);
[email protected]3f70c1e12010-01-12 20:38:491051 }
1052}
[email protected]18290eb2010-01-30 00:47:061053
1054void ExternalTabContainer::OnReinitialize() {
[email protected]6c2e45b2010-05-07 00:55:251055 if (load_requests_via_automation_) {
[email protected]6c2e45b2010-05-07 00:55:251056 RenderViewHost* rvh = tab_contents_->render_view_host();
1057 if (rvh) {
1058 AutomationResourceMessageFilter::ResumePendingRenderView(
1059 rvh->process()->id(), rvh->routing_id(),
1060 tab_handle_, automation_resource_message_filter_);
1061 }
1062 }
1063
[email protected]7b8d4a22011-02-10 20:57:541064 NavigationStateChanged(tab_contents(), 0);
[email protected]18290eb2010-01-30 00:47:061065 ServicePendingOpenURLRequests();
1066}
1067
1068void ExternalTabContainer::ServicePendingOpenURLRequests() {
1069 DCHECK(pending());
1070
1071 set_pending(false);
1072
1073 for (size_t index = 0; index < pending_open_url_requests_.size();
[email protected]7b8d4a22011-02-10 20:57:541074 ++index) {
[email protected]18290eb2010-01-30 00:47:061075 const PendingTopLevelNavigation& url_request =
1076 pending_open_url_requests_[index];
[email protected]7b8d4a22011-02-10 20:57:541077 OpenURLFromTab(tab_contents(), url_request.url, url_request.referrer,
[email protected]18290eb2010-01-30 00:47:061078 url_request.disposition, url_request.transition);
1079 }
1080 pending_open_url_requests_.clear();
1081}
1082
[email protected]ab861b42010-02-05 19:13:441083void ExternalTabContainer::SetupExternalTabView() {
1084 // Create a TabContentsContainer to handle focus cycling using Tab and
1085 // Shift-Tab.
1086 tab_contents_container_ = new TabContentsContainer;
1087
1088 // The views created here will be destroyed when the ExternalTabContainer
1089 // widget is torn down.
[email protected]ba67fd82010-07-09 18:30:311090 external_tab_view_ = new views::View();
[email protected]ab861b42010-02-05 19:13:441091
[email protected]6c6614f12011-03-31 18:51:421092 InfoBarContainerView* info_bar_container = new InfoBarContainerView(this);
[email protected]7abc95292011-05-18 00:18:091093 info_bar_container->ChangeTabContents(tab_contents_.get());
[email protected]ab861b42010-02-05 19:13:441094
[email protected]ba67fd82010-07-09 18:30:311095 views::GridLayout* layout = new views::GridLayout(external_tab_view_);
1096 // Give this column an identifier of 0.
1097 views::ColumnSet* columns = layout->AddColumnSet(0);
[email protected]ab861b42010-02-05 19:13:441098 columns->AddColumn(views::GridLayout::FILL,
1099 views::GridLayout::FILL,
1100 1,
1101 views::GridLayout::USE_PREF,
1102 0,
1103 0);
1104
[email protected]ba67fd82010-07-09 18:30:311105 external_tab_view_->SetLayoutManager(layout);
[email protected]ab861b42010-02-05 19:13:441106
1107 layout->StartRow(0, 0);
1108 layout->AddView(info_bar_container);
1109 layout->StartRow(1, 0);
1110 layout->AddView(tab_contents_container_);
[email protected]9a56a0d2011-05-13 19:03:311111 GetWidget()->SetContentsView(external_tab_view_);
[email protected]ab861b42010-02-05 19:13:441112 // Note that SetTabContents must be called after AddChildView is called
[email protected]7b8d4a22011-02-10 20:57:541113 tab_contents_container_->ChangeTabContents(tab_contents());
[email protected]ab861b42010-02-05 19:13:441114}
[email protected]9eeb35e2010-09-30 21:38:501115
1116TemporaryPopupExternalTabContainer::TemporaryPopupExternalTabContainer(
1117 AutomationProvider* automation,
1118 AutomationResourceMessageFilter* filter)
1119 : ExternalTabContainer(automation, filter) {
1120}
1121
1122TemporaryPopupExternalTabContainer::~TemporaryPopupExternalTabContainer() {
[email protected]8e96e502010-10-21 20:57:121123 DVLOG(1) << __FUNCTION__;
[email protected]9eeb35e2010-09-30 21:38:501124}
1125
1126void TemporaryPopupExternalTabContainer::OpenURLFromTab(
1127 TabContents* source, const GURL& url, const GURL& referrer,
1128 WindowOpenDisposition disposition, PageTransition::Type transition) {
1129 if (!automation_)
1130 return;
1131
1132 if (disposition == CURRENT_TAB) {
1133 DCHECK(route_all_top_level_navigations_);
1134 disposition = NEW_FOREGROUND_TAB;
1135 }
1136 ExternalTabContainer::OpenURLFromTab(source, url, referrer, disposition,
1137 transition);
1138 // support only one navigation for a dummy tab before it is killed.
1139 ::DestroyWindow(GetNativeView());
1140}