blob: 70ac7fc8c19088428439f4a2b44fa973147fb818 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/external_tab_container.h"
6
[email protected]4c540ee2009-07-07 17:15:557#include <string>
8
[email protected]cdb42662009-06-12 20:44:289#include "app/l10n_util.h"
[email protected]4a0765a2009-05-08 23:12:2510#include "app/win_util.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/logging.h"
[email protected]1eb89e82008-08-15 12:27:0312#include "base/win_util.h"
[email protected]3f70c1e12010-01-12 20:38:4913#include "chrome/app/chrome_dll_resource.h"
initial.commit09911bf2008-07-26 23:55:2914#include "chrome/browser/automation/automation_provider.h"
[email protected]4cfc1d922009-11-08 14:02:5815#include "chrome/browser/automation/automation_extension_function.h"
[email protected]36cf19b92009-07-22 18:07:5116#include "chrome/browser/browser_window.h"
[email protected]52933842009-09-29 03:44:0617#include "chrome/browser/debugger/devtools_manager.h"
[email protected]33ee8da2009-04-16 17:45:3718#include "chrome/browser/load_notification_details.h"
[email protected]21e302e2009-09-12 23:10:4119#include "chrome/browser/page_info_window.h"
initial.commit09911bf2008-07-26 23:55:2920#include "chrome/browser/profile.h"
[email protected]1db6ff152009-10-12 15:32:0721#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]8cb5d5b2010-02-09 11:36:1622#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]fc6fb7fb2009-11-07 02:35:0423#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
[email protected]2e39d2e2009-02-19 18:41:3124#include "chrome/browser/tab_contents/provisional_load_details.h"
[email protected]2eca5492009-06-14 21:52:1325#include "chrome/browser/views/tab_contents/render_view_context_menu_external_win.h"
[email protected]f3ec7742009-01-15 00:59:1626#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]610d36a2009-05-22 23:00:3827#include "chrome/browser/views/tab_contents/tab_contents_container.h"
[email protected]811bfe32009-07-01 08:46:2528#include "chrome/common/bindings_policy.h"
initial.commit09911bf2008-07-26 23:55:2929#include "chrome/common/chrome_constants.h"
[email protected]3f70c1e12010-01-12 20:38:4930#include "chrome/common/native_web_keyboard_event.h"
[email protected]1c58a5c2009-05-21 18:47:1431#include "chrome/common/notification_service.h"
initial.commit09911bf2008-07-26 23:55:2932#include "chrome/test/automation/automation_messages.h"
[email protected]e943d6662009-06-12 03:50:3933#include "grit/generated_resources.h"
[email protected]ab861b42010-02-05 19:13:4434#include "views/grid_layout.h"
35#include "views/widget/root_view.h"
[email protected]21e302e2009-09-12 23:10:4136#include "views/window/window.h"
[email protected]e943d6662009-06-12 03:50:3937
initial.commit09911bf2008-07-26 23:55:2938static const wchar_t kWindowObjectKey[] = L"ChromeWindowObject";
39
[email protected]632fbb12009-09-06 15:27:1440ExternalTabContainer::PendingTabs ExternalTabContainer::pending_tabs_;
[email protected]e56e96f82010-02-03 21:38:0841ExternalTabContainer* ExternalTabContainer::innermost_tab_for_unload_event_
42 = NULL;
[email protected]632fbb12009-09-06 15:27:1443
initial.commit09911bf2008-07-26 23:55:2944ExternalTabContainer::ExternalTabContainer(
[email protected]2e4633c2009-07-09 16:58:0645 AutomationProvider* automation, AutomationResourceMessageFilter* filter)
initial.commit09911bf2008-07-26 23:55:2946 : automation_(automation),
initial.commit09911bf2008-07-26 23:55:2947 tab_contents_(NULL),
[email protected]2e39d2e2009-02-19 18:41:3148 tab_contents_container_(NULL),
[email protected]eac83f02009-05-08 18:44:4449 tab_handle_(0),
[email protected]2e4633c2009-07-09 16:58:0650 ignore_next_load_notification_(false),
51 automation_resource_message_filter_(filter),
[email protected]a50a4902009-08-14 22:39:0152 load_requests_via_automation_(false),
[email protected]24f98bba2009-10-14 18:47:4953 handle_top_level_requests_(false),
[email protected]4cfc1d922009-11-08 14:02:5854 external_method_factory_(this),
[email protected]085d9cf2010-01-27 01:11:0255 enabled_extension_automation_(false),
[email protected]18290eb2010-01-30 00:47:0656 waiting_for_unload_event_(false),
57 pending_(false) {
initial.commit09911bf2008-07-26 23:55:2958}
59
60ExternalTabContainer::~ExternalTabContainer() {
[email protected]632fbb12009-09-06 15:27:1461 Uninitialize();
initial.commit09911bf2008-07-26 23:55:2962}
63
[email protected]9095e982009-05-27 17:28:2464bool ExternalTabContainer::Init(Profile* profile,
65 HWND parent,
66 const gfx::Rect& bounds,
[email protected]95c3c592009-07-14 22:09:0367 DWORD style,
[email protected]5f450e52009-07-28 13:28:1168 bool load_requests_via_automation,
[email protected]a50a4902009-08-14 22:39:0169 bool handle_top_level_requests,
[email protected]f5cde2b2009-09-11 22:33:5870 TabContents* existing_contents,
[email protected]7de487c2009-12-18 21:07:5371 const GURL& initial_url,
72 const GURL& referrer) {
initial.commit09911bf2008-07-26 23:55:2973 if (IsWindow()) {
74 NOTREACHED();
75 return false;
76 }
[email protected]0498f7f82009-02-24 03:04:1277
[email protected]95c3c592009-07-14 22:09:0378 load_requests_via_automation_ = load_requests_via_automation;
[email protected]a50a4902009-08-14 22:39:0179 handle_top_level_requests_ = handle_top_level_requests;
[email protected]95c3c592009-07-14 22:09:0380
[email protected]6603fe92009-08-05 17:05:5781 set_window_style(WS_POPUP | WS_CLIPCHILDREN);
[email protected]82166b62009-06-30 18:48:0082 views::WidgetWin::Init(NULL, bounds);
[email protected]08ed00a2009-05-28 20:48:1483 if (!IsWindow()) {
84 NOTREACHED();
85 return false;
86 }
[email protected]f5cde2b2009-09-11 22:33:5887
[email protected]82166b62009-06-30 18:48:0088 // TODO(jcampan): limit focus traversal to contents.
initial.commit09911bf2008-07-26 23:55:2989
90 // We don't ever remove the prop because the lifetime of this object
91 // is the same as the lifetime of the window
[email protected]9095e982009-05-27 17:28:2492 SetProp(GetNativeView(), kWindowObjectKey, this);
initial.commit09911bf2008-07-26 23:55:2993
[email protected]632fbb12009-09-06 15:27:1494 if (existing_contents) {
[email protected]a50a4902009-08-14 22:39:0195 tab_contents_ = existing_contents;
[email protected]632fbb12009-09-06 15:27:1496 tab_contents_->controller().set_profile(profile);
97 } else {
[email protected]12636df2009-09-28 22:32:2198 tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL);
[email protected]632fbb12009-09-06 15:27:1499 }
[email protected]a50a4902009-08-14 22:39:01100
initial.commit09911bf2008-07-26 23:55:29101 tab_contents_->set_delegate(this);
[email protected]632fbb12009-09-06 15:27:14102
[email protected]5f450e52009-07-28 13:28:11103 tab_contents_->GetMutableRendererPrefs()->browser_handles_top_level_requests =
104 handle_top_level_requests;
[email protected]a50a4902009-08-14 22:39:01105
106 if (!existing_contents) {
107 tab_contents_->render_view_host()->AllowBindings(
108 BindingsPolicy::EXTERNAL_HOST);
109 }
[email protected]18cb2572008-08-21 20:34:45110
[email protected]ce3fa3c2009-04-20 19:55:57111 NavigationController* controller = &tab_contents_->controller();
[email protected]bfd04a62009-02-01 18:16:56112 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]0e8db942008-09-24 21:21:48113 Source<NavigationController>(controller));
[email protected]2e39d2e2009-02-19 18:41:31114 registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
115 Source<NavigationController>(controller));
[email protected]33ee8da2009-04-16 17:45:37116 registrar_.Add(this, NotificationType::LOAD_STOP,
117 Source<NavigationController>(controller));
[email protected]2e4633c2009-07-09 16:58:06118 registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
119 Source<TabContents>(tab_contents_));
120 registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
121 Source<TabContents>(tab_contents_));
122
[email protected]bfd04a62009-02-01 18:16:56123 NotificationService::current()->Notify(
124 NotificationType::EXTERNAL_TAB_CREATED,
125 Source<NavigationController>(controller),
126 NotificationService::NoDetails());
[email protected]31fb110522009-01-28 21:50:39127
[email protected]f5cde2b2009-09-11 22:33:58128 // Start loading initial URL
129 if (!initial_url.is_empty()) {
130 // Navigate out of context since we don't have a 'tab_handle_' yet.
[email protected]24f98bba2009-10-14 18:47:49131 MessageLoop::current()->PostTask(
132 FROM_HERE,
133 external_method_factory_.NewRunnableMethod(
[email protected]7de487c2009-12-18 21:07:53134 &ExternalTabContainer::Navigate, initial_url, referrer));
[email protected]f5cde2b2009-09-11 22:33:58135 }
136
[email protected]0498f7f82009-02-24 03:04:12137 // We need WS_POPUP to be on the window during initialization, but
138 // once initialized we apply the requested style which may or may not
139 // include the popup bit.
140 // Note that it's important to do this before we call SetParent since
141 // during the SetParent call we will otherwise get a WA_ACTIVATE call
142 // that causes us to steal the current focus.
[email protected]9095e982009-05-27 17:28:24143 SetWindowLong(GWL_STYLE, (GetWindowLong(GWL_STYLE) & ~WS_POPUP) | style);
[email protected]0498f7f82009-02-24 03:04:12144
[email protected]31fb110522009-01-28 21:50:39145 // Now apply the parenting and style
146 if (parent)
[email protected]9095e982009-05-27 17:28:24147 SetParent(GetNativeView(), parent);
[email protected]7e503122009-02-04 21:52:48148
[email protected]0498f7f82009-02-24 03:04:12149 ::ShowWindow(tab_contents_->GetNativeView(), SW_SHOWNA);
[email protected]e943d6662009-06-12 03:50:39150
151 disabled_context_menu_ids_.push_back(
152 IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD);
[email protected]3f70c1e12010-01-12 20:38:49153 LoadAccelerators();
[email protected]ab861b42010-02-05 19:13:44154 SetupExternalTabView();
initial.commit09911bf2008-07-26 23:55:29155 return true;
156}
157
[email protected]632fbb12009-09-06 15:27:14158void ExternalTabContainer::Uninitialize() {
[email protected]4cfc1d922009-11-08 14:02:58159 if (enabled_extension_automation_) {
160 AutomationExtensionFunction::Disable();
161 }
162
[email protected]632fbb12009-09-06 15:27:14163 registrar_.RemoveAll();
164 if (tab_contents_) {
[email protected]52933842009-09-29 03:44:06165 RenderViewHost* rvh = tab_contents_->render_view_host();
[email protected]5951b5c12010-02-22 18:15:34166 if (rvh) {
167 if (DevToolsManager::GetInstance())
168 DevToolsManager::GetInstance()->UnregisterDevToolsClientHostFor(rvh);
169
[email protected]fd571bb2010-03-19 01:23:54170 UnregisterRenderViewHost(rvh);
[email protected]52933842009-09-29 03:44:06171 }
172
[email protected]632fbb12009-09-06 15:27:14173 NotificationService::current()->Notify(
174 NotificationType::EXTERNAL_TAB_CLOSED,
175 Source<NavigationController>(&tab_contents_->controller()),
176 Details<ExternalTabContainer>(this));
177
178 delete tab_contents_;
179 tab_contents_ = NULL;
180 }
[email protected]1a98a932009-11-17 00:12:52181
[email protected]3f70c1e12010-01-12 20:38:49182 views::FocusManager* focus_manager = GetFocusManager();
183 if (focus_manager) {
184 focus_manager->UnregisterAccelerators(this);
185 }
186
[email protected]13c30922009-11-19 03:43:19187 request_context_ = NULL;
[email protected]ab861b42010-02-05 19:13:44188 tab_contents_container_ = NULL;
[email protected]632fbb12009-09-06 15:27:14189}
190
191bool ExternalTabContainer::Reinitialize(
192 AutomationProvider* automation_provider,
193 AutomationResourceMessageFilter* filter) {
194 if (!automation_provider || !filter) {
195 NOTREACHED();
196 return false;
197 }
198
199 automation_ = automation_provider;
200 automation_resource_message_filter_ = filter;
201
202 if (load_requests_via_automation_) {
[email protected]5c4f4f62009-12-17 21:43:15203 InitializeAutomationRequestContext(tab_handle_);
204
[email protected]632fbb12009-09-06 15:27:14205 RenderViewHost* rvh = tab_contents_->render_view_host();
206 if (rvh) {
[email protected]18290eb2010-01-30 00:47:06207 AutomationResourceMessageFilter::ResumePendingRenderView(
[email protected]632fbb12009-09-06 15:27:14208 rvh->process()->id(), rvh->routing_id(),
209 tab_handle_, automation_resource_message_filter_);
210 }
[email protected]632fbb12009-09-06 15:27:14211 }
212
[email protected]24f98bba2009-10-14 18:47:49213 // We cannot send the navigation state right away as the automation channel
214 // may not have been fully setup yet.
215 MessageLoop::current()->PostTask(
216 FROM_HERE,
217 external_method_factory_.NewRunnableMethod(
[email protected]18290eb2010-01-30 00:47:06218 &ExternalTabContainer::OnReinitialize));
[email protected]632fbb12009-09-06 15:27:14219 return true;
220}
221
[email protected]1a98a932009-11-17 00:12:52222void ExternalTabContainer::SetTabHandle(int handle) {
223 tab_handle_ = handle;
[email protected]5c4f4f62009-12-17 21:43:15224 if (automation_resource_message_filter_.get() &&
225 load_requests_via_automation_) {
226 InitializeAutomationRequestContext(tab_handle_);
[email protected]18fca4e2009-12-17 20:17:36227 }
[email protected]1a98a932009-11-17 00:12:52228}
229
[email protected]9095e982009-05-27 17:28:24230void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) {
[email protected]3f70c1e12010-01-12 20:38:49231 NativeWebKeyboardEvent keyboard_event(msg.hwnd, msg.message, msg.wParam,
232 msg.lParam);
233 unhandled_keyboard_event_handler_.HandleKeyboardEvent(keyboard_event,
234 GetFocusManager());
[email protected]9095e982009-05-27 17:28:24235}
236
[email protected]90daadb42009-06-08 21:27:28237void ExternalTabContainer::FocusThroughTabTraversal(bool reverse) {
[email protected]9095e982009-05-27 17:28:24238 DCHECK(tab_contents_);
[email protected]6331e0b2010-02-23 19:36:10239 if (tab_contents_)
240 tab_contents_->Focus();
241
242 // The tab_contents_ member can get destroyed in the context of the call to
243 // TabContentsViewWin::Focus() above. This method eventually calls SetFocus
244 // on the native window, which could end up dispatching messages like
245 // WM_DESTROY for the external tab.
246 if (tab_contents_)
247 tab_contents_->FocusThroughTabTraversal(reverse);
initial.commit09911bf2008-07-26 23:55:29248}
249
[email protected]9095e982009-05-27 17:28:24250// static
251bool ExternalTabContainer::IsExternalTabContainer(HWND window) {
[email protected]2b19e2fe2010-02-16 02:24:18252 if (::GetProp(window, kWindowObjectKey) != NULL)
[email protected]5cdc8bd2009-05-27 23:01:21253 return true;
[email protected]90daadb42009-06-08 21:27:28254
[email protected]5cdc8bd2009-05-27 23:01:21255 return false;
initial.commit09911bf2008-07-26 23:55:29256}
257
[email protected]9095e982009-05-27 17:28:24258// static
259ExternalTabContainer* ExternalTabContainer::GetContainerForTab(
260 HWND tab_window) {
261 HWND parent_window = ::GetParent(tab_window);
262 if (!::IsWindow(parent_window)) {
263 return NULL;
initial.commit09911bf2008-07-26 23:55:29264 }
[email protected]9095e982009-05-27 17:28:24265 if (!IsExternalTabContainer(parent_window)) {
266 return NULL;
267 }
268 ExternalTabContainer* container = reinterpret_cast<ExternalTabContainer*>(
269 GetProp(parent_window, kWindowObjectKey));
270 return container;
initial.commit09911bf2008-07-26 23:55:29271}
272
[email protected]2b19e2fe2010-02-16 02:24:18273// static
274ExternalTabContainer*
275 ExternalTabContainer::GetExternalContainerFromNativeWindow(
276 gfx::NativeView native_window) {
277 ExternalTabContainer* tab_container = NULL;
278 if (native_window) {
279 HANDLE handle = ::GetProp(native_window, kWindowObjectKey);
280 tab_container = reinterpret_cast<ExternalTabContainer*>(handle);
281 }
282 return tab_container;
283}
[email protected]9095e982009-05-27 17:28:24284////////////////////////////////////////////////////////////////////////////////
285// ExternalTabContainer, TabContentsDelegate implementation:
[email protected]72baf6762009-05-06 18:45:33286
[email protected]e38f40152008-09-12 23:08:30287void ExternalTabContainer::OpenURLFromTab(TabContents* source,
288 const GURL& url,
[email protected]c0588052008-10-27 23:01:50289 const GURL& referrer,
[email protected]e38f40152008-09-12 23:08:30290 WindowOpenDisposition disposition,
291 PageTransition::Type transition) {
[email protected]18290eb2010-01-30 00:47:06292 if (pending()) {
293 PendingTopLevelNavigation url_request;
294 url_request.disposition = disposition;
295 url_request.transition = transition;
296 url_request.url = url;
297 url_request.referrer = referrer;
298
299 pending_open_url_requests_.push_back(url_request);
300 return;
301 }
302
initial.commit09911bf2008-07-26 23:55:29303 switch (disposition) {
304 case CURRENT_TAB:
[email protected]fba16f52009-04-02 22:30:35305 case SINGLETON_TAB:
initial.commit09911bf2008-07-26 23:55:29306 case NEW_FOREGROUND_TAB:
307 case NEW_BACKGROUND_TAB:
[email protected]5f450e52009-07-28 13:28:11308 case NEW_POPUP:
initial.commit09911bf2008-07-26 23:55:29309 case NEW_WINDOW:
[email protected]5f450e52009-07-28 13:28:11310 case SAVE_TO_DISK:
initial.commit09911bf2008-07-26 23:55:29311 if (automation_) {
[email protected]eac83f02009-05-08 18:44:44312 automation_->Send(new AutomationMsg_OpenURL(0, tab_handle_,
[email protected]b36a9f92009-10-19 17:34:57313 url, referrer,
314 disposition));
initial.commit09911bf2008-07-26 23:55:29315 }
316 break;
317 default:
[email protected]5f450e52009-07-28 13:28:11318 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29319 break;
[email protected]6dfed102009-04-28 03:09:53320 }
initial.commit09911bf2008-07-26 23:55:29321}
322
323void ExternalTabContainer::NavigationStateChanged(const TabContents* source,
[email protected]b9d227492009-02-10 15:20:27324 unsigned changed_flags) {
initial.commit09911bf2008-07-26 23:55:29325 if (automation_) {
[email protected]4150ef02009-08-19 23:14:26326 IPC::NavigationInfo nav_info;
[email protected]6c908bb2009-08-21 19:03:50327 if (InitNavigationInfo(&nav_info, NavigationType::NAV_IGNORE, 0))
328 automation_->Send(new AutomationMsg_NavigationStateChanged(
329 0, tab_handle_, changed_flags, nav_info));
initial.commit09911bf2008-07-26 23:55:29330 }
331}
332
initial.commit09911bf2008-07-26 23:55:29333void ExternalTabContainer::AddNewContents(TabContents* source,
334 TabContents* new_contents,
335 WindowOpenDisposition disposition,
336 const gfx::Rect& initial_pos,
337 bool user_gesture) {
[email protected]6f526082010-01-28 19:36:58338 DCHECK(automation_ != NULL);
[email protected]a50a4902009-08-14 22:39:01339
[email protected]6f526082010-01-28 19:36:58340 scoped_refptr<ExternalTabContainer> new_container =
341 new ExternalTabContainer(NULL, NULL);
[email protected]a50a4902009-08-14 22:39:01342
[email protected]6f526082010-01-28 19:36:58343 // Make sure that ExternalTabContainer instance is initialized with
344 // an unwrapped Profile.
345 bool result = new_container->Init(
346 new_contents->profile()->GetOriginalProfile(),
347 NULL,
348 initial_pos,
349 WS_CHILD,
350 load_requests_via_automation_,
351 handle_top_level_requests_,
352 new_contents,
353 GURL(),
354 GURL());
[email protected]a50a4902009-08-14 22:39:01355
[email protected]6f526082010-01-28 19:36:58356 if (result) {
[email protected]b1c55638612010-03-08 16:26:11357 uintptr_t cookie = reinterpret_cast<uintptr_t>(new_container.get());
358 pending_tabs_[cookie] = new_container;
[email protected]18290eb2010-01-30 00:47:06359 new_container->set_pending(true);
[email protected]b1c55638612010-03-08 16:26:11360 IPC::AttachExternalTabParams attach_params_;
361 attach_params_.cookie = static_cast<uint64>(cookie);
362 attach_params_.dimensions = initial_pos;
363 attach_params_.user_gesture = user_gesture;
364 attach_params_.disposition = disposition;
365 automation_->Send(new AutomationMsg_AttachExternalTab(0,
366 tab_handle_, attach_params_));
[email protected]6f526082010-01-28 19:36:58367 } else {
368 NOTREACHED();
[email protected]9f5b80a2009-04-08 01:26:07369 }
initial.commit09911bf2008-07-26 23:55:29370}
371
[email protected]5951b5c12010-02-22 18:15:34372void ExternalTabContainer::TabContentsCreated(TabContents* new_contents) {
373 RenderViewHost* rvh = new_contents->render_view_host();
374 DCHECK(rvh != NULL);
[email protected]fd571bb2010-03-19 01:23:54375
376 // Register this render view as a pending render view, i.e. any network
377 // requests initiated by this render view would be serviced when the
378 // external host connects to the new external tab instance.
379 RegisterRenderViewHostForAutomation(rvh, true);
[email protected]5951b5c12010-02-22 18:15:34380}
381
initial.commit09911bf2008-07-26 23:55:29382void ExternalTabContainer::ActivateContents(TabContents* contents) {
383}
384
385void ExternalTabContainer::LoadingStateChanged(TabContents* source) {
386}
387
388void ExternalTabContainer::CloseContents(TabContents* source) {
[email protected]e56e96f82010-02-03 21:38:08389 static const int kExternalTabCloseContentsDelayMS = 100;
390
[email protected]085d9cf2010-01-27 01:11:02391 if (waiting_for_unload_event_) {
[email protected]e56e96f82010-02-03 21:38:08392 // If we are not the innermost tab waiting for the unload event to return
393 // then don't handle this notification right away as we need the inner
394 // message loop to terminate.
395 if (this != innermost_tab_for_unload_event_) {
396 ChromeThread::PostDelayedTask(
397 ChromeThread::UI, FROM_HERE,
398 NewRunnableMethod(this, &ExternalTabContainer::CloseContents,
399 source), kExternalTabCloseContentsDelayMS);
400 return;
401 }
[email protected]085d9cf2010-01-27 01:11:02402 MessageLoop::current()->Quit();
403 }
initial.commit09911bf2008-07-26 23:55:29404}
405
[email protected]b9d227492009-02-10 15:20:27406void ExternalTabContainer::MoveContents(TabContents* source,
407 const gfx::Rect& pos) {
initial.commit09911bf2008-07-26 23:55:29408}
409
410bool ExternalTabContainer::IsPopup(TabContents* source) {
411 return false;
412}
413
[email protected]b9d227492009-02-10 15:20:27414void ExternalTabContainer::URLStarredChanged(TabContents* source,
415 bool starred) {
initial.commit09911bf2008-07-26 23:55:29416}
417
418void ExternalTabContainer::UpdateTargetURL(TabContents* source,
419 const GURL& url) {
420 if (automation_) {
421 std::wstring url_string = CA2W(url.spec().c_str());
422 automation_->Send(
[email protected]eac83f02009-05-08 18:44:44423 new AutomationMsg_UpdateTargetUrl(0, tab_handle_, url_string));
initial.commit09911bf2008-07-26 23:55:29424 }
425}
426
427void ExternalTabContainer::ContentsZoomChange(bool zoom_in) {
428}
429
430void ExternalTabContainer::ToolbarSizeChanged(TabContents* source,
[email protected]b9d227492009-02-10 15:20:27431 bool finished) {
initial.commit09911bf2008-07-26 23:55:29432}
433
[email protected]18cb2572008-08-21 20:34:45434void ExternalTabContainer::ForwardMessageToExternalHost(
[email protected]28790922009-03-09 19:48:37435 const std::string& message, const std::string& origin,
436 const std::string& target) {
[email protected]4c540ee2009-07-07 17:15:55437 if (automation_) {
[email protected]5e40e262008-08-15 20:33:28438 automation_->Send(
[email protected]eac83f02009-05-08 18:44:44439 new AutomationMsg_ForwardMessageToExternalHost(0, tab_handle_,
440 message, origin, target));
[email protected]5e40e262008-08-15 20:33:28441 }
442}
443
[email protected]a95631cb2009-12-10 01:59:11444gfx::NativeWindow ExternalTabContainer::GetFrameNativeWindow() {
445 return hwnd();
446}
447
[email protected]1e0a02d62009-04-23 22:55:56448bool ExternalTabContainer::TakeFocus(bool reverse) {
449 if (automation_) {
[email protected]48fcc7302009-06-03 18:16:05450 automation_->Send(new AutomationMsg_TabbedOut(0, tab_handle_,
451 win_util::IsShiftPressed()));
[email protected]1e0a02d62009-04-23 22:55:56452 }
453
454 return true;
455}
456
[email protected]fc6fb7fb2009-11-07 02:35:04457bool ExternalTabContainer::CanDownload(int request_id) {
458 if (load_requests_via_automation_) {
459 if (automation_) {
[email protected]62bb18dc12009-11-25 01:34:08460 // In case the host needs to show UI that needs to take the focus.
461 ::AllowSetForegroundWindow(ASFW_ANY);
462
[email protected]dda7d9c2009-11-11 23:01:47463 ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
[email protected]37b76dc2009-12-02 00:48:55464 NewRunnableMethod(automation_resource_message_filter_.get(),
[email protected]dda7d9c2009-11-11 23:01:47465 &AutomationResourceMessageFilter::SendDownloadRequestToHost,
466 0, tab_handle_, request_id));
[email protected]fc6fb7fb2009-11-07 02:35:04467 }
468 } else {
469 DLOG(WARNING) << "Downloads are only supported with host browser network "
470 "stack enabled.";
471 }
472
473 // Never allow downloads.
474 return false;
475}
476
[email protected]21e302e2009-09-12 23:10:41477void ExternalTabContainer::ShowPageInfo(Profile* profile,
478 const GURL& url,
479 const NavigationEntry::SSLStatus& ssl,
480 bool show_history) {
[email protected]fc6fb7fb2009-11-07 02:35:04481 browser::ShowPageInfo(GetNativeView(), profile, url, ssl, show_history);
[email protected]21e302e2009-09-12 23:10:41482}
483
[email protected]fd571bb2010-03-19 01:23:54484void ExternalTabContainer::RegisterRenderViewHostForAutomation(
485 RenderViewHost* render_view_host, bool pending_view) {
486 if (render_view_host) {
487 AutomationResourceMessageFilter::RegisterRenderView(
488 render_view_host->process()->id(),
489 render_view_host->routing_id(),
490 tab_handle(),
491 automation_resource_message_filter_,
492 pending_view);
493 }
494}
495
496
497void ExternalTabContainer::RegisterRenderViewHost(
498 RenderViewHost* render_view_host) {
499 // RenderViewHost instances that are to be associated with this
500 // ExternalTabContainer should share the same resource request automation
501 // settings.
502 RegisterRenderViewHostForAutomation(
503 render_view_host,
504 false); // Network requests should not be handled later.
505}
506
507void ExternalTabContainer::UnregisterRenderViewHost(
508 RenderViewHost* render_view_host) {
509 // Undo the resource automation registration performed in
510 // ExternalTabContainer::RegisterRenderViewHost.
511 if (render_view_host) {
512 AutomationResourceMessageFilter::UnRegisterRenderView(
513 render_view_host->process()->id(),
514 render_view_host->routing_id());
515 }
516}
517
[email protected]e943d6662009-06-12 03:50:39518bool ExternalTabContainer::HandleContextMenu(const ContextMenuParams& params) {
519 if (!automation_) {
520 NOTREACHED();
521 return false;
522 }
523
524 external_context_menu_.reset(
525 new RenderViewContextMenuExternalWin(tab_contents(),
526 params,
[email protected]e943d6662009-06-12 03:50:39527 disabled_context_menu_ids_));
528 external_context_menu_->Init();
529
530 POINT screen_pt = { params.x, params.y };
531 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1);
532
[email protected]35f13ab2009-12-16 23:59:17533 IPC::ContextMenuParams ipc_params;
534 ipc_params.screen_x = screen_pt.x;
535 ipc_params.screen_y = screen_pt.y;
536 ipc_params.link_url = params.link_url;
537 ipc_params.unfiltered_link_url = params.unfiltered_link_url;
538 ipc_params.src_url = params.src_url;
539 ipc_params.page_url = params.page_url;
540 ipc_params.frame_url = params.frame_url;
541
[email protected]4c540ee2009-07-07 17:15:55542 bool rtl = l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT;
[email protected]e943d6662009-06-12 03:50:39543 automation_->Send(
544 new AutomationMsg_ForwardContextMenuToExternalHost(0, tab_handle_,
[email protected]35f13ab2009-12-16 23:59:17545 external_context_menu_->GetMenuHandle(),
546 rtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN, ipc_params));
[email protected]e943d6662009-06-12 03:50:39547
548 return true;
549}
550
551bool ExternalTabContainer::ExecuteContextMenuCommand(int command) {
552 if (!external_context_menu_.get()) {
553 NOTREACHED();
554 return false;
555 }
556
[email protected]35f13ab2009-12-16 23:59:17557 switch (command) {
558 case IDS_CONTENT_CONTEXT_SAVEAUDIOAS:
559 case IDS_CONTENT_CONTEXT_SAVEVIDEOAS:
560 case IDS_CONTENT_CONTEXT_SAVEIMAGEAS:
561 case IDS_CONTENT_CONTEXT_SAVELINKAS: {
562 NOTREACHED(); // Should be handled in host.
563 break;
564 }
565 }
566
[email protected]e943d6662009-06-12 03:50:39567 external_context_menu_->ExecuteCommand(command);
568 return true;
569}
570
[email protected]867125a02009-12-10 06:01:48571bool ExternalTabContainer::PreHandleKeyboardEvent(
572 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
573 return false;
574}
575
576void ExternalTabContainer::HandleKeyboardEvent(
[email protected]334a105b2009-07-14 03:42:55577 const NativeWebKeyboardEvent& event) {
[email protected]867125a02009-12-10 06:01:48578 ProcessUnhandledKeyStroke(event.os_event.hwnd, event.os_event.message,
579 event.os_event.wParam, event.os_event.lParam);
[email protected]334a105b2009-07-14 03:42:55580}
581
[email protected]36cf19b92009-07-22 18:07:51582void ExternalTabContainer::ShowHtmlDialog(HtmlDialogUIDelegate* delegate,
583 gfx::NativeWindow parent_window) {
584 if (!browser_.get()) {
585 browser_.reset(Browser::CreateForPopup(tab_contents_->profile()));
586 }
587
588 gfx::NativeWindow parent = parent_window ? parent_window
589 : GetParent();
590 browser_->window()->ShowHTMLDialog(delegate, parent);
591}
592
[email protected]9095e982009-05-27 17:28:24593////////////////////////////////////////////////////////////////////////////////
594// ExternalTabContainer, NotificationObserver implementation:
595
initial.commit09911bf2008-07-26 23:55:29596void ExternalTabContainer::Observe(NotificationType type,
597 const NotificationSource& source,
598 const NotificationDetails& details) {
[email protected]33ee8da2009-04-16 17:45:37599 if (!automation_)
600 return;
601
[email protected]2e39d2e2009-02-19 18:41:31602 static const int kHttpClientErrorStart = 400;
603 static const int kHttpServerErrorEnd = 510;
604
[email protected]bfd04a62009-02-01 18:16:56605 switch (type.value) {
[email protected]33ee8da2009-04-16 17:45:37606 case NotificationType::LOAD_STOP: {
607 const LoadNotificationDetails* load =
608 Details<LoadNotificationDetails>(details).ptr();
[email protected]d86153f2009-05-18 21:10:52609 if (load != NULL && PageTransition::IsMainFrame(load->origin())) {
[email protected]eac83f02009-05-08 18:44:44610 automation_->Send(new AutomationMsg_TabLoaded(0, tab_handle_,
611 load->url()));
[email protected]33ee8da2009-04-16 17:45:37612 }
613 break;
[email protected]2e39d2e2009-02-19 18:41:31614 }
[email protected]33ee8da2009-04-16 17:45:37615 case NotificationType::NAV_ENTRY_COMMITTED: {
616 if (ignore_next_load_notification_) {
617 ignore_next_load_notification_ = false;
618 return;
619 }
[email protected]2e39d2e2009-02-19 18:41:31620
[email protected]0e8db942008-09-24 21:21:48621 const NavigationController::LoadCommittedDetails* commit =
622 Details<NavigationController::LoadCommittedDetails>(details).ptr();
623
[email protected]f0a51fb52009-03-05 12:46:38624 if (commit->http_status_code >= kHttpClientErrorStart &&
[email protected]2e39d2e2009-02-19 18:41:31625 commit->http_status_code <= kHttpServerErrorEnd) {
626 automation_->Send(new AutomationMsg_NavigationFailed(
[email protected]eac83f02009-05-08 18:44:44627 0, tab_handle_, commit->http_status_code, commit->entry->url()));
[email protected]2e39d2e2009-02-19 18:41:31628
629 ignore_next_load_notification_ = true;
630 } else {
[email protected]4150ef02009-08-19 23:14:26631 IPC::NavigationInfo navigation_info;
[email protected]2e39d2e2009-02-19 18:41:31632 // When the previous entry index is invalid, it will be -1, which
633 // will still make the computation come out right (navigating to the
634 // 0th entry will be +1).
[email protected]6c908bb2009-08-21 19:03:50635 if (InitNavigationInfo(&navigation_info, commit->type,
636 commit->previous_entry_index -
637 tab_contents_->controller().last_committed_entry_index()))
638 automation_->Send(new AutomationMsg_DidNavigate(0, tab_handle_,
639 navigation_info));
[email protected]2e39d2e2009-02-19 18:41:31640 }
[email protected]33ee8da2009-04-16 17:45:37641 break;
[email protected]0e8db942008-09-24 21:21:48642 }
[email protected]2e39d2e2009-02-19 18:41:31643 case NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR: {
[email protected]33ee8da2009-04-16 17:45:37644 const ProvisionalLoadDetails* load_details =
645 Details<ProvisionalLoadDetails>(details).ptr();
646 automation_->Send(new AutomationMsg_NavigationFailed(
[email protected]eac83f02009-05-08 18:44:44647 0, tab_handle_, load_details->error_code(), load_details->url()));
[email protected]2e39d2e2009-02-19 18:41:31648
[email protected]33ee8da2009-04-16 17:45:37649 ignore_next_load_notification_ = true;
[email protected]2e39d2e2009-02-19 18:41:31650 break;
651 }
[email protected]2e4633c2009-07-09 16:58:06652 case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
653 if (load_requests_via_automation_) {
654 RenderViewHost* rvh = Details<RenderViewHost>(details).ptr();
[email protected]fd571bb2010-03-19 01:23:54655 RegisterRenderViewHostForAutomation(rvh, false);
[email protected]2e4633c2009-07-09 16:58:06656 }
657 break;
658 }
659 case NotificationType::RENDER_VIEW_HOST_DELETED: {
660 if (load_requests_via_automation_) {
661 RenderViewHost* rvh = Details<RenderViewHost>(details).ptr();
[email protected]fd571bb2010-03-19 01:23:54662 UnregisterRenderViewHost(rvh);
[email protected]2e4633c2009-07-09 16:58:06663 }
664 break;
665 }
[email protected]0e8db942008-09-24 21:21:48666 default:
667 NOTREACHED();
668 }
initial.commit09911bf2008-07-26 23:55:29669}
670
[email protected]9095e982009-05-27 17:28:24671////////////////////////////////////////////////////////////////////////////////
672// ExternalTabContainer, views::WidgetWin overrides:
673
[email protected]632fbb12009-09-06 15:27:14674LRESULT ExternalTabContainer::OnCreate(LPCREATESTRUCT create_struct) {
675 LRESULT result = views::WidgetWin::OnCreate(create_struct);
676 if (result == 0) {
677 // Grab a reference here which will be released in OnFinalMessage
678 AddRef();
679 }
680 return result;
681}
682
[email protected]9095e982009-05-27 17:28:24683void ExternalTabContainer::OnDestroy() {
[email protected]a6caf0402010-02-19 21:49:04684 if (tab_contents_) {
685 waiting_for_unload_event_ = true;
686 if (Browser::RunUnloadEventsHelper(tab_contents_)) {
687 // Maintain a local global stack of Externa;TabCotainers waiting for the
688 // unload event listeners to finish. We need this as we only want to
689 // handle the CloseContents call from the TabContents when the current
690 // ExternalTabContainers message loop is active. This ensures that nested
691 // ExternalTabContainer message loops terminate correctly.
692 ExternalTabContainer* current_tab = innermost_tab_for_unload_event_;
693 innermost_tab_for_unload_event_ = this;
694 MessageLoop::current()->Run();
695 innermost_tab_for_unload_event_ = current_tab;
696 }
697 waiting_for_unload_event_ = false;
698 }
699
[email protected]632fbb12009-09-06 15:27:14700 Uninitialize();
[email protected]9095e982009-05-27 17:28:24701 WidgetWin::OnDestroy();
[email protected]36cf19b92009-07-22 18:07:51702 if (browser_.get()) {
703 ::DestroyWindow(browser_->window()->GetNativeHandle());
704 }
initial.commit09911bf2008-07-26 23:55:29705}
706
[email protected]632fbb12009-09-06 15:27:14707void ExternalTabContainer::OnFinalMessage(HWND window) {
708 // Release the reference which we grabbed in WM_CREATE.
709 Release();
[email protected]334a105b2009-07-14 03:42:55710}
711
[email protected]632fbb12009-09-06 15:27:14712////////////////////////////////////////////////////////////////////////////////
713// ExternalTabContainer, private:
[email protected]334a105b2009-07-14 03:42:55714bool ExternalTabContainer::ProcessUnhandledKeyStroke(HWND window,
715 UINT message,
716 WPARAM wparam,
717 LPARAM lparam) {
initial.commit09911bf2008-07-26 23:55:29718 if (!automation_) {
719 return false;
720 }
721 if ((wparam == VK_TAB) && !win_util::IsCtrlPressed()) {
722 // Tabs are handled separately (except if this is Ctrl-Tab or
723 // Ctrl-Shift-Tab)
724 return false;
725 }
[email protected]060254c2009-05-02 16:45:27726
[email protected]01dba672010-02-12 21:55:48727 // Send this keystroke to the external host as it could be processed as an
728 // accelerator there. If the host does not handle this accelerator, it will
729 // reflect the accelerator back to us via the ProcessUnhandledAccelerator
730 // method.
731 MSG msg = {0};
732 msg.hwnd = window;
733 msg.message = message;
734 msg.wParam = wparam;
735 msg.lParam = lparam;
736 automation_->Send(new AutomationMsg_HandleAccelerator(0, tab_handle_, msg));
737 return true;
initial.commit09911bf2008-07-26 23:55:29738}
[email protected]4150ef02009-08-19 23:14:26739
[email protected]6c908bb2009-08-21 19:03:50740bool ExternalTabContainer::InitNavigationInfo(IPC::NavigationInfo* nav_info,
[email protected]4150ef02009-08-19 23:14:26741 NavigationType::Type nav_type,
742 int relative_offset) {
[email protected]4150ef02009-08-19 23:14:26743 DCHECK(nav_info);
[email protected]6c908bb2009-08-21 19:03:50744 NavigationEntry* entry = tab_contents_->controller().GetActiveEntry();
745 // If this is very early in the game then we may not have an entry.
746 if (!entry)
747 return false;
[email protected]4150ef02009-08-19 23:14:26748
749 nav_info->navigation_type = nav_type;
750 nav_info->relative_offset = relative_offset;
751 nav_info->navigation_index =
752 tab_contents_->controller().GetCurrentEntryIndex();
[email protected]4150ef02009-08-19 23:14:26753 nav_info->url = entry->url();
[email protected]24f98bba2009-10-14 18:47:49754 nav_info->title = UTF16ToWideHack(entry->title());
755 if (nav_info->title.empty())
756 nav_info->title = UTF8ToWide(nav_info->url.spec());
757
[email protected]f5cde2b2009-09-11 22:33:58758 nav_info->security_style = entry->ssl().security_style();
759 nav_info->has_mixed_content = entry->ssl().has_mixed_content();
[email protected]6c908bb2009-08-21 19:03:50760 return true;
[email protected]4150ef02009-08-19 23:14:26761}
762
[email protected]cd0dec62010-02-11 02:33:18763scoped_refptr<ExternalTabContainer> ExternalTabContainer::RemovePendingTab(
[email protected]b1c55638612010-03-08 16:26:11764 uintptr_t cookie) {
[email protected]632fbb12009-09-06 15:27:14765 PendingTabs::iterator index = pending_tabs_.find(cookie);
766 if (index != pending_tabs_.end()) {
767 scoped_refptr<ExternalTabContainer> container = (*index).second;
768 pending_tabs_.erase(index);
[email protected]cd0dec62010-02-11 02:33:18769 return container;
[email protected]632fbb12009-09-06 15:27:14770 }
771
772 NOTREACHED() << "Failed to find ExternalTabContainer for cookie: "
773 << cookie;
774 return NULL;
775}
776
[email protected]4cfc1d922009-11-08 14:02:58777void ExternalTabContainer::SetEnableExtensionAutomation(
778 const std::vector<std::string>& functions_enabled) {
779 if (functions_enabled.size() > 0) {
780 if (!tab_contents_) {
781 NOTREACHED() << "Being invoked via tab so should have TabContents";
782 return;
783 }
784
785 AutomationExtensionFunction::Enable(tab_contents_, functions_enabled);
786 enabled_extension_automation_ = true;
787 } else {
788 AutomationExtensionFunction::Disable();
789 enabled_extension_automation_ = false;
790 }
791}
792
[email protected]ab861b42010-02-05 19:13:44793void ExternalTabContainer::InfoBarSizeChanged(bool is_animating) {
794 if (GetRootView()) {
795 GetRootView()->Layout();
796 }
797}
798
[email protected]a95631cb2009-12-10 01:59:11799// ExternalTabContainer instances do not have a window.
800views::Window* ExternalTabContainer::GetWindow() {
801 return NULL;
802}
803
[email protected]3f70c1e12010-01-12 20:38:49804bool ExternalTabContainer::AcceleratorPressed(
805 const views::Accelerator& accelerator) {
806 std::map<views::Accelerator, int>::const_iterator iter =
807 accelerator_table_.find(accelerator);
808 DCHECK(iter != accelerator_table_.end());
809
810 if (!tab_contents_ || !tab_contents_->render_view_host()) {
811 NOTREACHED();
812 return false;
813 }
814
815 int command_id = iter->second;
816 switch (command_id) {
817 case IDC_ZOOM_PLUS:
818 tab_contents_->render_view_host()->Zoom(PageZoom::ZOOM_IN);
819 break;
820 case IDC_ZOOM_NORMAL:
821 tab_contents_->render_view_host()->Zoom(PageZoom::RESET);
822 break;
823 case IDC_ZOOM_MINUS:
824 tab_contents_->render_view_host()->Zoom(PageZoom::ZOOM_OUT);
825 break;
826 case IDC_DEV_TOOLS:
827 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
828 tab_contents_->render_view_host(), false);
829 break;
830 case IDC_DEV_TOOLS_CONSOLE:
831 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
832 tab_contents_->render_view_host(), true);
833 break;
834 default:
835 NOTREACHED() << "Unsupported accelerator: " << command_id;
836 return false;
837 }
838 return true;
839}
840
[email protected]f5cde2b2009-09-11 22:33:58841void ExternalTabContainer::Navigate(const GURL& url, const GURL& referrer) {
842 if (!tab_contents_) {
843 NOTREACHED();
844 return;
845 }
846
847 tab_contents_->controller().LoadURL(url, referrer,
848 PageTransition::START_PAGE);
849}
[email protected]f9cc4c452009-10-13 14:56:38850
851bool ExternalTabContainer::OnGoToEntryOffset(int offset) {
852 if (load_requests_via_automation_) {
853 automation_->Send(new AutomationMsg_RequestGoToHistoryEntryOffset(
854 0, tab_handle_, offset));
855 return false;
856 }
857
858 return true;
859}
[email protected]1a98a932009-11-17 00:12:52860
861void ExternalTabContainer::InitializeAutomationRequestContext(
862 int tab_handle) {
[email protected]1a98a932009-11-17 00:12:52863 request_context_ =
864 AutomationRequestContext::CreateAutomationURLRequestContextForTab(
865 tab_handle, tab_contents_->profile(),
866 automation_resource_message_filter_);
867
868 DCHECK(request_context_.get() != NULL);
869 tab_contents_->set_request_context(request_context_.get());
870}
[email protected]3f70c1e12010-01-12 20:38:49871
872void ExternalTabContainer::LoadAccelerators() {
873 HACCEL accelerator_table = AtlLoadAccelerators(IDR_CHROMEFRAME);
874 DCHECK(accelerator_table);
875
876 // We have to copy the table to access its contents.
877 int count = CopyAcceleratorTable(accelerator_table, 0, 0);
878 if (count == 0) {
879 // Nothing to do in that case.
880 return;
881 }
882
883 scoped_ptr<ACCEL> scoped_accelerators(new ACCEL[count]);
884 ACCEL* accelerators = scoped_accelerators.get();
885 DCHECK(accelerators != NULL);
886
887 CopyAcceleratorTable(accelerator_table, accelerators, count);
888
889 views::FocusManager* focus_manager = GetFocusManager();
890 DCHECK(focus_manager);
891
892 // Let's fill our own accelerator table.
893 for (int i = 0; i < count; ++i) {
894 bool alt_down = (accelerators[i].fVirt & FALT) == FALT;
895 bool ctrl_down = (accelerators[i].fVirt & FCONTROL) == FCONTROL;
896 bool shift_down = (accelerators[i].fVirt & FSHIFT) == FSHIFT;
897 views::Accelerator accelerator(
898 static_cast<base::KeyboardCode>(accelerators[i].key),
899 shift_down, ctrl_down, alt_down);
900 accelerator_table_[accelerator] = accelerators[i].cmd;
901
902 // Also register with the focus manager.
903 focus_manager->RegisterAccelerator(accelerator, this);
904 }
905}
[email protected]18290eb2010-01-30 00:47:06906
907void ExternalTabContainer::OnReinitialize() {
908 NavigationStateChanged(tab_contents_, 0);
909 ServicePendingOpenURLRequests();
910}
911
912void ExternalTabContainer::ServicePendingOpenURLRequests() {
913 DCHECK(pending());
914
915 set_pending(false);
916
917 for (size_t index = 0; index < pending_open_url_requests_.size();
918 index ++) {
919 const PendingTopLevelNavigation& url_request =
920 pending_open_url_requests_[index];
921 OpenURLFromTab(tab_contents_, url_request.url, url_request.referrer,
922 url_request.disposition, url_request.transition);
923 }
924 pending_open_url_requests_.clear();
925}
926
[email protected]ab861b42010-02-05 19:13:44927void ExternalTabContainer::SetupExternalTabView() {
928 // Create a TabContentsContainer to handle focus cycling using Tab and
929 // Shift-Tab.
930 tab_contents_container_ = new TabContentsContainer;
931
932 // The views created here will be destroyed when the ExternalTabContainer
933 // widget is torn down.
934 views::View* external_tab_view = new views::View();
935
936 InfoBarContainer* info_bar_container = new InfoBarContainer(this);
937 info_bar_container->ChangeTabContents(tab_contents_);
938
939 views::GridLayout* layout = new views::GridLayout(external_tab_view);
940 views::ColumnSet* columns = layout->AddColumnSet(0); // Give this column an
941 // identifier of 0.
942 columns->AddColumn(views::GridLayout::FILL,
943 views::GridLayout::FILL,
944 1,
945 views::GridLayout::USE_PREF,
946 0,
947 0);
948
949 external_tab_view->SetLayoutManager(layout);
950
951 layout->StartRow(0, 0);
952 layout->AddView(info_bar_container);
953 layout->StartRow(1, 0);
954 layout->AddView(tab_contents_container_);
955 SetContentsView(external_tab_view);
956 // Note that SetTabContents must be called after AddChildView is called
957 tab_contents_container_->ChangeTabContents(tab_contents_);
958}
959