1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/views/external_tab_container_win.h"
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/debug/trace_event.h"
17 #include "base/i18n/rtl.h"
18 #include "base/logging.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/strings/string16.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/time/time.h"
23 #include "base/win/win_util.h"
24 #include "chrome/app/chrome_command_ids.h"
25 #include "chrome/app/chrome_dll_resource.h"
26 #include "chrome/browser/automation/automation_provider.h"
27 #include "chrome/browser/chrome_notification_types.h"
28 #include "chrome/browser/devtools/devtools_toggle_action.h"
29 #include "chrome/browser/devtools/devtools_window.h"
30 #include "chrome/browser/file_select_helper.h"
31 #include "chrome/browser/history/history_tab_helper.h"
32 #include "chrome/browser/history/history_types.h"
33 #include "chrome/browser/infobars/infobar_service.h"
34 #include "chrome/browser/media/media_stream_infobar_delegate.h"
35 #include "chrome/browser/pepper_broker_infobar_delegate.h"
36 #include "chrome/browser/profiles/profile.h"
37 #include "chrome/browser/repost_form_warning_controller.h"
38 #include "chrome/browser/themes/theme_properties.h"
39 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
40 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
41 #include "chrome/browser/ui/browser.h"
42 #include "chrome/browser/ui/browser_dialogs.h"
43 #include "chrome/browser/ui/browser_tab_contents.h"
44 #include "chrome/browser/ui/browser_window.h"
45 #include "chrome/browser/ui/tab_modal_confirm_dialog.h"
46 #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
47 #include "chrome/browser/ui/views/tab_contents/render_view_context_menu_win.h"
48 #include "chrome/common/automation_messages.h"
49 #include "chrome/common/chrome_constants.h"
50 #include "chrome/common/render_messages.h"
51 #include "chrome/common/url_constants.h"
52 #include "content/public/browser/load_notification_details.h"
53 #include "content/public/browser/native_web_keyboard_event.h"
54 #include "content/public/browser/navigation_details.h"
55 #include "content/public/browser/navigation_entry.h"
56 #include "content/public/browser/notification_service.h"
57 #include "content/public/browser/render_process_host.h"
58 #include "content/public/browser/render_view_host.h"
59 #include "content/public/browser/web_contents.h"
60 #include "content/public/browser/web_contents_view.h"
61 #include "content/public/common/bindings_policy.h"
62 #include "content/public/common/frame_navigate_params.h"
63 #include "content/public/common/page_transition_types.h"
64 #include "content/public/common/page_zoom.h"
65 #include "content/public/common/renderer_preferences.h"
66 #include "content/public/common/ssl_status.h"
67 #include "grit/generated_resources.h"
68 #include "grit/locale_settings.h"
69 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
70 #include "ui/base/events/event_utils.h"
71 #include "ui/base/l10n/l10n_util.h"
72 #include "ui/base/models/menu_model.h"
73 #include "ui/base/view_prop.h"
74 #include "ui/views/controls/webview/webview.h"
75 #include "ui/views/layout/grid_layout.h"
76 #include "ui/views/widget/widget.h"
77 #include "ui/views/win/hwnd_util.h"
80 #include "ui/aura/root_window.h"
81 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
82 #include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h"
85 using content::BrowserThread
;
86 using content::LoadNotificationDetails
;
87 using content::NativeWebKeyboardEvent
;
88 using content::NavigationController
;
89 using content::NavigationEntry
;
90 using content::OpenURLParams
;
91 using content::RenderViewHost
;
92 using content::SSLStatus
;
93 using content::WebContents
;
94 using WebKit::WebReferrerPolicy
;
98 static const char kWindowObjectKey
[] = "ChromeWindowObject";
100 // The following helper functions exist to localize UI toolkit-specific code.
102 void ShowNativeView(gfx::NativeView view
) {
103 #if !defined(USE_AURA)
104 ::ShowWindow(view
, SW_SHOWNA
);
108 scoped_ptr
<content::NativeWebKeyboardEvent
> CreateKeyboardEvent(
110 #if defined(USE_AURA)
111 // TODO(grt): confirm that this is a translated character event.
112 ui::KeyEvent
key_event(msg
, true);
113 return scoped_ptr
<content::NativeWebKeyboardEvent
>(
114 new content::NativeWebKeyboardEvent(&key_event
));
116 return scoped_ptr
<content::NativeWebKeyboardEvent
>(
117 new content::NativeWebKeyboardEvent(msg
));
121 const MSG
& MessageFromKeyboardEvent(
122 const content::NativeWebKeyboardEvent
& event
) {
123 #if defined(USE_AURA)
124 DCHECK(event
.os_event
);
125 return event
.os_event
->native_event();
127 return event
.os_event
;
131 // Convert ui::MenuModel into a serializable form for Chrome Frame
132 ContextMenuModel
* ConvertMenuModel(const ui::MenuModel
* ui_model
) {
133 ContextMenuModel
* new_model
= new ContextMenuModel
;
135 const int item_count
= ui_model
->GetItemCount();
136 new_model
->items
.reserve(item_count
);
137 for (int i
= 0; i
< item_count
; ++i
) {
138 if (ui_model
->IsVisibleAt(i
)) {
139 ContextMenuModel::Item item
;
140 item
.type
= ui_model
->GetTypeAt(i
);
141 item
.item_id
= ui_model
->GetCommandIdAt(i
);
142 item
.label
= ui_model
->GetLabelAt(i
);
143 item
.checked
= ui_model
->IsItemCheckedAt(i
);
144 item
.enabled
= ui_model
->IsEnabledAt(i
);
145 if (item
.type
== ui::MenuModel::TYPE_SUBMENU
)
146 item
.submenu
= ConvertMenuModel(ui_model
->GetSubmenuModelAt(i
));
148 new_model
->items
.push_back(item
);
155 // Generates a referrer header used by the AutomationProvider on navigation.
156 // Based on code from
157 // http://src.chromium.org/viewvc/blink/trunk/Source/weborigin/SecurityPolicy.cpp?revision=151498
158 bool ShouldHideReferrer(const GURL
& url
, const GURL
& referrer
) {
159 bool referrer_is_secure
= referrer
.SchemeIsSecure();
160 bool referrer_is_web_url
= referrer_is_secure
|| referrer
.SchemeIs("http");
162 if (!referrer_is_web_url
)
165 if (!referrer_is_secure
)
168 return !url
.SchemeIsSecure();
171 GURL
GenerateReferrer(WebKit::WebReferrerPolicy policy
,
173 const GURL
& referrer
) {
174 if (referrer
.is_empty())
178 case WebKit::WebReferrerPolicyNever
:
180 case WebKit::WebReferrerPolicyAlways
:
182 case WebKit::WebReferrerPolicyOrigin
:
183 return referrer
.GetOrigin();
188 return ShouldHideReferrer(url
, referrer
) ? GURL() : referrer
;
194 #if defined(USE_AURA)
195 typedef ATL::CWinTraits
<WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
196 WS_EX_NOACTIVATE
| WS_EX_TOOLWINDOW
>
197 ContainerWindowHWNDTraits
;
199 // A window placed in the parent/child hierarchy between the host (e.g., a
200 // ChromeFrameAutomationClient window) and the Aura DesktopRootWindowHostWin.
201 // This non-activatable window is necessary to prevent focus from warping from
202 // the DRWHW up to the CFAC window during reparenting. This is not needed in the
203 // non-Aura case because the ExternalTabContainer's primary widget takes this
204 // role (the RenderWidgetHostViewWin's HWND is a grandchild of it).
205 class ContainerWindow
: public ATL::CWindowImpl
<ContainerWindow
,
207 ContainerWindowHWNDTraits
>,
208 public base::SupportsWeakPtr
<ContainerWindow
> {
210 DECLARE_WND_CLASS_EX(NULL
, CS_DBLCLKS
, 0);
212 BEGIN_MSG_MAP_EX(ContainerWindow
)
214 MSG_WM_SHOWWINDOW(OnShowWindow
)
218 ContainerWindow(HWND parent
, const gfx::Rect
& bounds
) : child_(NULL
) {
219 RECT rect
= bounds
.ToRECT();
220 Create(parent
, rect
);
224 DCHECK(::IsWindow(m_hWnd
));
228 // Sets the child window (the DRWHW). The child is made activateable as part
230 void SetChild(HWND window
) {
235 (::GetWindowLong(window
, GWL_STYLE
) & ~WS_POPUP
) | WS_CHILD
);
236 ::SetWindowLong(window
, GWL_EXSTYLE
,
237 (::GetWindowLong(window
, GWL_EXSTYLE
) & ~WS_EX_NOACTIVATE
));
239 ::SetParent(window
, hwnd());
243 virtual void OnFinalMessage(HWND hwnd
) OVERRIDE
{
248 void OnMove(const CPoint
& position
) {
249 ::SetWindowPos(child_
, NULL
, position
.x
, position
.y
, 0, 0,
250 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
253 void OnShowWindow(BOOL show
, UINT status
) {
254 ::ShowWindow(child_
, SW_SHOWNA
);
257 void OnSize(UINT type
, const CSize
& size
) {
258 ::SetWindowPos(child_
, NULL
, 0, 0, size
.cx
, size
.cy
,
259 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
264 DISALLOW_COPY_AND_ASSIGN(ContainerWindow
);
267 // A specialization of DesktopRootWindowHost for an external tab container that
268 // saves and restores focus as the ETC is blurred and focused. DRWHW ordinarily
269 // does this during window activation and deactivation. Since the ETC is a child
270 // window, it does not receive activation messages.
271 class ExternalTabRootWindowHost
: public views::DesktopRootWindowHostWin
{
273 ExternalTabRootWindowHost(
274 views::internal::NativeWidgetDelegate
* native_widget_delegate
,
275 views::DesktopNativeWidgetAura
* desktop_native_widget_aura
,
276 const gfx::Rect
& initial_bounds
)
277 : views::DesktopRootWindowHostWin(native_widget_delegate
,
278 desktop_native_widget_aura
,
282 // HWNDMessageHandlerDelegate methods:
283 virtual void HandleNativeFocus(HWND last_focused_window
) OVERRIDE
{
284 views::DesktopRootWindowHostWin::HandleNativeFocus(last_focused_window
);
285 RestoreFocusOnActivate();
288 virtual void HandleNativeBlur(HWND focused_window
) OVERRIDE
{
289 SaveFocusOnDeactivate();
290 views::DesktopRootWindowHostWin::HandleNativeBlur(focused_window
);
294 DISALLOW_COPY_AND_ASSIGN(ExternalTabRootWindowHost
);
298 base::LazyInstance
<ExternalTabContainerWin::PendingTabs
>
299 ExternalTabContainerWin::pending_tabs_
= LAZY_INSTANCE_INITIALIZER
;
301 ExternalTabContainerWin::ExternalTabContainerWin(
302 AutomationProvider
* automation
,
303 AutomationResourceMessageFilter
* filter
)
305 automation_(automation
),
306 rvh_callback_(base::Bind(
307 &ExternalTabContainerWin::RegisterRenderViewHostForAutomation
,
308 base::Unretained(this), false)),
309 tab_contents_container_(NULL
),
311 ignore_next_load_notification_(false),
312 automation_resource_message_filter_(filter
),
313 load_requests_via_automation_(false),
314 handle_top_level_requests_(false),
315 route_all_top_level_navigations_(false),
318 focus_manager_(NULL
),
319 external_tab_view_(NULL
),
320 unload_reply_message_(NULL
),
321 is_popup_window_(false) {
325 scoped_refptr
<ExternalTabContainer
>
326 ExternalTabContainerWin::RemovePendingExternalTab(uintptr_t cookie
) {
327 PendingTabs
& pending_tabs
= pending_tabs_
.Get();
328 PendingTabs::iterator index
= pending_tabs
.find(cookie
);
329 if (index
!= pending_tabs
.end()) {
330 scoped_refptr
<ExternalTabContainer
> container
= (*index
).second
;
331 pending_tabs
.erase(index
);
335 NOTREACHED() << "Failed to find ExternalTabContainer for cookie: "
340 bool ExternalTabContainerWin::Init(Profile
* profile
,
342 const gfx::Rect
& bounds
,
344 bool load_requests_via_automation
,
345 bool handle_top_level_requests
,
346 content::WebContents
* existing_contents
,
347 const GURL
& initial_url
,
348 const GURL
& referrer
,
349 bool infobars_enabled
,
350 bool route_all_top_level_navigations
) {
356 widget_
= new views::Widget();
357 widget_
->AddObserver(this);
358 load_requests_via_automation_
= load_requests_via_automation
;
359 handle_top_level_requests_
= handle_top_level_requests
;
360 route_all_top_level_navigations_
= route_all_top_level_navigations
;
362 views::Widget::InitParams
params(views::Widget::InitParams::TYPE_POPUP
);
363 params
.bounds
= bounds
;
364 #if defined(USE_AURA)
365 // Create the window that sits between the parent (most likely a
366 // ChromeFrameAutomationClient) and the DesktopRootWindowHostWin.
367 tab_container_window_
=
368 (new ContainerWindow(HWND_DESKTOP
, params
.bounds
))->AsWeakPtr();
370 views::DesktopNativeWidgetAura
* native_widget
=
371 new views::DesktopNativeWidgetAura(widget_
);
372 params
.native_widget
= native_widget
;
373 params
.desktop_root_window_host
=
374 new ExternalTabRootWindowHost(widget_
, native_widget
, params
.bounds
);
375 params
.type
= views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
;
376 params
.opacity
= views::Widget::InitParams::OPAQUE_WINDOW
;
378 widget_
->Init(params
);
380 #if defined(USE_AURA)
381 tab_container_window_
->SetChild(views::HWNDForWidget(widget_
));
384 // TODO(jcampan): limit focus traversal to contents.
386 prop_
.reset(new ui::ViewProp(views::HWNDForWidget(widget_
), kWindowObjectKey
,
389 if (existing_contents
) {
390 existing_contents
->GetController().SetBrowserContext(profile
);
392 existing_contents
= WebContents::Create(WebContents::CreateParams(profile
));
393 existing_contents
->GetRenderViewHost()->AllowBindings(
394 content::BINDINGS_POLICY_EXTERNAL_HOST
);
397 existing_contents
->SetDelegate(this);
398 existing_contents
->GetMutableRendererPrefs()->
399 browser_handles_non_local_top_level_requests
= handle_top_level_requests
;
401 NavigationController
* controller
= &existing_contents
->GetController();
402 registrar_
.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED
,
403 content::Source
<NavigationController
>(controller
));
404 registrar_
.Add(this, content::NOTIFICATION_LOAD_STOP
,
405 content::Source
<NavigationController
>(controller
));
407 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED
,
408 content::Source
<WebContents
>(existing_contents
));
410 content::RenderViewHost::AddCreatedCallback(rvh_callback_
);
411 content::WebContentsObserver::Observe(existing_contents
);
413 BrowserTabContents::AttachTabHelpers(existing_contents
);
414 web_contents_
.reset(existing_contents
);
416 if (!infobars_enabled
) {
417 InfoBarService::FromWebContents(existing_contents
)->set_infobars_enabled(
421 // Start loading initial URL
422 if (!initial_url
.is_empty()) {
423 // Navigate out of context since we don't have a 'tab_handle_' yet.
424 base::MessageLoop::current()->PostTask(
426 base::Bind(&ExternalTabContainerWin::Navigate
,
427 weak_factory_
.GetWeakPtr(),
432 // We need WS_POPUP to be on the window during initialization, but
433 // once initialized we apply the requested style which may or may not
434 // include the popup bit.
435 // Note that it's important to do this before we call SetParent since
436 // during the SetParent call we will otherwise get a WA_ACTIVATE call
437 // that causes us to steal the current focus.
438 HWND window
= GetExternalTabHWND();
439 SetWindowLong(window
, GWL_STYLE
,
440 (GetWindowLong(window
, GWL_STYLE
) & ~WS_POPUP
) | style
);
442 // Now apply the parenting and style
444 SetParent(window
, parent
);
446 ShowNativeView(existing_contents
->GetView()->GetNativeView());
449 SetupExternalTabView();
450 BlockedContentTabHelper::FromWebContents(existing_contents
)->
455 void ExternalTabContainerWin::Uninitialize() {
456 registrar_
.RemoveAll();
457 content::RenderViewHost::RemoveCreatedCallback(rvh_callback_
);
458 if (web_contents_
.get()) {
459 tab_contents_container_
->SetWebContents(NULL
);
460 UnregisterRenderViewHost(web_contents_
->GetRenderViewHost());
462 // Explicitly tell the RPH to shutdown, as doing so is the only thing that
463 // cleans up certain resources like infobars (crbug.com/148398).
464 // Tell the RPH to shutdown iff it has a page count of 1, meaning that
465 // there is only a single remaining render widget host (the one owned by
466 // web_contents_) using this RPH.
468 // Note that it is not possible to simply call FastShutdownIfPossible on the
469 // RPH here as that unfortunately ignores RPH's internal ref count, which
470 // leaves any other render widget hosts using the same RPH dangling.
472 // Note that in an ideal world, this would not be needed. The WebContents
473 // could just destroy itself, resulting in RPH::Release() eventually getting
474 // called and all would be neat and tidy. Sadly, the RPH only fires
475 // NOTIFICATION_RENDERER_PROCESS_CLOSED if one of the FastShutdownXXX
476 // methods is called and other components rely on that notification to avoid
477 // crashing on shutdown. Sad panda. Or maybe clinically depressed panda is
479 web_contents_
->GetRenderProcessHost()->FastShutdownForPageCount(1);
481 if (widget_
->GetRootView())
482 widget_
->GetRootView()->RemoveAllChildViews(true);
485 content::NotificationService::current()->Notify(
486 chrome::NOTIFICATION_EXTERNAL_TAB_CLOSED
,
487 content::Source
<NavigationController
>(&web_contents_
->GetController()),
488 content::Details
<ExternalTabContainer
>(this));
490 web_contents_
.reset(NULL
);
493 if (focus_manager_
) {
494 focus_manager_
->UnregisterAccelerators(this);
495 focus_manager_
= NULL
;
498 external_tab_view_
= NULL
;
499 request_context_
= NULL
;
500 tab_contents_container_
= NULL
;
503 bool ExternalTabContainerWin::Reinitialize(
504 AutomationProvider
* automation_provider
,
505 AutomationResourceMessageFilter
* filter
,
506 HWND parent_window
) {
507 if (!automation_provider
|| !filter
) {
512 automation_
= automation_provider
;
513 automation_resource_message_filter_
= filter
;
514 // Wait for the automation channel to be initialized before resuming pending
515 // render views and sending in the navigation state.
516 base::MessageLoop::current()->PostTask(
518 base::Bind(&ExternalTabContainerWin::OnReinitialize
,
519 weak_factory_
.GetWeakPtr()));
522 SetParent(GetExternalTabHWND(), parent_window
);
526 WebContents
* ExternalTabContainerWin::GetWebContents() const {
527 return web_contents_
.get();
530 HWND
ExternalTabContainerWin::GetExternalTabHWND() const {
531 #if defined(USE_AURA)
532 return tab_container_window_
.get() ? tab_container_window_
->hwnd() : NULL
;
534 return views::HWNDForWidget(widget_
);
538 HWND
ExternalTabContainerWin::GetContentHWND() const {
539 return views::HWNDForNativeWindow(web_contents_
->GetView()->GetNativeView());
542 void ExternalTabContainerWin::SetTabHandle(int handle
) {
543 tab_handle_
= handle
;
546 int ExternalTabContainerWin::GetTabHandle() const {
550 bool ExternalTabContainerWin::ExecuteContextMenuCommand(int command
) {
551 if (!external_context_menu_
.get()) {
557 case IDS_CONTENT_CONTEXT_SAVEAUDIOAS
:
558 case IDS_CONTENT_CONTEXT_SAVEVIDEOAS
:
559 case IDS_CONTENT_CONTEXT_SAVEIMAGEAS
:
560 case IDS_CONTENT_CONTEXT_SAVELINKAS
: {
561 NOTREACHED(); // Should be handled in host.
566 external_context_menu_
->ExecuteCommand(command
, 0);
570 void ExternalTabContainerWin::RunUnloadHandlers(IPC::Message
* reply_message
) {
572 delete reply_message
;
576 // If we have a pending unload message, then just respond back to this
577 // request and continue processing the previous unload message.
578 if (unload_reply_message_
) {
579 AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message
, true);
580 automation_
->Send(reply_message
);
584 unload_reply_message_
= reply_message
;
585 bool wait_for_unload_handlers
=
586 web_contents_
.get() &&
587 Browser::RunUnloadEventsHelper(web_contents_
.get());
588 if (!wait_for_unload_handlers
) {
589 AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message
, true);
590 automation_
->Send(reply_message
);
591 unload_reply_message_
= NULL
;
595 void ExternalTabContainerWin::ProcessUnhandledAccelerator(const MSG
& msg
) {
596 scoped_ptr
<NativeWebKeyboardEvent
> keyboard_event(CreateKeyboardEvent(msg
));
597 unhandled_keyboard_event_handler_
.HandleKeyboardEvent(*keyboard_event
,
601 void ExternalTabContainerWin::FocusThroughTabTraversal(
603 bool restore_focus_to_view
) {
604 DCHECK(web_contents_
.get());
605 #if defined(USE_AURA)
606 SetFocus(views::HWNDForWidget(widget_
));
608 if (web_contents_
.get())
609 web_contents_
->GetView()->Focus();
611 // The web_contents_ member can get destroyed in the context of the call to
612 // WebContentsViewViews::Focus() above. This method eventually calls SetFocus
613 // on the native window, which could end up dispatching messages like
614 // WM_DESTROY for the external tab.
615 if (web_contents_
.get() && restore_focus_to_view
)
616 web_contents_
->FocusThroughTabTraversal(reverse
);
619 ////////////////////////////////////////////////////////////////////////////////
620 // ExternalTabContainer, content::WebContentsDelegate implementation:
622 WebContents
* ExternalTabContainerWin::OpenURLFromTab(
624 const OpenURLParams
& params
) {
626 pending_open_url_requests_
.push_back(params
);
630 switch (params
.disposition
) {
633 case NEW_FOREGROUND_TAB
:
634 case NEW_BACKGROUND_TAB
:
639 GURL referrer
= GenerateReferrer(params
.referrer
.policy
,
641 params
.referrer
.url
);
642 automation_
->Send(new AutomationMsg_OpenURL(tab_handle_
,
645 params
.disposition
));
647 // We should populate other fields in the
648 // ViewHostMsg_FrameNavigate_Params structure. Another option could be
649 // to refactor the UpdateHistoryForNavigation function in WebContents.
650 content::FrameNavigateParams nav_params
;
651 nav_params
.referrer
= content::Referrer(referrer
,
652 params
.referrer
.policy
);
653 nav_params
.url
= params
.url
;
654 nav_params
.page_id
= -1;
655 nav_params
.transition
= content::PAGE_TRANSITION_LINK
;
657 HistoryTabHelper
* history_tab_helper
=
658 HistoryTabHelper::FromWebContents(web_contents_
.get());
659 const history::HistoryAddPageArgs
& add_page_args
=
660 history_tab_helper
->CreateHistoryAddPageArgs(
661 params
.url
, base::Time::Now(),
662 false /* did_replace_entry */, nav_params
);
663 history_tab_helper
->UpdateHistoryForNavigation(add_page_args
);
665 return web_contents_
.get();
676 void ExternalTabContainerWin::NavigationStateChanged(const WebContents
* source
,
677 unsigned changed_flags
) {
679 NavigationInfo nav_info
;
680 if (InitNavigationInfo(&nav_info
, content::NAVIGATION_TYPE_NAV_IGNORE
, 0))
681 automation_
->Send(new AutomationMsg_NavigationStateChanged(
682 tab_handle_
, changed_flags
, nav_info
));
686 void ExternalTabContainerWin::AddNewContents(WebContents
* source
,
687 WebContents
* new_contents
,
688 WindowOpenDisposition disposition
,
689 const gfx::Rect
& initial_pos
,
694 LOG(ERROR
) << "Invalid automation provider. Dropping new contents notify";
699 scoped_refptr
<ExternalTabContainerWin
> new_container
;
700 // If the host is a browser like IE8, then the URL being navigated to in the
701 // new tab contents could potentially navigate back to Chrome from a new
702 // IE process. We support full tab mode only for IE and hence we use that as
703 // a determining factor in whether the new ExternalTabContainer instance is
704 // created as pending or not.
705 if (!route_all_top_level_navigations_
) {
706 new_container
= new ExternalTabContainerWin(NULL
, NULL
);
708 // Reuse the same tab handle here as the new container instance is a dummy
709 // instance which does not have an automation client connected at the other
711 new_container
= new TemporaryPopupExternalTabContainerWin(
712 automation_
, automation_resource_message_filter_
.get());
713 new_container
->SetTabHandle(tab_handle_
);
716 // Make sure that ExternalTabContainer instance is initialized with
717 // an unwrapped Profile.
719 Profile::FromBrowserContext(new_contents
->GetBrowserContext())->
720 GetOriginalProfile();
721 bool result
= new_container
->Init(profile
,
725 load_requests_via_automation_
,
726 handle_top_level_requests_
,
731 route_all_top_level_navigations_
);
734 if (route_all_top_level_navigations_
) {
737 uintptr_t cookie
= reinterpret_cast<uintptr_t>(new_container
.get());
738 pending_tabs_
.Get()[cookie
] = new_container
;
739 new_container
->set_pending(true);
740 new_container
->set_is_popup_window(disposition
== NEW_POPUP
);
741 AttachExternalTabParams attach_params_
;
742 attach_params_
.cookie
= static_cast<uint64
>(cookie
);
743 attach_params_
.dimensions
= initial_pos
;
744 attach_params_
.user_gesture
= user_gesture
;
745 attach_params_
.disposition
= disposition
;
746 attach_params_
.profile_name
= WideToUTF8(
747 profile
->GetPath().DirName().BaseName().value());
748 automation_
->Send(new AutomationMsg_AttachExternalTab(
749 tab_handle_
, attach_params_
));
755 void ExternalTabContainerWin::WebContentsCreated(WebContents
* source_contents
,
756 int64 source_frame_id
,
757 const string16
& frame_name
,
758 const GURL
& target_url
,
759 WebContents
* new_contents
) {
760 if (!load_requests_via_automation_
)
763 RenderViewHost
* rvh
= new_contents
->GetRenderViewHost();
766 // Register this render view as a pending render view, i.e. any network
767 // requests initiated by this render view would be serviced when the
768 // external host connects to the new external tab instance.
769 RegisterRenderViewHostForAutomation(true, rvh
);
772 void ExternalTabContainerWin::CloseContents(content::WebContents
* source
) {
776 if (unload_reply_message_
) {
777 AutomationMsg_RunUnloadHandlers::WriteReplyParams(unload_reply_message_
,
779 automation_
->Send(unload_reply_message_
);
780 unload_reply_message_
= NULL
;
782 automation_
->Send(new AutomationMsg_CloseExternalTab(tab_handle_
));
786 void ExternalTabContainerWin::MoveContents(WebContents
* source
,
787 const gfx::Rect
& pos
) {
788 if (automation_
&& is_popup_window_
)
789 automation_
->Send(new AutomationMsg_MoveWindow(tab_handle_
, pos
));
792 content::WebContents
* ExternalTabContainerWin::GetConstrainingWebContents(
793 content::WebContents
* source
) {
797 ExternalTabContainerWin::~ExternalTabContainerWin() {
801 bool ExternalTabContainerWin::IsPopupOrPanel(const WebContents
* source
) const {
802 return is_popup_window_
;
805 void ExternalTabContainerWin::UpdateTargetURL(WebContents
* source
,
809 string16 url_string
= base::UTF8ToUTF16(url
.spec());
811 new AutomationMsg_UpdateTargetUrl(tab_handle_
, url_string
));
815 void ExternalTabContainerWin::ContentsZoomChange(bool zoom_in
) {
818 bool ExternalTabContainerWin::TakeFocus(content::WebContents
* source
,
821 automation_
->Send(new AutomationMsg_TabbedOut(tab_handle_
,
822 base::win::IsShiftPressed()));
828 void ExternalTabContainerWin::WebContentsFocused(
829 content::WebContents
* contents
) {
830 DCHECK_EQ(tab_contents_container_
->GetWebContents(), contents
);
831 tab_contents_container_
->OnWebContentsFocused(contents
);
834 void ExternalTabContainerWin::CanDownload(
835 RenderViewHost
* render_view_host
,
837 const std::string
& request_method
,
838 const base::Callback
<void(bool)>& callback
) {
839 if (load_requests_via_automation_
) {
841 // In case the host needs to show UI that needs to take the focus.
842 ::AllowSetForegroundWindow(ASFW_ANY
);
844 BrowserThread::PostTask(
845 BrowserThread::IO
, FROM_HERE
,
848 &AutomationResourceMessageFilter::SendDownloadRequestToHost
),
849 automation_resource_message_filter_
.get(), 0, tab_handle_
,
853 DLOG(WARNING
) << "Downloads are only supported with host browser network "
857 // Never allow downloads.
861 void ExternalTabContainerWin::RegisterRenderViewHostForAutomation(
863 RenderViewHost
* render_view_host
) {
864 if (!GetTabHandle()) {
865 // This method is being called when it shouldn't be on the win_rel trybot;
866 // see http://crbug.com/250965. Don't crash release builds in that case
867 // until the root cause can be diagnosed and fixed. TODO(grt): fix this.
868 DLOG(FATAL
) << "tab_handle_ unset";
869 } else if (render_view_host
) {
870 AutomationResourceMessageFilter::RegisterRenderView(
871 render_view_host
->GetProcess()->GetID(),
872 render_view_host
->GetRoutingID(),
874 automation_resource_message_filter_
,
879 void ExternalTabContainerWin::RegisterRenderViewHost(
880 RenderViewHost
* render_view_host
) {
881 // RenderViewHost instances that are to be associated with this
882 // ExternalTabContainer should share the same resource request automation
884 RegisterRenderViewHostForAutomation(
885 false, // Network requests should not be handled later.
889 void ExternalTabContainerWin::UnregisterRenderViewHost(
890 RenderViewHost
* render_view_host
) {
891 // Undo the resource automation registration performed in
892 // ExternalTabContainerWin::RegisterRenderViewHost.
893 if (render_view_host
) {
894 AutomationResourceMessageFilter::UnRegisterRenderView(
895 render_view_host
->GetProcess()->GetID(),
896 render_view_host
->GetRoutingID());
900 content::JavaScriptDialogManager
*
901 ExternalTabContainerWin::GetJavaScriptDialogManager() {
902 return GetJavaScriptDialogManagerInstance();
905 bool ExternalTabContainerWin::HandleContextMenu(
906 const content::ContextMenuParams
& params
) {
912 if (params
.custom_context
.is_pepper_menu
)
915 external_context_menu_
.reset(RenderViewContextMenuViews::Create(
916 web_contents(), params
));
917 static_cast<RenderViewContextMenuWin
*>(
918 external_context_menu_
.get())->SetExternal();
919 external_context_menu_
->Init();
921 scoped_ptr
<ContextMenuModel
> context_menu_model(
922 ConvertMenuModel(&external_context_menu_
->menu_model()));
924 POINT screen_pt
= { params
.x
, params
.y
};
925 MapWindowPoints(views::HWNDForWidget(widget_
), HWND_DESKTOP
, &screen_pt
, 1);
927 MiniContextMenuParams ipc_params
;
928 ipc_params
.screen_x
= screen_pt
.x
;
929 ipc_params
.screen_y
= screen_pt
.y
;
930 ipc_params
.link_url
= params
.link_url
;
931 ipc_params
.unfiltered_link_url
= params
.unfiltered_link_url
;
932 ipc_params
.src_url
= params
.src_url
;
933 ipc_params
.page_url
= params
.page_url
;
934 ipc_params
.keyword_url
= params
.keyword_url
;
935 ipc_params
.frame_url
= params
.frame_url
;
937 bool rtl
= base::i18n::IsRTL();
939 new AutomationMsg_ForwardContextMenuToExternalHost(tab_handle_
,
941 rtl
? TPM_RIGHTALIGN
: TPM_LEFTALIGN
, ipc_params
));
946 bool ExternalTabContainerWin::PreHandleKeyboardEvent(
947 content::WebContents
* source
,
948 const NativeWebKeyboardEvent
& event
,
949 bool* is_keyboard_shortcut
) {
953 void ExternalTabContainerWin::HandleKeyboardEvent(
954 content::WebContents
* source
,
955 const NativeWebKeyboardEvent
& event
) {
957 #if defined(USE_AURA)
958 // Character events created and inserted by the IME code on Aura will not
959 // contain a native os_event, so don't attempt to pluck one out. These events
960 // also do not correspond to accelerator key presses so do not need to be
961 // forwarded to the host.
966 const MSG
& message
= MessageFromKeyboardEvent(event
);
967 ProcessUnhandledKeyStroke(message
.hwnd
, message
.message
,
968 message
.wParam
, message
.lParam
);
971 void ExternalTabContainerWin::BeforeUnloadFired(WebContents
* tab
,
973 bool* proceed_to_fire_unload
) {
974 *proceed_to_fire_unload
= true;
977 delete unload_reply_message_
;
978 unload_reply_message_
= NULL
;
982 if (!unload_reply_message_
) {
983 NOTREACHED() << "**** NULL unload reply message pointer.";
988 AutomationMsg_RunUnloadHandlers::WriteReplyParams(unload_reply_message_
,
990 automation_
->Send(unload_reply_message_
);
991 unload_reply_message_
= NULL
;
992 *proceed_to_fire_unload
= false;
996 void ExternalTabContainerWin::ShowRepostFormWarningDialog(WebContents
* source
) {
997 TabModalConfirmDialog::Create(new RepostFormWarningController(source
),
1001 content::ColorChooser
* ExternalTabContainerWin::OpenColorChooser(
1002 WebContents
* web_contents
, SkColor initial_color
) {
1003 return chrome::ShowColorChooser(web_contents
, initial_color
);
1006 void ExternalTabContainerWin::RunFileChooser(
1008 const content::FileChooserParams
& params
) {
1009 FileSelectHelper::RunFileChooser(tab
, params
);
1012 void ExternalTabContainerWin::EnumerateDirectory(WebContents
* tab
,
1014 const base::FilePath
& path
) {
1015 FileSelectHelper::EnumerateDirectory(tab
, request_id
, path
);
1018 void ExternalTabContainerWin::JSOutOfMemory(WebContents
* tab
) {
1019 Browser::JSOutOfMemoryHelper(tab
);
1022 void ExternalTabContainerWin::RegisterProtocolHandler(
1024 const std::string
& protocol
,
1026 const string16
& title
,
1027 bool user_gesture
) {
1028 Browser::RegisterProtocolHandlerHelper(tab
, protocol
, url
, title
,
1029 user_gesture
, NULL
);
1032 void ExternalTabContainerWin::FindReply(WebContents
* tab
,
1034 int number_of_matches
,
1035 const gfx::Rect
& selection_rect
,
1036 int active_match_ordinal
,
1037 bool final_update
) {
1038 Browser::FindReplyHelper(tab
, request_id
, number_of_matches
, selection_rect
,
1039 active_match_ordinal
, final_update
);
1042 void ExternalTabContainerWin::RequestMediaAccessPermission(
1043 content::WebContents
* web_contents
,
1044 const content::MediaStreamRequest
& request
,
1045 const content::MediaResponseCallback
& callback
) {
1046 MediaStreamInfoBarDelegate::Create(web_contents
, request
, callback
);
1049 bool ExternalTabContainerWin::RequestPpapiBrokerPermission(
1050 WebContents
* web_contents
,
1052 const base::FilePath
& plugin_path
,
1053 const base::Callback
<void(bool)>& callback
) {
1054 PepperBrokerInfoBarDelegate::Create(web_contents
, url
, plugin_path
, callback
);
1058 void ExternalTabContainerWin::RenderViewDeleted(
1059 content::RenderViewHost
* render_view_host
) {
1060 if (load_requests_via_automation_
)
1061 UnregisterRenderViewHost(render_view_host
);
1064 bool ExternalTabContainerWin::OnMessageReceived(const IPC::Message
& message
) {
1065 bool handled
= true;
1066 IPC_BEGIN_MESSAGE_MAP(ExternalTabContainerWin
, message
)
1067 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ForwardMessageToExternalHost
,
1068 OnForwardMessageToExternalHost
)
1069 IPC_MESSAGE_UNHANDLED(handled
= false)
1070 IPC_END_MESSAGE_MAP()
1074 void ExternalTabContainerWin::DidFailProvisionalLoad(
1077 const GURL
& validated_url
,
1079 const string16
& error_description
,
1080 content::RenderViewHost
* render_view_host
) {
1082 automation_
->Send(new AutomationMsg_NavigationFailed(
1083 tab_handle_
, error_code
, validated_url
));
1085 ignore_next_load_notification_
= true;
1088 void ExternalTabContainerWin::OnForwardMessageToExternalHost(
1089 const std::string
& message
,
1090 const std::string
& origin
,
1091 const std::string
& target
) {
1093 automation_
->Send(new AutomationMsg_ForwardMessageToExternalHost(
1094 tab_handle_
, message
, origin
, target
));
1098 ////////////////////////////////////////////////////////////////////////////////
1099 // ExternalTabContainer, NotificationObserver implementation:
1101 void ExternalTabContainerWin::Observe(
1103 const content::NotificationSource
& source
,
1104 const content::NotificationDetails
& details
) {
1108 static const int kHttpClientErrorStart
= 400;
1109 static const int kHttpServerErrorEnd
= 510;
1112 case content::NOTIFICATION_LOAD_STOP
: {
1113 const LoadNotificationDetails
* load
=
1114 content::Details
<LoadNotificationDetails
>(details
).ptr();
1115 if (load
&& content::PageTransitionIsMainFrame(load
->origin
)) {
1116 TRACE_EVENT_END_ETW("ExternalTabContainerWin::Navigate", 0,
1118 automation_
->Send(new AutomationMsg_TabLoaded(tab_handle_
,
1123 case content::NOTIFICATION_NAV_ENTRY_COMMITTED
: {
1124 if (ignore_next_load_notification_
) {
1125 ignore_next_load_notification_
= false;
1129 const content::LoadCommittedDetails
* commit
=
1130 content::Details
<content::LoadCommittedDetails
>(details
).ptr();
1132 if (commit
->http_status_code
>= kHttpClientErrorStart
&&
1133 commit
->http_status_code
<= kHttpServerErrorEnd
) {
1134 automation_
->Send(new AutomationMsg_NavigationFailed(
1135 tab_handle_
, commit
->http_status_code
, commit
->entry
->GetURL()));
1137 ignore_next_load_notification_
= true;
1139 NavigationInfo navigation_info
;
1140 // When the previous entry index is invalid, it will be -1, which
1141 // will still make the computation come out right (navigating to the
1142 // 0th entry will be +1).
1143 if (InitNavigationInfo(&navigation_info
, commit
->type
,
1144 commit
->previous_entry_index
-
1145 web_contents_
->GetController().GetLastCommittedEntryIndex()))
1146 automation_
->Send(new AutomationMsg_DidNavigate(tab_handle_
,
1151 case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED
: {
1152 if (load_requests_via_automation_
) {
1153 RenderViewHost
* rvh
= content::Details
<RenderViewHost
>(details
).ptr();
1154 RegisterRenderViewHostForAutomation(false, rvh
);
1163 ////////////////////////////////////////////////////////////////////////////////
1164 // WidgetObserver overrides:
1166 void ExternalTabContainerWin::OnWidgetCreated(views::Widget
* widget
) {
1167 DCHECK_EQ(widget_
, widget
);
1168 // Grab a reference here which will be released in OnWidgetDestroyed.
1172 void ExternalTabContainerWin::OnWidgetDestroying(views::Widget
* widget
) {
1173 DCHECK_EQ(widget_
, widget
);
1178 void ExternalTabContainerWin::OnWidgetDestroyed(views::Widget
* widget
) {
1179 DCHECK_EQ(widget_
, static_cast<views::Widget
*>(NULL
));
1180 // Release the reference which we grabbed in OnWidgetCreated.
1184 ////////////////////////////////////////////////////////////////////////////////
1185 // ExternalTabContainer, private:
1186 bool ExternalTabContainerWin::ProcessUnhandledKeyStroke(HWND window
,
1193 if ((wparam
== VK_TAB
) && !base::win::IsCtrlPressed()) {
1194 // Tabs are handled separately (except if this is Ctrl-Tab or
1199 // Send this keystroke to the external host as it could be processed as an
1200 // accelerator there. If the host does not handle this accelerator, it will
1201 // reflect the accelerator back to us via the ProcessUnhandledAccelerator
1205 msg
.message
= message
;
1206 msg
.wParam
= wparam
;
1207 msg
.lParam
= lparam
;
1208 automation_
->Send(new AutomationMsg_HandleAccelerator(tab_handle_
, msg
));
1212 bool ExternalTabContainerWin::InitNavigationInfo(
1213 NavigationInfo
* nav_info
,
1214 content::NavigationType nav_type
,
1215 int relative_offset
) {
1217 NavigationEntry
* entry
= web_contents_
->GetController().GetActiveEntry();
1218 // If this is very early in the game then there may not be an entry.
1222 nav_info
->navigation_type
= nav_type
;
1223 nav_info
->relative_offset
= relative_offset
;
1224 nav_info
->navigation_index
=
1225 web_contents_
->GetController().GetCurrentEntryIndex();
1226 nav_info
->url
= entry
->GetURL();
1227 nav_info
->referrer
= entry
->GetReferrer().url
;
1228 nav_info
->title
= UTF16ToWideHack(entry
->GetTitle());
1229 if (nav_info
->title
.empty())
1230 nav_info
->title
= UTF8ToWide(nav_info
->url
.spec());
1232 nav_info
->security_style
= entry
->GetSSL().security_style
;
1233 int content_status
= entry
->GetSSL().content_status
;
1234 nav_info
->displayed_insecure_content
=
1235 !!(content_status
& SSLStatus::DISPLAYED_INSECURE_CONTENT
);
1236 nav_info
->ran_insecure_content
=
1237 !!(content_status
& SSLStatus::RAN_INSECURE_CONTENT
);
1241 SkColor
ExternalTabContainerWin::GetInfoBarSeparatorColor() const {
1242 return ThemeProperties::GetDefaultColor(
1243 ThemeProperties::COLOR_TOOLBAR_SEPARATOR
);
1246 void ExternalTabContainerWin::InfoBarContainerStateChanged(bool is_animating
) {
1247 if (external_tab_view_
)
1248 external_tab_view_
->Layout();
1251 bool ExternalTabContainerWin::DrawInfoBarArrows(int* x
) const {
1255 bool ExternalTabContainerWin::AcceleratorPressed(
1256 const ui::Accelerator
& accelerator
) {
1257 std::map
<ui::Accelerator
, int>::const_iterator iter
=
1258 accelerator_table_
.find(accelerator
);
1259 DCHECK(iter
!= accelerator_table_
.end());
1261 if (!web_contents_
.get() || !web_contents_
->GetRenderViewHost()) {
1266 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1267 int command_id
= iter
->second
;
1268 switch (command_id
) {
1270 host
->Zoom(content::PAGE_ZOOM_IN
);
1272 case IDC_ZOOM_NORMAL
:
1273 host
->Zoom(content::PAGE_ZOOM_RESET
);
1275 case IDC_ZOOM_MINUS
:
1276 host
->Zoom(content::PAGE_ZOOM_OUT
);
1279 DevToolsWindow::ToggleDevToolsWindow(web_contents_
->GetRenderViewHost(),
1281 DEVTOOLS_TOGGLE_ACTION_SHOW
);
1283 case IDC_DEV_TOOLS_CONSOLE
:
1284 DevToolsWindow::ToggleDevToolsWindow(web_contents_
->GetRenderViewHost(),
1286 DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE
);
1288 case IDC_DEV_TOOLS_INSPECT
:
1289 DevToolsWindow::ToggleDevToolsWindow(web_contents_
->GetRenderViewHost(),
1291 DEVTOOLS_TOGGLE_ACTION_INSPECT
);
1293 case IDC_DEV_TOOLS_TOGGLE
:
1294 DevToolsWindow::ToggleDevToolsWindow(web_contents_
->GetRenderViewHost(),
1296 DEVTOOLS_TOGGLE_ACTION_TOGGLE
);
1299 NOTREACHED() << "Unsupported accelerator: " << command_id
;
1305 bool ExternalTabContainerWin::CanHandleAccelerators() const {
1309 void ExternalTabContainerWin::Navigate(const GURL
& url
, const GURL
& referrer
) {
1310 if (!web_contents_
.get()) {
1315 TRACE_EVENT_BEGIN_ETW("ExternalTabContainerWin::Navigate", 0, url
.spec());
1317 web_contents_
->GetController().LoadURL(
1318 url
, content::Referrer(referrer
, WebKit::WebReferrerPolicyDefault
),
1319 content::PAGE_TRANSITION_AUTO_TOPLEVEL
, std::string());
1322 bool ExternalTabContainerWin::OnGoToEntryOffset(int offset
) {
1323 if (load_requests_via_automation_
) {
1325 automation_
->Send(new AutomationMsg_RequestGoToHistoryEntryOffset(
1326 tab_handle_
, offset
));
1334 void ExternalTabContainerWin::LoadAccelerators() {
1335 HACCEL accelerator_table
= AtlLoadAccelerators(IDR_CHROMEFRAME
);
1336 DCHECK(accelerator_table
);
1338 // We have to copy the table to access its contents.
1339 int count
= CopyAcceleratorTable(accelerator_table
, 0, 0);
1341 // Nothing to do in that case.
1345 scoped_ptr
<ACCEL
[]> scoped_accelerators(new ACCEL
[count
]);
1346 ACCEL
* accelerators
= scoped_accelerators
.get();
1347 DCHECK(accelerators
!= NULL
);
1349 CopyAcceleratorTable(accelerator_table
, accelerators
, count
);
1351 focus_manager_
= widget_
->GetFocusManager();
1352 DCHECK(focus_manager_
);
1354 // Let's fill our own accelerator table.
1355 for (int i
= 0; i
< count
; ++i
) {
1356 ui::Accelerator
accelerator(
1357 static_cast<ui::KeyboardCode
>(accelerators
[i
].key
),
1358 ui::GetModifiersFromACCEL(accelerators
[i
]));
1359 accelerator_table_
[accelerator
] = accelerators
[i
].cmd
;
1361 // Also register with the focus manager.
1362 if (focus_manager_
) {
1363 focus_manager_
->RegisterAccelerator(
1364 accelerator
, ui::AcceleratorManager::kNormalPriority
, this);
1369 void ExternalTabContainerWin::OnReinitialize() {
1370 if (load_requests_via_automation_
) {
1371 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
1373 AutomationResourceMessageFilter::ResumePendingRenderView(
1374 rvh
->GetProcess()->GetID(), rvh
->GetRoutingID(),
1375 tab_handle_
, automation_resource_message_filter_
);
1379 NavigationStateChanged(web_contents(), 0);
1380 ServicePendingOpenURLRequests();
1383 void ExternalTabContainerWin::ServicePendingOpenURLRequests() {
1388 for (size_t index
= 0; index
< pending_open_url_requests_
.size();
1390 const OpenURLParams
& url_request
= pending_open_url_requests_
[index
];
1391 OpenURLFromTab(web_contents(), url_request
);
1393 pending_open_url_requests_
.clear();
1396 void ExternalTabContainerWin::SetupExternalTabView() {
1397 // Create a TabContentsContainer to handle focus cycling using Tab and
1400 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
1401 tab_contents_container_
= new views::WebView(profile
);
1403 // The views created here will be destroyed when the ExternalTabContainer
1404 // widget is torn down.
1405 external_tab_view_
= new views::View();
1407 InfoBarContainerView
* infobar_container
= new InfoBarContainerView(this);
1408 infobar_container
->ChangeInfoBarService(
1409 InfoBarService::FromWebContents(web_contents_
.get()));
1411 views::GridLayout
* layout
= new views::GridLayout(external_tab_view_
);
1412 // Give this column an identifier of 0.
1413 views::ColumnSet
* columns
= layout
->AddColumnSet(0);
1414 columns
->AddColumn(views::GridLayout::FILL
,
1415 views::GridLayout::FILL
,
1417 views::GridLayout::USE_PREF
,
1421 external_tab_view_
->SetLayoutManager(layout
);
1423 layout
->StartRow(0, 0);
1424 layout
->AddView(infobar_container
);
1425 layout
->StartRow(1, 0);
1426 layout
->AddView(tab_contents_container_
);
1427 widget_
->SetContentsView(external_tab_view_
);
1428 // Note that SetWebContents must be called after AddChildView is called
1429 tab_contents_container_
->SetWebContents(web_contents());
1433 ExternalTabContainer
* ExternalTabContainer::Create(
1434 AutomationProvider
* automation_provider
,
1435 AutomationResourceMessageFilter
* filter
) {
1436 return new ExternalTabContainerWin(automation_provider
, filter
);
1440 ExternalTabContainer
* ExternalTabContainer::GetContainerForTab(
1441 content::WebContents
* web_contents
) {
1442 HWND window
= views::HWNDForNativeWindow(
1443 web_contents
->GetView()->GetNativeView());
1444 #if !defined(USE_AURA)
1445 // In the non-Aura case, it is the parent of the WebContents's view that has
1446 // the property set.
1447 window
= ::GetParent(window
);
1448 if (!::IsWindow(window
))
1451 return reinterpret_cast<ExternalTabContainerWin
*>(
1452 ui::ViewProp::GetValue(window
, kWindowObjectKey
));
1456 scoped_refptr
<ExternalTabContainer
> ExternalTabContainer::RemovePendingTab(
1458 return ExternalTabContainerWin::RemovePendingExternalTab(cookie
);
1461 ///////////////////////////////////////////////////////////////////////////////
1462 // TemporaryPopupExternalTabContainerWin
1464 TemporaryPopupExternalTabContainerWin::TemporaryPopupExternalTabContainerWin(
1465 AutomationProvider
* automation
,
1466 AutomationResourceMessageFilter
* filter
)
1467 : ExternalTabContainerWin(automation
, filter
) {
1470 TemporaryPopupExternalTabContainerWin::~TemporaryPopupExternalTabContainerWin(
1472 DVLOG(1) << __FUNCTION__
;
1475 WebContents
* TemporaryPopupExternalTabContainerWin::OpenURLFromTab(
1476 WebContents
* source
,
1477 const OpenURLParams
& params
) {
1481 OpenURLParams forward_params
= params
;
1482 if (params
.disposition
== CURRENT_TAB
) {
1483 DCHECK(route_all_top_level_navigations_
);
1484 forward_params
.disposition
= NEW_FOREGROUND_TAB
;
1486 WebContents
* new_contents
=
1487 ExternalTabContainerWin::OpenURLFromTab(source
, forward_params
);
1488 // support only one navigation for a dummy tab before it is killed.
1489 widget_
->CloseNow();
1490 return new_contents
;