Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: chrome/browser/external_tab_container_win.cc

Issue 9959051: Move ExternalTabContainer into a directory with an OWNERS file. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removing wstring. Beating a small red car with a branch. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/external_tab_container_win.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/external_tab_container_win.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/debug/trace_event.h"
12 #include "base/i18n/rtl.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/utf_string_conversions.h"
16 #include "base/win/win_util.h"
17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/app/chrome_dll_resource.h"
19 #include "chrome/browser/automation/automation_provider.h"
20 #include "chrome/browser/debugger/devtools_toggle_action.h"
21 #include "chrome/browser/debugger/devtools_window.h"
22 #include "chrome/browser/history/history_tab_helper.h"
23 #include "chrome/browser/history/history_types.h"
24 #include "chrome/browser/infobars/infobar_tab_helper.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/repost_form_warning_controller.h"
27 #include "chrome/browser/themes/theme_service.h"
28 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h"
29 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
30 #include "chrome/browser/ui/browser.h"
31 #include "chrome/browser/ui/browser_dialogs.h"
32 #include "chrome/browser/ui/browser_window.h"
33 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
34 #include "chrome/browser/ui/views/browser_dialogs.h"
35 #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
36 #include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
37 #include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
38 #include "chrome/common/automation_messages.h"
39 #include "chrome/common/chrome_constants.h"
40 #include "chrome/common/chrome_notification_types.h"
41 #include "chrome/common/render_messages.h"
42 #include "chrome/common/url_constants.h"
43 #include "content/public/browser/load_notification_details.h"
44 #include "content/public/browser/native_web_keyboard_event.h"
45 #include "content/public/browser/navigation_details.h"
46 #include "content/public/browser/navigation_entry.h"
47 #include "content/public/browser/notification_service.h"
48 #include "content/public/browser/render_process_host.h"
49 #include "content/public/browser/render_view_host.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/browser/web_intents_dispatcher.h"
52 #include "content/public/common/bindings_policy.h"
53 #include "content/public/common/frame_navigate_params.h"
54 #include "content/public/common/page_transition_types.h"
55 #include "content/public/common/page_zoom.h"
56 #include "content/public/common/renderer_preferences.h"
57 #include "content/public/common/ssl_status.h"
58 #include "grit/generated_resources.h"
59 #include "grit/locale_settings.h"
60 #include "third_party/WebKit/Source/WebKit/chromium/public/WebReferrerPolicy.h"
61 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
62 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h "
63 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
64 #include "ui/base/l10n/l10n_util.h"
65 #include "ui/base/models/menu_model.h"
66 #include "ui/base/view_prop.h"
67 #include "ui/views/layout/grid_layout.h"
68
69 using content::BrowserThread;
70 using content::LoadNotificationDetails;
71 using content::NavigationController;
72 using content::NavigationEntry;
73 using content::OpenURLParams;
74 using content::RenderViewHost;
75 using content::SSLStatus;
76 using content::WebContents;
77 using ui::ViewProp;
78 using WebKit::WebCString;
79 using WebKit::WebReferrerPolicy;
80 using WebKit::WebSecurityPolicy;
81 using WebKit::WebString;
82
83 static const char kWindowObjectKey[] = "ChromeWindowObject";
84
85 namespace {
86
87 // Convert ui::MenuModel into a serializable form for Chrome Frame
88 ContextMenuModel* ConvertMenuModel(const ui::MenuModel* ui_model) {
89 ContextMenuModel* new_model = new ContextMenuModel;
90
91 const int index_base = ui_model->GetFirstItemIndex(NULL);
92 const int item_count = ui_model->GetItemCount();
93 new_model->items.reserve(item_count);
94 for (int i = 0; i < item_count; ++i) {
95 const int index = index_base + i;
96 if (ui_model->IsVisibleAt(index)) {
97 ContextMenuModel::Item item;
98 item.type = ui_model->GetTypeAt(index);
99 item.item_id = ui_model->GetCommandIdAt(index);
100 item.label = ui_model->GetLabelAt(index);
101 item.checked = ui_model->IsItemCheckedAt(index);
102 item.enabled = ui_model->IsEnabledAt(index);
103 if (item.type == ui::MenuModel::TYPE_SUBMENU)
104 item.submenu = ConvertMenuModel(ui_model->GetSubmenuModelAt(index));
105
106 new_model->items.push_back(item);
107 }
108 }
109
110 return new_model;
111 }
112
113 } // namespace
114
115 base::LazyInstance<ExternalTabContainer::PendingTabs>
116 ExternalTabContainer::pending_tabs_ = LAZY_INSTANCE_INITIALIZER;
117
118 ExternalTabContainer::ExternalTabContainer(
119 AutomationProvider* automation, AutomationResourceMessageFilter* filter)
120 : views::NativeWidgetWin(new views::Widget),
121 automation_(automation),
122 tab_contents_container_(NULL),
123 tab_handle_(0),
124 ignore_next_load_notification_(false),
125 automation_resource_message_filter_(filter),
126 load_requests_via_automation_(false),
127 handle_top_level_requests_(false),
128 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
129 pending_(false),
130 focus_manager_(NULL),
131 external_tab_view_(NULL),
132 unload_reply_message_(NULL),
133 route_all_top_level_navigations_(false),
134 is_popup_window_(false) {
135 }
136
137 ExternalTabContainer::~ExternalTabContainer() {
138 Uninitialize();
139 }
140
141 WebContents * ExternalTabContainer::web_contents() const {
142 return tab_contents_.get() ? tab_contents_->web_contents() : NULL;
143 }
144
145 bool ExternalTabContainer::Init(Profile* profile,
146 HWND parent,
147 const gfx::Rect& bounds,
148 DWORD style,
149 bool load_requests_via_automation,
150 bool handle_top_level_requests,
151 TabContentsWrapper* existing_contents,
152 const GURL& initial_url,
153 const GURL& referrer,
154 bool infobars_enabled,
155 bool route_all_top_level_navigations) {
156 if (IsWindow()) {
157 NOTREACHED();
158 return false;
159 }
160
161 load_requests_via_automation_ = load_requests_via_automation;
162 handle_top_level_requests_ = handle_top_level_requests;
163 route_all_top_level_navigations_ = route_all_top_level_navigations;
164
165 set_window_style(WS_POPUP | WS_CLIPCHILDREN);
166
167 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
168 params.bounds = bounds;
169 params.native_widget = this;
170 GetWidget()->Init(params);
171 if (!IsWindow()) {
172 NOTREACHED();
173 return false;
174 }
175
176 // TODO(jcampan): limit focus traversal to contents.
177
178 prop_.reset(new ViewProp(GetNativeView(), kWindowObjectKey, this));
179
180 if (existing_contents) {
181 tab_contents_.reset(existing_contents);
182 tab_contents_->web_contents()->GetController().SetBrowserContext(profile);
183 } else {
184 WebContents* new_contents = WebContents::Create(
185 profile, NULL, MSG_ROUTING_NONE, NULL, NULL);
186 tab_contents_.reset(new TabContentsWrapper(new_contents));
187 }
188
189 if (!infobars_enabled)
190 tab_contents_->infobar_tab_helper()->set_infobars_enabled(false);
191
192 tab_contents_->web_contents()->SetDelegate(this);
193
194 tab_contents_->web_contents()->
195 GetMutableRendererPrefs()->browser_handles_top_level_requests =
196 handle_top_level_requests;
197
198 if (!existing_contents) {
199 tab_contents_->web_contents()->GetRenderViewHost()->AllowBindings(
200 content::BINDINGS_POLICY_EXTERNAL_HOST);
201 }
202
203 NavigationController* controller =
204 &tab_contents_->web_contents()->GetController();
205 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
206 content::Source<NavigationController>(controller));
207 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
208 content::Source<NavigationController>(controller));
209 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CREATED_FOR_TAB,
210 content::Source<WebContents>(tab_contents_->web_contents()));
211 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_DELETED,
212 content::NotificationService::AllSources());
213 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CREATED,
214 content::NotificationService::AllSources());
215
216 content::WebContentsObserver::Observe(tab_contents_->web_contents());
217
218 // Start loading initial URL
219 if (!initial_url.is_empty()) {
220 // Navigate out of context since we don't have a 'tab_handle_' yet.
221 MessageLoop::current()->PostTask(
222 FROM_HERE,
223 base::Bind(&ExternalTabContainer::Navigate, weak_factory_.GetWeakPtr(),
224 initial_url, referrer));
225 }
226
227 // We need WS_POPUP to be on the window during initialization, but
228 // once initialized we apply the requested style which may or may not
229 // include the popup bit.
230 // Note that it's important to do this before we call SetParent since
231 // during the SetParent call we will otherwise get a WA_ACTIVATE call
232 // that causes us to steal the current focus.
233 SetWindowLong(GWL_STYLE, (GetWindowLong(GWL_STYLE) & ~WS_POPUP) | style);
234
235 // Now apply the parenting and style
236 if (parent)
237 SetParent(GetNativeView(), parent);
238
239 ::ShowWindow(tab_contents_->web_contents()->GetNativeView(), SW_SHOWNA);
240
241 LoadAccelerators();
242 SetupExternalTabView();
243 tab_contents_->blocked_content_tab_helper()->set_delegate(this);
244 return true;
245 }
246
247 void ExternalTabContainer::Uninitialize() {
248 registrar_.RemoveAll();
249 if (tab_contents_.get()) {
250 UnregisterRenderViewHost(
251 tab_contents_->web_contents()->GetRenderViewHost());
252
253 if (GetWidget()->GetRootView())
254 GetWidget()->GetRootView()->RemoveAllChildViews(true);
255
256 content::NotificationService::current()->Notify(
257 chrome::NOTIFICATION_EXTERNAL_TAB_CLOSED,
258 content::Source<NavigationController>(
259 &tab_contents_->web_contents()->GetController()),
260 content::Details<ExternalTabContainer>(this));
261
262 tab_contents_.reset(NULL);
263 }
264
265 if (focus_manager_) {
266 focus_manager_->UnregisterAccelerators(this);
267 focus_manager_ = NULL;
268 }
269
270 external_tab_view_ = NULL;
271 request_context_ = NULL;
272 tab_contents_container_ = NULL;
273 }
274
275 bool ExternalTabContainer::Reinitialize(
276 AutomationProvider* automation_provider,
277 AutomationResourceMessageFilter* filter,
278 gfx::NativeWindow parent_window) {
279 if (!automation_provider || !filter) {
280 NOTREACHED();
281 return false;
282 }
283
284 automation_ = automation_provider;
285 automation_resource_message_filter_ = filter;
286 // Wait for the automation channel to be initialized before resuming pending
287 // render views and sending in the navigation state.
288 MessageLoop::current()->PostTask(
289 FROM_HERE, base::Bind(&ExternalTabContainer::OnReinitialize,
290 weak_factory_.GetWeakPtr()));
291
292 if (parent_window)
293 SetParent(GetNativeView(), parent_window);
294 return true;
295 }
296
297 void ExternalTabContainer::SetTabHandle(int handle) {
298 tab_handle_ = handle;
299 }
300
301 void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) {
302 NativeWebKeyboardEvent keyboard_event(msg);
303 unhandled_keyboard_event_handler_.HandleKeyboardEvent(keyboard_event,
304 focus_manager_);
305 }
306
307 void ExternalTabContainer::FocusThroughTabTraversal(
308 bool reverse, bool restore_focus_to_view) {
309 DCHECK(tab_contents_.get());
310 if (tab_contents_.get())
311 tab_contents_->web_contents()->Focus();
312
313 // The tab_contents_ member can get destroyed in the context of the call to
314 // TabContentsViewViews::Focus() above. This method eventually calls SetFocus
315 // on the native window, which could end up dispatching messages like
316 // WM_DESTROY for the external tab.
317 if (tab_contents_.get() && restore_focus_to_view)
318 tab_contents_->web_contents()->FocusThroughTabTraversal(reverse);
319 }
320
321 // static
322 bool ExternalTabContainer::IsExternalTabContainer(HWND window) {
323 return ViewProp::GetValue(window, kWindowObjectKey) != NULL;
324 }
325
326 // static
327 ExternalTabContainer* ExternalTabContainer::GetContainerForTab(
328 HWND tab_window) {
329 HWND parent_window = ::GetParent(tab_window);
330 if (!::IsWindow(parent_window)) {
331 return NULL;
332 }
333 if (!IsExternalTabContainer(parent_window)) {
334 return NULL;
335 }
336 ExternalTabContainer* container = reinterpret_cast<ExternalTabContainer*>(
337 ViewProp::GetValue(parent_window, kWindowObjectKey));
338 return container;
339 }
340
341 // static
342 ExternalTabContainer*
343 ExternalTabContainer::GetExternalContainerFromNativeWindow(
344 gfx::NativeView native_window) {
345 ExternalTabContainer* tab_container = NULL;
346 if (native_window) {
347 tab_container = reinterpret_cast<ExternalTabContainer*>(
348 ViewProp::GetValue(native_window, kWindowObjectKey));
349 }
350 return tab_container;
351 }
352 ////////////////////////////////////////////////////////////////////////////////
353 // ExternalTabContainer, content::WebContentsDelegate implementation:
354
355 WebContents* ExternalTabContainer::OpenURLFromTab(WebContents* source,
356 const OpenURLParams& params) {
357 if (pending()) {
358 pending_open_url_requests_.push_back(params);
359 return NULL;
360 }
361
362 switch (params.disposition) {
363 case CURRENT_TAB:
364 case SINGLETON_TAB:
365 case NEW_FOREGROUND_TAB:
366 case NEW_BACKGROUND_TAB:
367 case NEW_POPUP:
368 case NEW_WINDOW:
369 case SAVE_TO_DISK:
370 if (automation_) {
371 GURL referrer = GURL(WebSecurityPolicy::generateReferrerHeader(
372 params.referrer.policy,
373 params.url,
374 WebString::fromUTF8(params.referrer.url.spec())).utf8());
375 automation_->Send(new AutomationMsg_OpenURL(tab_handle_,
376 params.url,
377 referrer,
378 params.disposition));
379 // TODO(ananta)
380 // We should populate other fields in the
381 // ViewHostMsg_FrameNavigate_Params structure. Another option could be
382 // to refactor the UpdateHistoryForNavigation function in TabContents.
383 content::FrameNavigateParams nav_params;
384 nav_params.referrer = content::Referrer(referrer,
385 params.referrer.policy);
386 nav_params.url = params.url;
387 nav_params.page_id = -1;
388 nav_params.transition = content::PAGE_TRANSITION_LINK;
389
390 content::LoadCommittedDetails details;
391 details.did_replace_entry = false;
392
393 scoped_refptr<history::HistoryAddPageArgs> add_page_args(
394 tab_contents_->history_tab_helper()->
395 CreateHistoryAddPageArgs(params.url, details, nav_params));
396 tab_contents_->history_tab_helper()->
397 UpdateHistoryForNavigation(add_page_args);
398
399 return tab_contents_->web_contents();
400 }
401 break;
402 default:
403 NOTREACHED();
404 break;
405 }
406
407 return NULL;
408 }
409
410 void ExternalTabContainer::NavigationStateChanged(const WebContents* source,
411 unsigned changed_flags) {
412 if (automation_) {
413 NavigationInfo nav_info;
414 if (InitNavigationInfo(&nav_info, content::NAVIGATION_TYPE_NAV_IGNORE, 0))
415 automation_->Send(new AutomationMsg_NavigationStateChanged(
416 tab_handle_, changed_flags, nav_info));
417 }
418 }
419
420 void ExternalTabContainer::AddNewContents(WebContents* source,
421 WebContents* new_contents,
422 WindowOpenDisposition disposition,
423 const gfx::Rect& initial_pos,
424 bool user_gesture) {
425 if (!automation_) {
426 DCHECK(pending_);
427 LOG(ERROR) << "Invalid automation provider. Dropping new contents notify";
428 delete new_contents;
429 return;
430 }
431
432 scoped_refptr<ExternalTabContainer> new_container;
433 // If the host is a browser like IE8, then the URL being navigated to in the
434 // new tab contents could potentially navigate back to Chrome from a new
435 // IE process. We support full tab mode only for IE and hence we use that as
436 // a determining factor in whether the new ExternalTabContainer instance is
437 // created as pending or not.
438 if (!route_all_top_level_navigations_) {
439 new_container = new ExternalTabContainer(NULL, NULL);
440 } else {
441 // Reuse the same tab handle here as the new container instance is a dummy
442 // instance which does not have an automation client connected at the other
443 // end.
444 new_container = new TemporaryPopupExternalTabContainer(
445 automation_, automation_resource_message_filter_.get());
446 new_container->SetTabHandle(tab_handle_);
447 }
448
449 // Make sure that ExternalTabContainer instance is initialized with
450 // an unwrapped Profile.
451 scoped_ptr<TabContentsWrapper> wrapper(new TabContentsWrapper(new_contents));
452 bool result = new_container->Init(
453 wrapper->profile()->GetOriginalProfile(),
454 NULL,
455 initial_pos,
456 WS_CHILD,
457 load_requests_via_automation_,
458 handle_top_level_requests_,
459 wrapper.get(),
460 GURL(),
461 GURL(),
462 true,
463 route_all_top_level_navigations_);
464
465 if (result) {
466 Profile* profile = wrapper->profile();
467 wrapper.release(); // Ownership has been transferred.
468 if (route_all_top_level_navigations_) {
469 return;
470 }
471 uintptr_t cookie = reinterpret_cast<uintptr_t>(new_container.get());
472 pending_tabs_.Get()[cookie] = new_container;
473 new_container->set_pending(true);
474 new_container->set_is_popup_window(disposition == NEW_POPUP);
475 AttachExternalTabParams attach_params_;
476 attach_params_.cookie = static_cast<uint64>(cookie);
477 attach_params_.dimensions = initial_pos;
478 attach_params_.user_gesture = user_gesture;
479 attach_params_.disposition = disposition;
480 attach_params_.profile_name = WideToUTF8(
481 profile->GetPath().DirName().BaseName().value());
482 automation_->Send(new AutomationMsg_AttachExternalTab(
483 tab_handle_, attach_params_));
484 } else {
485 NOTREACHED();
486 }
487 }
488
489 void ExternalTabContainer::WebContentsCreated(WebContents* source_contents,
490 int64 source_frame_id,
491 const GURL& target_url,
492 WebContents* new_contents) {
493 RenderViewHost* rvh = new_contents->GetRenderViewHost();
494 DCHECK(rvh != NULL);
495
496 // Register this render view as a pending render view, i.e. any network
497 // requests initiated by this render view would be serviced when the
498 // external host connects to the new external tab instance.
499 RegisterRenderViewHostForAutomation(rvh, true);
500 }
501
502 void ExternalTabContainer::CloseContents(content::WebContents* source) {
503 if (!automation_)
504 return;
505
506 if (unload_reply_message_) {
507 AutomationMsg_RunUnloadHandlers::WriteReplyParams(unload_reply_message_,
508 true);
509 automation_->Send(unload_reply_message_);
510 unload_reply_message_ = NULL;
511 } else {
512 automation_->Send(new AutomationMsg_CloseExternalTab(tab_handle_));
513 }
514 }
515
516 void ExternalTabContainer::MoveContents(WebContents* source,
517 const gfx::Rect& pos) {
518 if (automation_ && is_popup_window_)
519 automation_->Send(new AutomationMsg_MoveWindow(tab_handle_, pos));
520 }
521
522 TabContentsWrapper* ExternalTabContainer::GetConstrainingContentsWrapper(
523 TabContentsWrapper* source) {
524 return source;
525 }
526
527 bool ExternalTabContainer::IsPopupOrPanel(const WebContents* source) const {
528 return is_popup_window_;
529 }
530
531 void ExternalTabContainer::UpdateTargetURL(WebContents* source,
532 int32 page_id,
533 const GURL& url) {
534 Browser::UpdateTargetURLHelper(source, page_id, url);
535 if (automation_) {
536 std::wstring url_string = CA2W(url.spec().c_str());
537 automation_->Send(
538 new AutomationMsg_UpdateTargetUrl(tab_handle_, url_string));
539 }
540 }
541
542 void ExternalTabContainer::ContentsZoomChange(bool zoom_in) {
543 }
544
545 gfx::NativeWindow ExternalTabContainer::GetFrameNativeWindow() {
546 return hwnd();
547 }
548
549 bool ExternalTabContainer::TakeFocus(bool reverse) {
550 if (automation_) {
551 automation_->Send(new AutomationMsg_TabbedOut(tab_handle_,
552 base::win::IsShiftPressed()));
553 }
554
555 return true;
556 }
557
558 bool ExternalTabContainer::CanDownload(RenderViewHost* render_view_host,
559 int request_id,
560 const std::string& request_method) {
561 if (load_requests_via_automation_) {
562 if (automation_) {
563 // In case the host needs to show UI that needs to take the focus.
564 ::AllowSetForegroundWindow(ASFW_ANY);
565
566 BrowserThread::PostTask(
567 BrowserThread::IO, FROM_HERE,
568 base::Bind(
569 base::IgnoreResult(
570 &AutomationResourceMessageFilter::SendDownloadRequestToHost),
571 automation_resource_message_filter_.get(), 0, tab_handle_,
572 request_id));
573 }
574 } else {
575 DLOG(WARNING) << "Downloads are only supported with host browser network "
576 "stack enabled.";
577 }
578
579 // Never allow downloads.
580 return false;
581 }
582
583 void ExternalTabContainer::RegisterRenderViewHostForAutomation(
584 RenderViewHost* render_view_host, bool pending_view) {
585 if (render_view_host) {
586 AutomationResourceMessageFilter::RegisterRenderView(
587 render_view_host->GetProcess()->GetID(),
588 render_view_host->GetRoutingID(),
589 tab_handle(),
590 automation_resource_message_filter_,
591 pending_view);
592 }
593 }
594
595 void ExternalTabContainer::RegisterRenderViewHost(
596 RenderViewHost* render_view_host) {
597 // RenderViewHost instances that are to be associated with this
598 // ExternalTabContainer should share the same resource request automation
599 // settings.
600 RegisterRenderViewHostForAutomation(
601 render_view_host,
602 false); // Network requests should not be handled later.
603 }
604
605 void ExternalTabContainer::UnregisterRenderViewHost(
606 RenderViewHost* render_view_host) {
607 // Undo the resource automation registration performed in
608 // ExternalTabContainer::RegisterRenderViewHost.
609 if (render_view_host) {
610 AutomationResourceMessageFilter::UnRegisterRenderView(
611 render_view_host->GetProcess()->GetID(),
612 render_view_host->GetRoutingID());
613 }
614 }
615
616 content::JavaScriptDialogCreator*
617 ExternalTabContainer::GetJavaScriptDialogCreator() {
618 return GetJavaScriptDialogCreatorInstance();
619 }
620
621 bool ExternalTabContainer::HandleContextMenu(
622 const content::ContextMenuParams& params) {
623 if (!automation_) {
624 NOTREACHED();
625 return false;
626 }
627 external_context_menu_.reset(
628 new RenderViewContextMenuViews(web_contents(), params));
629 external_context_menu_->SetExternal();
630 external_context_menu_->Init();
631 external_context_menu_->UpdateMenuItemStates();
632
633 scoped_ptr<ContextMenuModel> context_menu_model(
634 ConvertMenuModel(&external_context_menu_->menu_model()));
635
636 POINT screen_pt = { params.x, params.y };
637 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1);
638
639 MiniContextMenuParams ipc_params;
640 ipc_params.screen_x = screen_pt.x;
641 ipc_params.screen_y = screen_pt.y;
642 ipc_params.link_url = params.link_url;
643 ipc_params.unfiltered_link_url = params.unfiltered_link_url;
644 ipc_params.src_url = params.src_url;
645 ipc_params.page_url = params.page_url;
646 ipc_params.keyword_url = params.keyword_url;
647 ipc_params.frame_url = params.frame_url;
648
649 bool rtl = base::i18n::IsRTL();
650 automation_->Send(
651 new AutomationMsg_ForwardContextMenuToExternalHost(tab_handle_,
652 *context_menu_model,
653 rtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN, ipc_params));
654
655 return true;
656 }
657
658 bool ExternalTabContainer::ExecuteContextMenuCommand(int command) {
659 if (!external_context_menu_.get()) {
660 NOTREACHED();
661 return false;
662 }
663
664 switch (command) {
665 case IDS_CONTENT_CONTEXT_SAVEAUDIOAS:
666 case IDS_CONTENT_CONTEXT_SAVEVIDEOAS:
667 case IDS_CONTENT_CONTEXT_SAVEIMAGEAS:
668 case IDS_CONTENT_CONTEXT_SAVELINKAS: {
669 NOTREACHED(); // Should be handled in host.
670 break;
671 }
672 }
673
674 external_context_menu_->ExecuteCommand(command);
675 return true;
676 }
677
678 bool ExternalTabContainer::PreHandleKeyboardEvent(
679 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
680 return false;
681 }
682
683 void ExternalTabContainer::HandleKeyboardEvent(
684 const NativeWebKeyboardEvent& event) {
685 ProcessUnhandledKeyStroke(event.os_event.hwnd, event.os_event.message,
686 event.os_event.wParam, event.os_event.lParam);
687 }
688
689 void ExternalTabContainer::BeforeUnloadFired(WebContents* tab,
690 bool proceed,
691 bool* proceed_to_fire_unload) {
692 *proceed_to_fire_unload = true;
693
694 if (!automation_) {
695 delete unload_reply_message_;
696 unload_reply_message_ = NULL;
697 return;
698 }
699
700 if (!unload_reply_message_) {
701 NOTREACHED() << "**** NULL unload reply message pointer.";
702 return;
703 }
704
705 if (!proceed) {
706 AutomationMsg_RunUnloadHandlers::WriteReplyParams(unload_reply_message_,
707 false);
708 automation_->Send(unload_reply_message_);
709 unload_reply_message_ = NULL;
710 *proceed_to_fire_unload = false;
711 }
712 }
713
714 void ExternalTabContainer::ShowRepostFormWarningDialog(
715 WebContents* source) {
716 browser::ShowTabModalConfirmDialog(
717 new RepostFormWarningController(source),
718 TabContentsWrapper::GetCurrentWrapperForContents(source));
719 }
720
721 void ExternalTabContainer::RunFileChooser(
722 WebContents* tab, const content::FileChooserParams& params) {
723 Browser::RunFileChooserHelper(tab, params);
724 }
725
726 void ExternalTabContainer::EnumerateDirectory(WebContents* tab, int request_id,
727 const FilePath& path) {
728 Browser::EnumerateDirectoryHelper(tab, request_id, path);
729 }
730
731 void ExternalTabContainer::JSOutOfMemory(WebContents* tab) {
732 Browser::JSOutOfMemoryHelper(tab);
733 }
734
735 void ExternalTabContainer::RegisterProtocolHandler(WebContents* tab,
736 const std::string& protocol,
737 const GURL& url,
738 const string16& title) {
739 Browser::RegisterProtocolHandlerHelper(tab, protocol, url, title);
740 }
741
742 void ExternalTabContainer::RegisterIntentHandler(WebContents* tab,
743 const string16& action,
744 const string16& type,
745 const string16& href,
746 const string16& title,
747 const string16& disposition) {
748 Browser::RegisterIntentHandlerHelper(
749 tab, action, type, href, title, disposition);
750 }
751
752 void ExternalTabContainer::WebIntentDispatch(
753 WebContents* tab,
754 content::WebIntentsDispatcher* intents_dispatcher) {
755 // TODO(binji) How do we want to display the WebIntentPicker bubble if there
756 // is no BrowserWindow?
757 delete intents_dispatcher;
758 }
759
760 void ExternalTabContainer::FindReply(WebContents* tab,
761 int request_id,
762 int number_of_matches,
763 const gfx::Rect& selection_rect,
764 int active_match_ordinal,
765 bool final_update) {
766 Browser::FindReplyHelper(tab, request_id, number_of_matches, selection_rect,
767 active_match_ordinal, final_update);
768 }
769
770 void ExternalTabContainer::CrashedPlugin(WebContents* tab,
771 const FilePath& plugin_path) {
772 Browser::CrashedPluginHelper(tab, plugin_path);
773 }
774
775 bool ExternalTabContainer::OnMessageReceived(const IPC::Message& message) {
776 bool handled = true;
777 IPC_BEGIN_MESSAGE_MAP(ExternalTabContainer, message)
778 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ForwardMessageToExternalHost,
779 OnForwardMessageToExternalHost)
780 IPC_MESSAGE_UNHANDLED(handled = false)
781 IPC_END_MESSAGE_MAP()
782 return handled;
783 }
784
785 void ExternalTabContainer::DidFailProvisionalLoad(
786 int64 frame_id,
787 bool is_main_frame,
788 const GURL& validated_url,
789 int error_code,
790 const string16& error_description) {
791 automation_->Send(new AutomationMsg_NavigationFailed(
792 tab_handle_, error_code, validated_url));
793 ignore_next_load_notification_ = true;
794 }
795
796 void ExternalTabContainer::OnForwardMessageToExternalHost(
797 const std::string& message,
798 const std::string& origin,
799 const std::string& target) {
800 if (automation_) {
801 automation_->Send(new AutomationMsg_ForwardMessageToExternalHost(
802 tab_handle_, message, origin, target));
803 }
804 }
805
806 ////////////////////////////////////////////////////////////////////////////////
807 // ExternalTabContainer, NotificationObserver implementation:
808
809 void ExternalTabContainer::Observe(
810 int type,
811 const content::NotificationSource& source,
812 const content::NotificationDetails& details) {
813 if (!automation_)
814 return;
815
816 static const int kHttpClientErrorStart = 400;
817 static const int kHttpServerErrorEnd = 510;
818
819 switch (type) {
820 case content::NOTIFICATION_LOAD_STOP: {
821 const LoadNotificationDetails* load =
822 content::Details<LoadNotificationDetails>(details).ptr();
823 if (load && content::PageTransitionIsMainFrame(load->origin)) {
824 TRACE_EVENT_END_ETW("ExternalTabContainer::Navigate", 0,
825 load->url.spec());
826 automation_->Send(new AutomationMsg_TabLoaded(tab_handle_,
827 load->url));
828 }
829 break;
830 }
831 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
832 if (ignore_next_load_notification_) {
833 ignore_next_load_notification_ = false;
834 return;
835 }
836
837 const content::LoadCommittedDetails* commit =
838 content::Details<content::LoadCommittedDetails>(details).ptr();
839
840 if (commit->http_status_code >= kHttpClientErrorStart &&
841 commit->http_status_code <= kHttpServerErrorEnd) {
842 automation_->Send(new AutomationMsg_NavigationFailed(
843 tab_handle_, commit->http_status_code, commit->entry->GetURL()));
844
845 ignore_next_load_notification_ = true;
846 } else {
847 NavigationInfo navigation_info;
848 // When the previous entry index is invalid, it will be -1, which
849 // will still make the computation come out right (navigating to the
850 // 0th entry will be +1).
851 if (InitNavigationInfo(&navigation_info, commit->type,
852 commit->previous_entry_index -
853 tab_contents_->web_contents()->
854 GetController().GetLastCommittedEntryIndex()))
855 automation_->Send(new AutomationMsg_DidNavigate(tab_handle_,
856 navigation_info));
857 }
858 break;
859 }
860 case content::NOTIFICATION_RENDER_VIEW_HOST_CREATED_FOR_TAB: {
861 if (load_requests_via_automation_) {
862 RenderViewHost* rvh = content::Details<RenderViewHost>(details).ptr();
863 RegisterRenderViewHostForAutomation(rvh, false);
864 }
865 break;
866 }
867 case content::NOTIFICATION_RENDER_VIEW_HOST_DELETED: {
868 if (load_requests_via_automation_) {
869 RenderViewHost* rvh = content::Source<RenderViewHost>(source).ptr();
870 UnregisterRenderViewHost(rvh);
871 }
872 break;
873 }
874 case content::NOTIFICATION_RENDER_VIEW_HOST_CREATED: {
875 if (load_requests_via_automation_) {
876 RenderViewHost* rvh = content::Source<RenderViewHost>(source).ptr();
877 RegisterRenderViewHostForAutomation(rvh, false);
878 }
879 break;
880 }
881 default:
882 NOTREACHED();
883 }
884 }
885
886 ////////////////////////////////////////////////////////////////////////////////
887 // ExternalTabContainer, views::NativeWidgetWin overrides:
888
889 LRESULT ExternalTabContainer::OnCreate(LPCREATESTRUCT create_struct) {
890 LRESULT result = views::NativeWidgetWin::OnCreate(create_struct);
891 if (result == 0) {
892 // Grab a reference here which will be released in OnFinalMessage
893 AddRef();
894 }
895 return result;
896 }
897
898 void ExternalTabContainer::OnDestroy() {
899 prop_.reset();
900 Uninitialize();
901 NativeWidgetWin::OnDestroy();
902 }
903
904 void ExternalTabContainer::OnFinalMessage(HWND window) {
905 GetWidget()->OnNativeWidgetDestroyed();
906 // Release the reference which we grabbed in WM_CREATE.
907 Release();
908 }
909
910 void ExternalTabContainer::RunUnloadHandlers(IPC::Message* reply_message) {
911 if (!automation_) {
912 delete reply_message;
913 return;
914 }
915
916 // If we have a pending unload message, then just respond back to this
917 // request and continue processing the previous unload message.
918 if (unload_reply_message_) {
919 AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message, true);
920 automation_->Send(reply_message);
921 return;
922 }
923
924 unload_reply_message_ = reply_message;
925 bool wait_for_unload_handlers =
926 tab_contents_.get() &&
927 Browser::RunUnloadEventsHelper(tab_contents_->web_contents());
928 if (!wait_for_unload_handlers) {
929 AutomationMsg_RunUnloadHandlers::WriteReplyParams(reply_message, true);
930 automation_->Send(reply_message);
931 unload_reply_message_ = NULL;
932 }
933 }
934
935 ////////////////////////////////////////////////////////////////////////////////
936 // ExternalTabContainer, private:
937 bool ExternalTabContainer::ProcessUnhandledKeyStroke(HWND window,
938 UINT message,
939 WPARAM wparam,
940 LPARAM lparam) {
941 if (!automation_) {
942 return false;
943 }
944 if ((wparam == VK_TAB) && !base::win::IsCtrlPressed()) {
945 // Tabs are handled separately (except if this is Ctrl-Tab or
946 // Ctrl-Shift-Tab)
947 return false;
948 }
949
950 // Send this keystroke to the external host as it could be processed as an
951 // accelerator there. If the host does not handle this accelerator, it will
952 // reflect the accelerator back to us via the ProcessUnhandledAccelerator
953 // method.
954 MSG msg = {0};
955 msg.hwnd = window;
956 msg.message = message;
957 msg.wParam = wparam;
958 msg.lParam = lparam;
959 automation_->Send(new AutomationMsg_HandleAccelerator(tab_handle_, msg));
960 return true;
961 }
962
963 bool ExternalTabContainer::InitNavigationInfo(NavigationInfo* nav_info,
964 content::NavigationType nav_type,
965 int relative_offset) {
966 DCHECK(nav_info);
967 NavigationEntry* entry =
968 tab_contents_->web_contents()->GetController().GetActiveEntry();
969 // If this is very early in the game then we may not have an entry.
970 if (!entry)
971 return false;
972
973 nav_info->navigation_type = nav_type;
974 nav_info->relative_offset = relative_offset;
975 nav_info->navigation_index =
976 tab_contents_->web_contents()->GetController().GetCurrentEntryIndex();
977 nav_info->url = entry->GetURL();
978 nav_info->referrer = entry->GetReferrer().url;
979 nav_info->title = UTF16ToWideHack(entry->GetTitle());
980 if (nav_info->title.empty())
981 nav_info->title = UTF8ToWide(nav_info->url.spec());
982
983 nav_info->security_style = entry->GetSSL().security_style;
984 int content_status = entry->GetSSL().content_status;
985 nav_info->displayed_insecure_content =
986 !!(content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT);
987 nav_info->ran_insecure_content =
988 !!(content_status & SSLStatus::RAN_INSECURE_CONTENT);
989 return true;
990 }
991
992 scoped_refptr<ExternalTabContainer> ExternalTabContainer::RemovePendingTab(
993 uintptr_t cookie) {
994 ExternalTabContainer::PendingTabs& pending_tabs = pending_tabs_.Get();
995 PendingTabs::iterator index = pending_tabs.find(cookie);
996 if (index != pending_tabs.end()) {
997 scoped_refptr<ExternalTabContainer> container = (*index).second;
998 pending_tabs.erase(index);
999 return container;
1000 }
1001
1002 NOTREACHED() << "Failed to find ExternalTabContainer for cookie: "
1003 << cookie;
1004 return NULL;
1005 }
1006
1007 SkColor ExternalTabContainer::GetInfoBarSeparatorColor() const {
1008 return ThemeService::GetDefaultColor(ThemeService::COLOR_TOOLBAR_SEPARATOR);
1009 }
1010
1011 void ExternalTabContainer::InfoBarContainerStateChanged(bool is_animating) {
1012 if (external_tab_view_)
1013 external_tab_view_->Layout();
1014 }
1015
1016 bool ExternalTabContainer::DrawInfoBarArrows(int* x) const {
1017 return false;
1018 }
1019
1020 bool ExternalTabContainer::AcceleratorPressed(
1021 const ui::Accelerator& accelerator) {
1022 std::map<ui::Accelerator, int>::const_iterator iter =
1023 accelerator_table_.find(accelerator);
1024 DCHECK(iter != accelerator_table_.end());
1025
1026 if (!tab_contents_.get() ||
1027 !tab_contents_->web_contents()->GetRenderViewHost()) {
1028 NOTREACHED();
1029 return false;
1030 }
1031
1032 RenderViewHost* host = tab_contents_->web_contents()->GetRenderViewHost();
1033 int command_id = iter->second;
1034 switch (command_id) {
1035 case IDC_ZOOM_PLUS:
1036 host->Zoom(content::PAGE_ZOOM_IN);
1037 break;
1038 case IDC_ZOOM_NORMAL:
1039 host->Zoom(content::PAGE_ZOOM_RESET);
1040 break;
1041 case IDC_ZOOM_MINUS:
1042 host->Zoom(content::PAGE_ZOOM_OUT);
1043 break;
1044 case IDC_DEV_TOOLS:
1045 DevToolsWindow::ToggleDevToolsWindow(
1046 tab_contents_->web_contents()->GetRenderViewHost(),
1047 DEVTOOLS_TOGGLE_ACTION_NONE);
1048 break;
1049 case IDC_DEV_TOOLS_CONSOLE:
1050 DevToolsWindow::ToggleDevToolsWindow(
1051 tab_contents_->web_contents()->GetRenderViewHost(),
1052 DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
1053 break;
1054 case IDC_DEV_TOOLS_INSPECT:
1055 DevToolsWindow::ToggleDevToolsWindow(
1056 tab_contents_->web_contents()->GetRenderViewHost(),
1057 DEVTOOLS_TOGGLE_ACTION_INSPECT);
1058 break;
1059 default:
1060 NOTREACHED() << "Unsupported accelerator: " << command_id;
1061 return false;
1062 }
1063 return true;
1064 }
1065
1066 bool ExternalTabContainer::CanHandleAccelerators() const {
1067 return true;
1068 }
1069
1070 void ExternalTabContainer::Navigate(const GURL& url, const GURL& referrer) {
1071 if (!tab_contents_.get()) {
1072 NOTREACHED();
1073 return;
1074 }
1075
1076 TRACE_EVENT_BEGIN_ETW("ExternalTabContainer::Navigate", 0, url.spec());
1077
1078 tab_contents_->web_contents()->GetController().LoadURL(
1079 url, content::Referrer(referrer, WebKit::WebReferrerPolicyDefault),
1080 content::PAGE_TRANSITION_START_PAGE, std::string());
1081 }
1082
1083 bool ExternalTabContainer::OnGoToEntryOffset(int offset) {
1084 if (load_requests_via_automation_) {
1085 automation_->Send(new AutomationMsg_RequestGoToHistoryEntryOffset(
1086 tab_handle_, offset));
1087 return false;
1088 }
1089
1090 return true;
1091 }
1092
1093 void ExternalTabContainer::LoadAccelerators() {
1094 HACCEL accelerator_table = AtlLoadAccelerators(IDR_CHROMEFRAME);
1095 DCHECK(accelerator_table);
1096
1097 // We have to copy the table to access its contents.
1098 int count = CopyAcceleratorTable(accelerator_table, 0, 0);
1099 if (count == 0) {
1100 // Nothing to do in that case.
1101 return;
1102 }
1103
1104 scoped_array<ACCEL> scoped_accelerators(new ACCEL[count]);
1105 ACCEL* accelerators = scoped_accelerators.get();
1106 DCHECK(accelerators != NULL);
1107
1108 CopyAcceleratorTable(accelerator_table, accelerators, count);
1109
1110 focus_manager_ = GetWidget()->GetFocusManager();
1111 DCHECK(focus_manager_);
1112
1113 // Let's fill our own accelerator table.
1114 for (int i = 0; i < count; ++i) {
1115 bool alt_down = (accelerators[i].fVirt & FALT) == FALT;
1116 bool ctrl_down = (accelerators[i].fVirt & FCONTROL) == FCONTROL;
1117 bool shift_down = (accelerators[i].fVirt & FSHIFT) == FSHIFT;
1118 ui::Accelerator accelerator(
1119 static_cast<ui::KeyboardCode>(accelerators[i].key),
1120 shift_down, ctrl_down, alt_down);
1121 accelerator_table_[accelerator] = accelerators[i].cmd;
1122
1123 // Also register with the focus manager.
1124 if (focus_manager_) {
1125 focus_manager_->RegisterAccelerator(
1126 accelerator, ui::AcceleratorManager::kNormalPriority, this);
1127 }
1128 }
1129 }
1130
1131 void ExternalTabContainer::OnReinitialize() {
1132 if (load_requests_via_automation_) {
1133 RenderViewHost* rvh = tab_contents_->web_contents()->GetRenderViewHost();
1134 if (rvh) {
1135 AutomationResourceMessageFilter::ResumePendingRenderView(
1136 rvh->GetProcess()->GetID(), rvh->GetRoutingID(),
1137 tab_handle_, automation_resource_message_filter_);
1138 }
1139 }
1140
1141 NavigationStateChanged(web_contents(), 0);
1142 ServicePendingOpenURLRequests();
1143 }
1144
1145 void ExternalTabContainer::ServicePendingOpenURLRequests() {
1146 DCHECK(pending());
1147
1148 set_pending(false);
1149
1150 for (size_t index = 0; index < pending_open_url_requests_.size();
1151 ++index) {
1152 const OpenURLParams& url_request = pending_open_url_requests_[index];
1153 OpenURLFromTab(web_contents(), url_request);
1154 }
1155 pending_open_url_requests_.clear();
1156 }
1157
1158 void ExternalTabContainer::SetupExternalTabView() {
1159 // Create a TabContentsContainer to handle focus cycling using Tab and
1160 // Shift-Tab.
1161 tab_contents_container_ = new TabContentsContainer;
1162
1163 // The views created here will be destroyed when the ExternalTabContainer
1164 // widget is torn down.
1165 external_tab_view_ = new views::View();
1166
1167 InfoBarContainerView* info_bar_container = new InfoBarContainerView(this);
1168 info_bar_container->ChangeTabContents(tab_contents_->infobar_tab_helper());
1169
1170 views::GridLayout* layout = new views::GridLayout(external_tab_view_);
1171 // Give this column an identifier of 0.
1172 views::ColumnSet* columns = layout->AddColumnSet(0);
1173 columns->AddColumn(views::GridLayout::FILL,
1174 views::GridLayout::FILL,
1175 1,
1176 views::GridLayout::USE_PREF,
1177 0,
1178 0);
1179
1180 external_tab_view_->SetLayoutManager(layout);
1181
1182 layout->StartRow(0, 0);
1183 layout->AddView(info_bar_container);
1184 layout->StartRow(1, 0);
1185 layout->AddView(tab_contents_container_);
1186 GetWidget()->SetContentsView(external_tab_view_);
1187 // Note that SetTabContents must be called after AddChildView is called
1188 tab_contents_container_->ChangeWebContents(web_contents());
1189 }
1190
1191 TemporaryPopupExternalTabContainer::TemporaryPopupExternalTabContainer(
1192 AutomationProvider* automation,
1193 AutomationResourceMessageFilter* filter)
1194 : ExternalTabContainer(automation, filter) {
1195 }
1196
1197 TemporaryPopupExternalTabContainer::~TemporaryPopupExternalTabContainer() {
1198 DVLOG(1) << __FUNCTION__;
1199 }
1200
1201 WebContents* TemporaryPopupExternalTabContainer::OpenURLFromTab(
1202 WebContents* source,
1203 const OpenURLParams& params) {
1204 if (!automation_)
1205 return NULL;
1206
1207 OpenURLParams forward_params = params;
1208 if (params.disposition == CURRENT_TAB) {
1209 DCHECK(route_all_top_level_navigations_);
1210 forward_params.disposition = NEW_FOREGROUND_TAB;
1211 }
1212 WebContents* new_contents =
1213 ExternalTabContainer::OpenURLFromTab(source, forward_params);
1214 // support only one navigation for a dummy tab before it is killed.
1215 ::DestroyWindow(GetNativeView());
1216 return new_contents;
1217 }
OLDNEW
« no previous file with comments | « chrome/browser/external_tab_container_win.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698