1 // Copyright 2014 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 "athena/content/public/web_contents_view_delegate_creator.h" 6 7 #include "athena/content/render_view_context_menu_impl.h" 8 #include "components/web_modal/popup_manager.h" 9 #include "components/web_modal/single_web_contents_dialog_manager.h" 10 #include "components/web_modal/web_contents_modal_dialog_host.h" 11 #include "components/web_modal/web_contents_modal_dialog_manager.h" 12 #include "content/public/browser/render_widget_host_view.h" 13 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents_delegate.h" 15 #include "content/public/browser/web_contents_view_delegate.h" 16 #include "ui/aura/client/screen_position_client.h" 17 #include "ui/aura/window.h" 18 #include "ui/views/widget/widget.h" 19 20 namespace athena { 21 namespace { 22 23 class WebContentsViewDelegateImpl : public content::WebContentsViewDelegate { 24 public: 25 explicit WebContentsViewDelegateImpl(content::WebContents* web_contents) 26 : web_contents_(web_contents) {} 27 virtual ~WebContentsViewDelegateImpl() {} 28 29 virtual content::WebDragDestDelegate* GetDragDestDelegate() OVERRIDE { 30 // TODO(oshima): crbug.com/401610 31 return NULL; 32 } 33 34 virtual bool Focus() OVERRIDE { 35 web_modal::PopupManager* popup_manager = 36 web_modal::PopupManager::FromWebContents(web_contents_); 37 if (popup_manager) 38 popup_manager->WasFocused(web_contents_); 39 return false; 40 } 41 42 virtual void ShowContextMenu( 43 content::RenderFrameHost* render_frame_host, 44 const content::ContextMenuParams& params) OVERRIDE { 45 ShowMenu(BuildMenu( 46 content::WebContents::FromRenderFrameHost(render_frame_host), params)); 47 } 48 49 virtual void SizeChanged(const gfx::Size& size) OVERRIDE { 50 // TODO(oshima|sadrul): Implement this when sad_tab is componentized. 51 // See c/b/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc 52 } 53 54 virtual void ShowDisambiguationPopup( 55 const gfx::Rect& target_rect, 56 const SkBitmap& zoomed_bitmap, 57 const gfx::NativeView content, 58 const base::Callback<void(ui::GestureEvent*)>& gesture_cb, 59 const base::Callback<void(ui::MouseEvent*)>& mouse_cb) OVERRIDE { 60 } 61 62 virtual void HideDisambiguationPopup() OVERRIDE { 63 } 64 65 scoped_ptr<RenderViewContextMenuImpl> BuildMenu( 66 content::WebContents* web_contents, 67 const content::ContextMenuParams& params) { 68 scoped_ptr<RenderViewContextMenuImpl> menu; 69 content::RenderFrameHost* focused_frame = web_contents->GetFocusedFrame(); 70 // If the frame tree does not have a focused frame at this point, do not 71 // bother creating RenderViewContextMenuViews. 72 // This happens if the frame has navigated to a different page before 73 // ContextMenu message was received by the current RenderFrameHost. 74 if (focused_frame) { 75 menu.reset(new RenderViewContextMenuImpl(focused_frame, params)); 76 menu->Init(); 77 } 78 return menu.Pass(); 79 } 80 81 void ShowMenu(scoped_ptr<RenderViewContextMenuImpl> menu) { 82 context_menu_.reset(menu.release()); 83 84 if (!context_menu_.get()) 85 return; 86 87 // Menus need a Widget to work. If we're not the active tab we won't 88 // necessarily be in a widget. 89 views::Widget* top_level_widget = GetTopLevelWidget(); 90 if (!top_level_widget) 91 return; 92 93 const content::ContextMenuParams& params = context_menu_->params(); 94 // Don't show empty menus. 95 if (context_menu_->menu_model().GetItemCount() == 0) 96 return; 97 98 gfx::Point screen_point(params.x, params.y); 99 100 // Convert from target window coordinates to root window coordinates. 101 aura::Window* target_window = GetActiveNativeView(); 102 aura::Window* root_window = target_window->GetRootWindow(); 103 aura::client::ScreenPositionClient* screen_position_client = 104 aura::client::GetScreenPositionClient(root_window); 105 if (screen_position_client) { 106 screen_position_client->ConvertPointToScreen(target_window, 107 &screen_point); 108 } 109 // Enable recursive tasks on the message loop so we can get updates while 110 // the context menu is being displayed. 111 base::MessageLoop::ScopedNestableTaskAllower allow( 112 base::MessageLoop::current()); 113 context_menu_->RunMenuAt( 114 top_level_widget, screen_point, params.source_type); 115 } 116 117 aura::Window* GetActiveNativeView() { 118 return web_contents_->GetFullscreenRenderWidgetHostView() 119 ? web_contents_->GetFullscreenRenderWidgetHostView() 120 ->GetNativeView() 121 : web_contents_->GetNativeView(); 122 } 123 124 views::Widget* GetTopLevelWidget() { 125 return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView()); 126 } 127 128 views::FocusManager* GetFocusManager() { 129 views::Widget* toplevel_widget = GetTopLevelWidget(); 130 return toplevel_widget ? toplevel_widget->GetFocusManager() : NULL; 131 } 132 133 void SetInitialFocus() { 134 if (web_contents_->FocusLocationBarByDefault()) { 135 if (web_contents_->GetDelegate()) 136 web_contents_->GetDelegate()->SetFocusToLocationBar(false); 137 } else { 138 web_contents_->Focus(); 139 } 140 } 141 scoped_ptr<RenderViewContextMenuImpl> context_menu_; 142 content::WebContents* web_contents_; 143 DISALLOW_COPY_AND_ASSIGN(WebContentsViewDelegateImpl); 144 }; 145 146 } // namespace 147 148 content::WebContentsViewDelegate* CreateWebContentsViewDelegate( 149 content::WebContents* web_contents) { 150 return new WebContentsViewDelegateImpl(web_contents); 151 } 152 153 } // namespace athena 154