| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/web_contents/web_contents_view_guest.h" |
| |
| #include "build/build_config.h" |
| #include "content/browser/browser_plugin/browser_plugin_embedder.h" |
| #include "content/browser/browser_plugin/browser_plugin_guest.h" |
| #include "content/browser/frame_host/interstitial_page_impl.h" |
| #include "content/browser/renderer_host/render_view_host_factory.h" |
| #include "content/browser/renderer_host/render_view_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_view_guest.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/common/drag_messages.h" |
| #include "content/public/browser/web_contents_delegate.h" |
| #include "content/public/common/context_menu_params.h" |
| #include "content/public/common/drop_data.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/point.h" |
| #include "ui/gfx/rect.h" |
| #include "ui/gfx/size.h" |
| |
| #if defined(USE_AURA) |
| #include "ui/aura/window.h" |
| #endif |
| |
| using WebKit::WebDragOperation; |
| using WebKit::WebDragOperationsMask; |
| |
| namespace content { |
| |
| WebContentsViewGuest::WebContentsViewGuest( |
| WebContentsImpl* web_contents, |
| BrowserPluginGuest* guest, |
| scoped_ptr<WebContentsViewPort> platform_view, |
| RenderViewHostDelegateView* platform_view_delegate_view) |
| : web_contents_(web_contents), |
| guest_(guest), |
| platform_view_(platform_view.Pass()), |
| platform_view_delegate_view_(platform_view_delegate_view) { |
| } |
| |
| WebContentsViewGuest::~WebContentsViewGuest() { |
| } |
| |
| gfx::NativeView WebContentsViewGuest::GetNativeView() const { |
| return platform_view_->GetNativeView(); |
| } |
| |
| gfx::NativeView WebContentsViewGuest::GetContentNativeView() const { |
| RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); |
| if (!rwhv) |
| return NULL; |
| return rwhv->GetNativeView(); |
| } |
| |
| gfx::NativeWindow WebContentsViewGuest::GetTopLevelNativeWindow() const { |
| return guest_->embedder_web_contents()->GetView()->GetTopLevelNativeWindow(); |
| } |
| |
| void WebContentsViewGuest::OnGuestInitialized(WebContentsView* parent_view) { |
| #if defined(USE_AURA) || defined(OS_WIN) |
| // In aura and windows, ScreenPositionClient doesn't work properly if we do |
| // not have the native view associated with this WebContentsViewGuest in the |
| // view hierarchy. We add this view as embedder's child here. |
| // This would go in WebContentsViewGuest::CreateView, but that is too early to |
| // access embedder_web_contents(). Therefore, we do it here. |
| #if defined(USE_AURA) |
| // This can be win aura or chromeos. |
| parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView()); |
| #elif defined(OS_WIN) |
| SetParent(platform_view_->GetNativeView(), parent_view->GetNativeView()); |
| #endif |
| #endif // defined(USE_AURA) || defined(OS_WIN) |
| } |
| |
| void WebContentsViewGuest::GetContainerBounds(gfx::Rect* out) const { |
| // We need embedder container's bounds to calculate our bounds. |
| guest_->embedder_web_contents()->GetView()->GetContainerBounds(out); |
| gfx::Point guest_coordinates = guest_->GetScreenCoordinates(gfx::Point()); |
| out->Offset(guest_coordinates.x(), guest_coordinates.y()); |
| out->set_size(size_); |
| } |
| |
| void WebContentsViewGuest::SizeContents(const gfx::Size& size) { |
| size_ = size; |
| RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); |
| if (rwhv) |
| rwhv->SetSize(size); |
| } |
| |
| void WebContentsViewGuest::SetInitialFocus() { |
| platform_view_->SetInitialFocus(); |
| } |
| |
| gfx::Rect WebContentsViewGuest::GetViewBounds() const { |
| return gfx::Rect(size_); |
| } |
| |
| #if defined(OS_MACOSX) |
| void WebContentsViewGuest::SetAllowOverlappingViews(bool overlapping) { |
| platform_view_->SetAllowOverlappingViews(overlapping); |
| } |
| |
| bool WebContentsViewGuest::GetAllowOverlappingViews() const { |
| return platform_view_->GetAllowOverlappingViews(); |
| } |
| #endif |
| |
| void WebContentsViewGuest::CreateView(const gfx::Size& initial_size, |
| gfx::NativeView context) { |
| platform_view_->CreateView(initial_size, context); |
| size_ = initial_size; |
| } |
| |
| RenderWidgetHostView* WebContentsViewGuest::CreateViewForWidget( |
| RenderWidgetHost* render_widget_host) { |
| if (render_widget_host->GetView()) { |
| // During testing, the view will already be set up in most cases to the |
| // test view, so we don't want to clobber it with a real one. To verify that |
| // this actually is happening (and somebody isn't accidentally creating the |
| // view twice), we check for the RVH Factory, which will be set when we're |
| // making special ones (which go along with the special views). |
| DCHECK(RenderViewHostFactory::has_factory()); |
| return render_widget_host->GetView(); |
| } |
| |
| RenderWidgetHostView* platform_widget = NULL; |
| platform_widget = platform_view_->CreateViewForWidget(render_widget_host); |
| |
| RenderWidgetHostView* view = new RenderWidgetHostViewGuest( |
| render_widget_host, |
| guest_, |
| platform_widget); |
| |
| return view; |
| } |
| |
| RenderWidgetHostView* WebContentsViewGuest::CreateViewForPopupWidget( |
| RenderWidgetHost* render_widget_host) { |
| return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); |
| } |
| |
| void WebContentsViewGuest::SetPageTitle(const string16& title) { |
| } |
| |
| void WebContentsViewGuest::RenderViewCreated(RenderViewHost* host) { |
| platform_view_->RenderViewCreated(host); |
| } |
| |
| void WebContentsViewGuest::RenderViewSwappedIn(RenderViewHost* host) { |
| platform_view_->RenderViewSwappedIn(host); |
| } |
| |
| void WebContentsViewGuest::SetOverscrollControllerEnabled(bool enabled) { |
| // This should never override the setting of the embedder view. |
| } |
| |
| #if defined(OS_MACOSX) |
| bool WebContentsViewGuest::IsEventTracking() const { |
| return false; |
| } |
| |
| void WebContentsViewGuest::CloseTabAfterEventTracking() { |
| } |
| #endif |
| |
| WebContents* WebContentsViewGuest::web_contents() { |
| return web_contents_; |
| } |
| |
| void WebContentsViewGuest::RestoreFocus() { |
| platform_view_->RestoreFocus(); |
| } |
| |
| void WebContentsViewGuest::OnTabCrashed(base::TerminationStatus status, |
| int error_code) { |
| } |
| |
| void WebContentsViewGuest::Focus() { |
| platform_view_->Focus(); |
| } |
| |
| void WebContentsViewGuest::StoreFocus() { |
| platform_view_->StoreFocus(); |
| } |
| |
| DropData* WebContentsViewGuest::GetDropData() const { |
| NOTIMPLEMENTED(); |
| return NULL; |
| } |
| |
| void WebContentsViewGuest::UpdateDragCursor(WebDragOperation operation) { |
| RenderViewHostImpl* embedder_render_view_host = |
| static_cast<RenderViewHostImpl*>( |
| guest_->embedder_web_contents()->GetRenderViewHost()); |
| CHECK(embedder_render_view_host); |
| RenderViewHostDelegateView* view = |
| embedder_render_view_host->GetDelegate()->GetDelegateView(); |
| if (view) |
| view->UpdateDragCursor(operation); |
| } |
| |
| void WebContentsViewGuest::GotFocus() { |
| } |
| |
| void WebContentsViewGuest::TakeFocus(bool reverse) { |
| } |
| |
| void WebContentsViewGuest::ShowContextMenu(const ContextMenuParams& params) { |
| #if defined(USE_AURA) || defined(OS_WIN) |
| // Context menu uses ScreenPositionClient::ConvertPointToScreen() in aura and |
| // windows to calculate popup position. Guest's native view |
| // (platform_view_->GetNativeView()) is part of the embedder's view hierarchy, |
| // but is placed at (0, 0) w.r.t. the embedder's position. Therefore, |offset| |
| // is added to |params|. |
| gfx::Rect embedder_bounds; |
| guest_->embedder_web_contents()->GetView()->GetContainerBounds( |
| &embedder_bounds); |
| gfx::Rect guest_bounds; |
| GetContainerBounds(&guest_bounds); |
| |
| gfx::Vector2d offset = guest_bounds.origin() - embedder_bounds.origin(); |
| ContextMenuParams params_in_embedder = params; |
| params_in_embedder.x += offset.x(); |
| params_in_embedder.y += offset.y(); |
| platform_view_delegate_view_->ShowContextMenu(params_in_embedder); |
| #else |
| platform_view_delegate_view_->ShowContextMenu(params); |
| #endif // defined(USE_AURA) || defined(OS_WIN) |
| } |
| |
| void WebContentsViewGuest::ShowPopupMenu(const gfx::Rect& bounds, |
| int item_height, |
| double item_font_size, |
| int selected_item, |
| const std::vector<MenuItem>& items, |
| bool right_aligned, |
| bool allow_multiple_selection) { |
| // External popup menus are only used on Mac and Android. |
| NOTIMPLEMENTED(); |
| } |
| |
| void WebContentsViewGuest::StartDragging( |
| const DropData& drop_data, |
| WebDragOperationsMask ops, |
| const gfx::ImageSkia& image, |
| const gfx::Vector2d& image_offset, |
| const DragEventSourceInfo& event_info) { |
| WebContentsImpl* embedder_web_contents = guest_->embedder_web_contents(); |
| embedder_web_contents->GetBrowserPluginEmbedder()->StartDrag(guest_); |
| RenderViewHostImpl* embedder_render_view_host = |
| static_cast<RenderViewHostImpl*>( |
| embedder_web_contents->GetRenderViewHost()); |
| CHECK(embedder_render_view_host); |
| RenderViewHostDelegateView* view = |
| embedder_render_view_host->GetDelegate()->GetDelegateView(); |
| if (view) |
| view->StartDragging(drop_data, ops, image, image_offset, event_info); |
| else |
| embedder_web_contents->SystemDragEnded(); |
| } |
| |
| } // namespace content |