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 "content/browser/web_contents/web_contents_view_guest.h" 6 7 #include "build/build_config.h" 8 #include "content/browser/browser_plugin/browser_plugin_embedder.h" 9 #include "content/browser/browser_plugin/browser_plugin_guest.h" 10 #include "content/browser/frame_host/interstitial_page_impl.h" 11 #include "content/browser/frame_host/render_widget_host_view_guest.h" 12 #include "content/browser/renderer_host/render_view_host_factory.h" 13 #include "content/browser/renderer_host/render_view_host_impl.h" 14 #include "content/browser/web_contents/web_contents_impl.h" 15 #include "content/common/drag_messages.h" 16 #include "content/public/browser/user_metrics.h" 17 #include "content/public/browser/web_contents_delegate.h" 18 #include "content/public/common/context_menu_params.h" 19 #include "content/public/common/drop_data.h" 20 #include "ui/gfx/image/image_skia.h" 21 #include "ui/gfx/point.h" 22 #include "ui/gfx/rect.h" 23 #include "ui/gfx/size.h" 24 25 #if defined(USE_AURA) 26 #include "ui/aura/window.h" 27 #endif 28 29 using blink::WebDragOperation; 30 using blink::WebDragOperationsMask; 31 32 namespace content { 33 34 WebContentsViewGuest::WebContentsViewGuest( 35 WebContentsImpl* web_contents, 36 BrowserPluginGuest* guest, 37 scoped_ptr<WebContentsView> platform_view, 38 RenderViewHostDelegateView* platform_view_delegate_view) 39 : web_contents_(web_contents), 40 guest_(guest), 41 platform_view_(platform_view.Pass()), 42 platform_view_delegate_view_(platform_view_delegate_view) { 43 } 44 45 WebContentsViewGuest::~WebContentsViewGuest() { 46 } 47 48 gfx::NativeView WebContentsViewGuest::GetNativeView() const { 49 return platform_view_->GetNativeView(); 50 } 51 52 gfx::NativeView WebContentsViewGuest::GetContentNativeView() const { 53 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 54 if (!rwhv) 55 return NULL; 56 return rwhv->GetNativeView(); 57 } 58 59 gfx::NativeWindow WebContentsViewGuest::GetTopLevelNativeWindow() const { 60 return guest_->embedder_web_contents()->GetTopLevelNativeWindow(); 61 } 62 63 void WebContentsViewGuest::OnGuestInitialized(WebContentsView* parent_view) { 64 #if defined(USE_AURA) 65 // In aura, ScreenPositionClient doesn't work properly if we do 66 // not have the native view associated with this WebContentsViewGuest in the 67 // view hierarchy. We add this view as embedder's child here. 68 // This would go in WebContentsViewGuest::CreateView, but that is too early to 69 // access embedder_web_contents(). Therefore, we do it here. 70 parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView()); 71 #endif // defined(USE_AURA) 72 } 73 74 ContextMenuParams WebContentsViewGuest::ConvertContextMenuParams( 75 const ContextMenuParams& params) const { 76 // We need to add |offset| of the guest from the embedder to position the 77 // menu properly. 78 gfx::Rect embedder_bounds; 79 guest_->embedder_web_contents()->GetView()->GetContainerBounds( 80 &embedder_bounds); 81 gfx::Rect guest_bounds; 82 GetContainerBounds(&guest_bounds); 83 84 gfx::Vector2d offset = guest_bounds.origin() - embedder_bounds.origin(); 85 ContextMenuParams params_in_embedder = params; 86 params_in_embedder.x += offset.x(); 87 params_in_embedder.y += offset.y(); 88 return params_in_embedder; 89 } 90 91 void WebContentsViewGuest::GetContainerBounds(gfx::Rect* out) const { 92 if (guest_->embedder_web_contents()) { 93 // We need embedder container's bounds to calculate our bounds. 94 guest_->embedder_web_contents()->GetView()->GetContainerBounds(out); 95 gfx::Point guest_coordinates = guest_->GetScreenCoordinates(gfx::Point()); 96 out->Offset(guest_coordinates.x(), guest_coordinates.y()); 97 } else { 98 out->set_origin(gfx::Point()); 99 } 100 101 out->set_size(size_); 102 } 103 104 void WebContentsViewGuest::SizeContents(const gfx::Size& size) { 105 size_ = size; 106 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 107 if (rwhv) 108 rwhv->SetSize(size); 109 } 110 111 void WebContentsViewGuest::SetInitialFocus() { 112 platform_view_->SetInitialFocus(); 113 } 114 115 gfx::Rect WebContentsViewGuest::GetViewBounds() const { 116 return gfx::Rect(size_); 117 } 118 119 #if defined(OS_MACOSX) 120 void WebContentsViewGuest::SetAllowOtherViews(bool allow) { 121 platform_view_->SetAllowOtherViews(allow); 122 } 123 124 bool WebContentsViewGuest::GetAllowOtherViews() const { 125 return platform_view_->GetAllowOtherViews(); 126 } 127 #endif 128 129 void WebContentsViewGuest::CreateView(const gfx::Size& initial_size, 130 gfx::NativeView context) { 131 platform_view_->CreateView(initial_size, context); 132 size_ = initial_size; 133 } 134 135 RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForWidget( 136 RenderWidgetHost* render_widget_host) { 137 if (render_widget_host->GetView()) { 138 // During testing, the view will already be set up in most cases to the 139 // test view, so we don't want to clobber it with a real one. To verify that 140 // this actually is happening (and somebody isn't accidentally creating the 141 // view twice), we check for the RVH Factory, which will be set when we're 142 // making special ones (which go along with the special views). 143 DCHECK(RenderViewHostFactory::has_factory()); 144 return static_cast<RenderWidgetHostViewBase*>( 145 render_widget_host->GetView()); 146 } 147 148 RenderWidgetHostViewBase* platform_widget = 149 platform_view_->CreateViewForWidget(render_widget_host); 150 151 RenderWidgetHostViewBase* view = new RenderWidgetHostViewGuest( 152 render_widget_host, 153 guest_, 154 platform_widget); 155 156 return view; 157 } 158 159 RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForPopupWidget( 160 RenderWidgetHost* render_widget_host) { 161 return platform_view_->CreateViewForPopupWidget(render_widget_host); 162 } 163 164 void WebContentsViewGuest::SetPageTitle(const base::string16& title) { 165 } 166 167 void WebContentsViewGuest::RenderViewCreated(RenderViewHost* host) { 168 platform_view_->RenderViewCreated(host); 169 } 170 171 void WebContentsViewGuest::RenderViewSwappedIn(RenderViewHost* host) { 172 platform_view_->RenderViewSwappedIn(host); 173 } 174 175 void WebContentsViewGuest::SetOverscrollControllerEnabled(bool enabled) { 176 // This should never override the setting of the embedder view. 177 } 178 179 #if defined(OS_MACOSX) 180 bool WebContentsViewGuest::IsEventTracking() const { 181 return false; 182 } 183 184 void WebContentsViewGuest::CloseTabAfterEventTracking() { 185 } 186 #endif 187 188 WebContents* WebContentsViewGuest::web_contents() { 189 return web_contents_; 190 } 191 192 void WebContentsViewGuest::RestoreFocus() { 193 platform_view_->RestoreFocus(); 194 } 195 196 void WebContentsViewGuest::Focus() { 197 platform_view_->Focus(); 198 } 199 200 void WebContentsViewGuest::StoreFocus() { 201 platform_view_->StoreFocus(); 202 } 203 204 DropData* WebContentsViewGuest::GetDropData() const { 205 NOTIMPLEMENTED(); 206 return NULL; 207 } 208 209 void WebContentsViewGuest::UpdateDragCursor(WebDragOperation operation) { 210 RenderViewHostImpl* embedder_render_view_host = 211 static_cast<RenderViewHostImpl*>( 212 guest_->embedder_web_contents()->GetRenderViewHost()); 213 CHECK(embedder_render_view_host); 214 RenderViewHostDelegateView* view = 215 embedder_render_view_host->GetDelegate()->GetDelegateView(); 216 if (view) 217 view->UpdateDragCursor(operation); 218 } 219 220 void WebContentsViewGuest::GotFocus() { 221 } 222 223 void WebContentsViewGuest::TakeFocus(bool reverse) { 224 } 225 226 void WebContentsViewGuest::ShowContextMenu(RenderFrameHost* render_frame_host, 227 const ContextMenuParams& params) { 228 platform_view_delegate_view_->ShowContextMenu( 229 render_frame_host, ConvertContextMenuParams(params)); 230 } 231 232 void WebContentsViewGuest::StartDragging( 233 const DropData& drop_data, 234 WebDragOperationsMask ops, 235 const gfx::ImageSkia& image, 236 const gfx::Vector2d& image_offset, 237 const DragEventSourceInfo& event_info) { 238 WebContentsImpl* embedder_web_contents = guest_->embedder_web_contents(); 239 embedder_web_contents->GetBrowserPluginEmbedder()->StartDrag(guest_); 240 RenderViewHostImpl* embedder_render_view_host = 241 static_cast<RenderViewHostImpl*>( 242 embedder_web_contents->GetRenderViewHost()); 243 CHECK(embedder_render_view_host); 244 RenderViewHostDelegateView* view = 245 embedder_render_view_host->GetDelegate()->GetDelegateView(); 246 if (view) { 247 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.StartDrag")); 248 view->StartDragging(drop_data, ops, image, image_offset, event_info); 249 } else { 250 embedder_web_contents->SystemDragEnded(); 251 } 252 } 253 254 } // namespace content 255