web_contents_view_aura.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_view_aura.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/auto_reset.h" 8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/command_line.h" 9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/histogram.h" 10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/utf_string_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/dip_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/overscroll_controller.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_view_host_factory.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_impl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_view_aura.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/aura/image_window_delegate.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/aura/shadow_layer_delegate.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/aura/window_slider.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/interstitial_page_impl.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/navigation_entry_impl.h" 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/touch_editable_impl_aura.h" 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/notification_types.h" 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/overscroll_configuration.h" 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_view_host.h" 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_widget_host.h" 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_widget_host_view.h" 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_delegate.h" 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h" 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_view_delegate.h" 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_drag_dest_delegate.h" 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/content_switches.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/drop_data.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/WebKit/public/web/WebInputEvent.h" 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/aura/client/aura_constants.h" 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/drag_drop_client.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/drag_drop_delegate.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window_observer.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_observer.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/clipboard.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/custom_data_helper.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_drop_types.h" 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/base/dragdrop/drag_utils.h" 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h" 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/hit_test.h" 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer.h" 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h" 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/events/event.h" 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/events/event_utils.h" 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_png_rep.h" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/screen.h" 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContentsViewPort* CreateWebContentsView( 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContentsImpl* web_contents, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContentsViewDelegate* delegate, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostDelegateView** render_view_host_delegate_view) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *render_view_host_delegate_view = rv; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool IsScrollEndEffectEnabled() { 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kScrollEndEffect) == "1"; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldNavigateForward(const NavigationController& controller, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OverscrollMode mode) { 82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) && 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller.CanGoForward(); 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 85a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ShouldNavigateBack(const NavigationController& controller, 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OverscrollMode mode) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) && 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) controller.CanGoBack(); 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RenderWidgetHostViewAura* ToRenderWidgetHostViewAura( 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenderWidgetHostView* view) { 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!view || RenderViewHostFactory::has_factory()) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests. 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>( 976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) view->GetRenderWidgetHost()->GetProcess()); 980de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (process->IsGuest()) 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return static_cast<RenderWidgetHostViewAura*>(view); 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The window delegate for the overscroll window. This redirects trackpad events 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// to the web-contents window. The delegate destroys itself when the window is 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// destroyed. 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class OverscrollWindowDelegate : public ImageWindowDelegate { 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OverscrollWindowDelegate(WebContentsImpl* web_contents, 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OverscrollMode overscroll_mode) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : web_contents_(web_contents), 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) forward_events_(true) { 112ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch const NavigationControllerImpl& controller = web_contents->GetController(); 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const NavigationEntryImpl* entry = NULL; 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ShouldNavigateForward(controller, overscroll_mode)) { 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) entry = NavigationEntryImpl::FromNavigationEntry( 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch controller.GetEntryAtOffset(1)); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ShouldNavigateBack(controller, overscroll_mode)) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry = NavigationEntryImpl::FromNavigationEntry( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller.GetEntryAtOffset(-1)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Image image; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry && entry->screenshot().get()) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::ImagePNGRep> image_reps; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetScaleFactorForNativeView(web_contents_window()))); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image = gfx::Image(image_reps); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetImage(image); 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void stop_forwarding_events() { forward_events_ = false; } 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual ~OverscrollWindowDelegate() {} 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aura::Window* web_contents_window() { 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return web_contents_->GetView()->GetContentNativeView(); 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Overridden from ui::EventHandler. 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE { 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (forward_events_ && web_contents_window()) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) web_contents_window()->delegate()->OnScrollEvent(event); 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (forward_events_ && web_contents_window()) 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch web_contents_window()->delegate()->OnGestureEvent(event); 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebContents* web_contents_; 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // The window is displayed both during the gesture, and after the gesture 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // while the navigation is in progress. During the gesture, it is necessary to 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // forward input events to the content page (e.g. when the overscroll window 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // slides under the cursor and starts receiving scroll events). However, once 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // the gesture is complete, and the window is being displayed as an overlay 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // window during navigation, events should not be forwarded anymore. 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool forward_events_; 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate); 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Listens to all mouse drag events during a drag and drop and sends them to 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the renderer. 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass WebDragSourceAura : public base::MessageLoopForUI::Observer, 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public NotificationObserver { 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebDragSourceAura(aura::Window* window, WebContentsImpl* contents) 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : window_(window), 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch contents_(contents) { 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoopForUI::current()->AddObserver(this); 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Source<WebContents>(contents)); 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~WebDragSourceAura() { 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoopForUI::current()->RemoveObserver(this); 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // MessageLoop::Observer implementation: 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual base::EventStatus WillProcessEvent( 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::NativeEvent& event) OVERRIDE { 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return base::EVENT_CONTINUE; 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!contents_) 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui::EventType type = ui::EventTypeFromNative(event); 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RenderViewHost* rvh = NULL; 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (type) { 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case ui::ET_MOUSE_DRAGGED: 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rvh = contents_->GetRenderViewHost(); 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (rvh) { 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event); 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Point screen_loc = ConvertViewPointToDIP(rvh->GetView(), 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch screen_loc_in_pixel); 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Point client_loc = screen_loc; 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window = rvh->GetView()->GetNativeView(); 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch aura::Window::ConvertPointToTarget(window->GetRootWindow(), 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch window, &client_loc); 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) contents_->DragSourceMovedTo(client_loc.x(), client_loc.y(), 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch screen_loc.x(), screen_loc.y()); 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 213a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch virtual void Observe(int type, 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const NotificationSource& source, 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const NotificationDetails& details) OVERRIDE { 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED) 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Cancel the drag if it is still in progress. 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) aura::client::DragDropClient* dnd_client = 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::GetDragDropClient(window_->GetRootWindow()); 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (dnd_client && dnd_client->IsDragDropInProgress()) 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dnd_client->DragCancel(); 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) window_ = NULL; 2260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) contents_ = NULL; 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aura::Window* window() const { return window_; } 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aura::Window* window_; 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* contents_; 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NotificationRegistrar registrar_; 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura); 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN) 240ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch// Fill out the OSExchangeData with a file contents, synthesizing a name if 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// necessary. 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PrepareDragForFileContents(const DropData& drop_data, 243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui::OSExchangeData::Provider* provider) { 244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::FilePath file_name(drop_data.file_description_filename); 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Images without ALT text will only have a file extension so we need to 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // synthesize one from the provided extension and URL. 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (file_name.BaseName().RemoveExtension().empty()) { 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const string16 extension = file_name.Extension(); 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Retrieve the name from the URL. 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch file_name = base::FilePath(net::GetSuggestedFilename( 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch drop_data.url, "", "", "", "", "")).ReplaceExtension(extension); 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch provider->SetFileContents(file_name, drop_data.file_contents); 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Utility to fill a ui::OSExchangeDataProvider object from DropData. 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PrepareDragData(const DropData& drop_data, 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui::OSExchangeData::Provider* provider) { 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN) 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We set the file contents before the URL because the URL also sets file 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // contents (to a .URL shortcut). We want to prefer file content data over 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // a shortcut so we add it first. 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!drop_data.file_contents.empty()) 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PrepareDragForFileContents(drop_data, provider); 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!drop_data.text.string().empty()) 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) provider->SetString(drop_data.text.string()); 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (drop_data.url.is_valid()) 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) provider->SetURL(drop_data.url, drop_data.url_title); 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!drop_data.html.string().empty()) 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) provider->SetHtml(drop_data.html.string(), drop_data.html_base_url); 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!drop_data.filenames.empty()) { 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<ui::OSExchangeData::FileInfo> filenames; 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (std::vector<DropData::FileInfo>::const_iterator it = 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_data.filenames.begin(); 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it != drop_data.filenames.end(); ++it) { 27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filenames.push_back( 27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ui::OSExchangeData::FileInfo( 28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)), 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->display_name)))); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->SetFilenames(filenames); 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!drop_data.custom_data.empty()) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pickle pickle; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pickle); 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Utility to fill a DropData object from ui::OSExchangeData. 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 plain_text; 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.GetString(&plain_text); 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!plain_text.empty()) 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch drop_data->text = base::NullableString16(plain_text, false); 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GURL url; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 url_title; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.GetURLAndTitle(&url, &url_title); 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (url.is_valid()) { 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_data->url = url; 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_data->url_title = url_title; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string16 html; 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GURL html_base_url; 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) data.GetHtml(&html, &html_base_url); 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!html.empty()) 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_data->html = base::NullableString16(html, false); 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (html_base_url.is_valid()) 314c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch drop_data->html_base_url = html_base_url; 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 316 std::vector<ui::OSExchangeData::FileInfo> files; 317 if (data.GetFilenames(&files) && !files.empty()) { 318 for (std::vector<ui::OSExchangeData::FileInfo>::const_iterator 319 it = files.begin(); it != files.end(); ++it) { 320 drop_data->filenames.push_back( 321 DropData::FileInfo( 322 UTF8ToUTF16(it->path.AsUTF8Unsafe()), 323 UTF8ToUTF16(it->display_name.AsUTF8Unsafe()))); 324 } 325 } 326 327 Pickle pickle; 328 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle)) 329 ui::ReadCustomDataIntoMap( 330 pickle.data(), pickle.size(), &drop_data->custom_data); 331} 332 333// Utilities to convert between WebKit::WebDragOperationsMask and 334// ui::DragDropTypes. 335int ConvertFromWeb(WebKit::WebDragOperationsMask ops) { 336 int drag_op = ui::DragDropTypes::DRAG_NONE; 337 if (ops & WebKit::WebDragOperationCopy) 338 drag_op |= ui::DragDropTypes::DRAG_COPY; 339 if (ops & WebKit::WebDragOperationMove) 340 drag_op |= ui::DragDropTypes::DRAG_MOVE; 341 if (ops & WebKit::WebDragOperationLink) 342 drag_op |= ui::DragDropTypes::DRAG_LINK; 343 return drag_op; 344} 345 346WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) { 347 int web_drag_op = WebKit::WebDragOperationNone; 348 if (drag_op & ui::DragDropTypes::DRAG_COPY) 349 web_drag_op |= WebKit::WebDragOperationCopy; 350 if (drag_op & ui::DragDropTypes::DRAG_MOVE) 351 web_drag_op |= WebKit::WebDragOperationMove; 352 if (drag_op & ui::DragDropTypes::DRAG_LINK) 353 web_drag_op |= WebKit::WebDragOperationLink; 354 return (WebKit::WebDragOperationsMask) web_drag_op; 355} 356 357int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) { 358 int web_input_event_modifiers = 0; 359 if (aura_event_flags & ui::EF_SHIFT_DOWN) 360 web_input_event_modifiers |= WebKit::WebInputEvent::ShiftKey; 361 if (aura_event_flags & ui::EF_CONTROL_DOWN) 362 web_input_event_modifiers |= WebKit::WebInputEvent::ControlKey; 363 if (aura_event_flags & ui::EF_ALT_DOWN) 364 web_input_event_modifiers |= WebKit::WebInputEvent::AltKey; 365 if (aura_event_flags & ui::EF_COMMAND_DOWN) 366 web_input_event_modifiers |= WebKit::WebInputEvent::MetaKey; 367 return web_input_event_modifiers; 368} 369 370// A LayerDelegate that paints an image for the layer. 371class ImageLayerDelegate : public ui::LayerDelegate { 372 public: 373 ImageLayerDelegate() {} 374 375 virtual ~ImageLayerDelegate() {} 376 377 void SetImage(const gfx::Image& image) { 378 image_ = image; 379 image_size_ = image.AsImageSkia().size(); 380 } 381 const gfx::Image& image() const { return image_; } 382 383 private: 384 // Overridden from ui::LayerDelegate: 385 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { 386 if (image_.IsEmpty()) { 387 canvas->DrawColor(SK_ColorGRAY); 388 } else { 389 SkISize size = canvas->sk_canvas()->getDeviceSize(); 390 if (size.width() != image_size_.width() || 391 size.height() != image_size_.height()) { 392 canvas->DrawColor(SK_ColorWHITE); 393 } 394 canvas->DrawImageInt(image_.AsImageSkia(), 0, 0); 395 } 396 } 397 398 // Called when the layer's device scale factor has changed. 399 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { 400 } 401 402 // Invoked prior to the bounds changing. The returned closured is run after 403 // the bounds change. 404 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { 405 return base::Closure(); 406 } 407 408 gfx::Image image_; 409 gfx::Size image_size_; 410 411 DISALLOW_COPY_AND_ASSIGN(ImageLayerDelegate); 412}; 413 414} // namespace 415 416// When a history navigation is triggered at the end of an overscroll 417// navigation, it is necessary to show the history-screenshot until the page is 418// done navigating and painting. This class accomplishes this by showing the 419// screenshot window on top of the page until the page has completed loading and 420// painting. 421class OverscrollNavigationOverlay : 422 public RenderWidgetHostViewAura::PaintObserver, 423 public WindowSlider::Delegate { 424 public: 425 explicit OverscrollNavigationOverlay(WebContentsImpl* web_contents) 426 : web_contents_(web_contents), 427 image_delegate_(NULL), 428 view_(NULL), 429 loading_complete_(false), 430 received_paint_update_(false), 431 compositor_updated_(false), 432 slide_direction_(SLIDE_UNKNOWN), 433 need_paint_update_(true) { 434 } 435 436 virtual ~OverscrollNavigationOverlay() { 437 if (view_) 438 view_->set_paint_observer(NULL); 439 } 440 441 bool has_window() const { return !!window_.get(); } 442 443 void StartObservingView(RenderWidgetHostViewAura* view) { 444 if (view_) 445 view_->set_paint_observer(NULL); 446 447 loading_complete_ = false; 448 received_paint_update_ = false; 449 compositor_updated_ = false; 450 view_ = view; 451 if (view_) 452 view_->set_paint_observer(this); 453 454 // Make sure the overlay window is on top. 455 if (window_.get() && window_->parent()) 456 window_->parent()->StackChildAtTop(window_.get()); 457 } 458 459 void SetOverlayWindow(scoped_ptr<aura::Window> window, 460 ImageWindowDelegate* delegate) { 461 window_ = window.Pass(); 462 if (window_.get() && window_->parent()) 463 window_->parent()->StackChildAtTop(window_.get()); 464 image_delegate_ = delegate; 465 466 if (window_.get() && delegate->has_image()) { 467 window_slider_.reset(new WindowSlider(this, 468 window_->parent(), 469 window_.get())); 470 slide_direction_ = SLIDE_UNKNOWN; 471 } else { 472 window_slider_.reset(); 473 } 474 } 475 476 void SetupForTesting() { 477 need_paint_update_ = false; 478 } 479 480 private: 481 // Stop observing the page if the page-load has completed and the page has 482 // been painted, and a window-slide isn't in progress. 483 void StopObservingIfDone() { 484 // If there is a screenshot displayed in the overlay window, then wait for 485 // the navigated page to complete loading and some paint update before 486 // hiding the overlay. 487 // If there is no screenshot in the overlay window, then hide this view 488 // as soon as there is any new painting notification. 489 if ((need_paint_update_ && !received_paint_update_) || 490 (image_delegate_->has_image() && !loading_complete_)) { 491 return; 492 } 493 494 // If a slide is in progress, then do not destroy the window or the slide. 495 if (window_slider_.get() && window_slider_->IsSlideInProgress()) 496 return; 497 498 window_slider_.reset(); 499 window_.reset(); 500 image_delegate_ = NULL; 501 if (view_) { 502 view_->set_paint_observer(NULL); 503 view_ = NULL; 504 } 505 } 506 507 // Creates a layer to be used for window-slide. |offset| is the offset of the 508 // NavigationEntry for the screenshot image to display. 509 ui::Layer* CreateSlideLayer(int offset) { 510 const NavigationControllerImpl& controller = web_contents_->GetController(); 511 const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 512 controller.GetEntryAtOffset(offset)); 513 514 gfx::Image image; 515 if (entry && entry->screenshot().get()) { 516 std::vector<gfx::ImagePNGRep> image_reps; 517 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 518 ui::GetScaleFactorForNativeView(window_.get()))); 519 image = gfx::Image(image_reps); 520 } 521 layer_delegate_.SetImage(image); 522 523 ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED); 524 layer->set_delegate(&layer_delegate_); 525 return layer; 526 } 527 528 // Overridden from WindowSlider::Delegate: 529 virtual ui::Layer* CreateBackLayer() OVERRIDE { 530 if (!web_contents_->GetController().CanGoBack()) 531 return NULL; 532 slide_direction_ = SLIDE_BACK; 533 return CreateSlideLayer(-1); 534 } 535 536 virtual ui::Layer* CreateFrontLayer() OVERRIDE { 537 if (!web_contents_->GetController().CanGoForward()) 538 return NULL; 539 slide_direction_ = SLIDE_FRONT; 540 return CreateSlideLayer(1); 541 } 542 543 virtual void OnWindowSlideComplete() OVERRIDE { 544 if (slide_direction_ == SLIDE_UNKNOWN) { 545 window_slider_.reset(); 546 StopObservingIfDone(); 547 return; 548 } 549 550 // Change the image used for the overlay window. 551 image_delegate_->SetImage(layer_delegate_.image()); 552 window_->layer()->SetTransform(gfx::Transform()); 553 window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size())); 554 555 SlideDirection direction = slide_direction_; 556 slide_direction_ = SLIDE_UNKNOWN; 557 558 // Reset state and wait for the new navigation page to complete 559 // loading/painting. 560 StartObservingView(ToRenderWidgetHostViewAura( 561 web_contents_->GetRenderWidgetHostView())); 562 563 // Perform the navigation. 564 if (direction == SLIDE_BACK) 565 web_contents_->GetController().GoBack(); 566 else if (direction == SLIDE_FRONT) 567 web_contents_->GetController().GoForward(); 568 else 569 NOTREACHED(); 570 } 571 572 virtual void OnWindowSlideAborted() OVERRIDE { 573 StopObservingIfDone(); 574 } 575 576 virtual void OnWindowSliderDestroyed() OVERRIDE { 577 // The slider has just been destroyed. Release the ownership. 578 WindowSlider* slider ALLOW_UNUSED = window_slider_.release(); 579 StopObservingIfDone(); 580 } 581 582 // Overridden from RenderWidgetHostViewAura::PaintObserver: 583 virtual void OnPaintComplete() OVERRIDE { 584 received_paint_update_ = true; 585 StopObservingIfDone(); 586 } 587 588 virtual void OnCompositingComplete() OVERRIDE { 589 received_paint_update_ = compositor_updated_; 590 StopObservingIfDone(); 591 } 592 593 virtual void OnUpdateCompositorContent() OVERRIDE { 594 compositor_updated_ = true; 595 } 596 597 virtual void OnPageLoadComplete() OVERRIDE { 598 loading_complete_ = true; 599 StopObservingIfDone(); 600 } 601 602 virtual void OnViewDestroyed() OVERRIDE { 603 DCHECK(view_); 604 view_->set_paint_observer(NULL); 605 view_ = NULL; 606 } 607 608 // The WebContents which is being navigated. 609 WebContentsImpl* web_contents_; 610 611 scoped_ptr<aura::Window> window_; 612 613 // This is the WindowDelegate of |window_|. The delegate manages its own 614 // lifetime (destroys itself when |window_| is destroyed). 615 ImageWindowDelegate* image_delegate_; 616 617 RenderWidgetHostViewAura* view_; 618 bool loading_complete_; 619 bool received_paint_update_; 620 bool compositor_updated_; 621 622 enum SlideDirection { 623 SLIDE_UNKNOWN, 624 SLIDE_BACK, 625 SLIDE_FRONT 626 }; 627 628 // The |WindowSlider| that allows sliding history layers while the page is 629 // being reloaded. 630 scoped_ptr<WindowSlider> window_slider_; 631 632 // The direction of the in-progress slide (if any). 633 SlideDirection slide_direction_; 634 635 // The LayerDelegate used for the back/front layers during a slide. 636 ImageLayerDelegate layer_delegate_; 637 638 // During tests, the aura windows don't get any paint updates. So the overlay 639 // container keeps waiting for a paint update it never receives, causing a 640 // timeout. So during tests, disable the wait for paint updates. 641 bool need_paint_update_; 642 643 DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay); 644}; 645 646class WebContentsViewAura::WindowObserver 647 : public aura::WindowObserver, public aura::RootWindowObserver { 648 public: 649 explicit WindowObserver(WebContentsViewAura* view) 650 : view_(view), 651 parent_(NULL) { 652 view_->window_->AddObserver(this); 653 } 654 655 virtual ~WindowObserver() { 656 view_->window_->RemoveObserver(this); 657 if (view_->window_->GetRootWindow()) 658 view_->window_->GetRootWindow()->RemoveRootWindowObserver(this); 659 if (parent_) 660 parent_->RemoveObserver(this); 661 } 662 663 // Overridden from aura::WindowObserver: 664 virtual void OnWindowParentChanged(aura::Window* window, 665 aura::Window* parent) OVERRIDE { 666 if (window == parent_) 667 return; 668 if (parent_) 669 parent_->RemoveObserver(this); 670 parent_ = parent; 671 if (parent) 672 parent->AddObserver(this); 673 } 674 675 virtual void OnWindowBoundsChanged(aura::Window* window, 676 const gfx::Rect& old_bounds, 677 const gfx::Rect& new_bounds) OVERRIDE { 678 SendScreenRects(); 679 if (view_->touch_editable_) 680 view_->touch_editable_->UpdateEditingController(); 681 } 682 683 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE { 684 if (window != parent_) 685 window->GetRootWindow()->AddRootWindowObserver(this); 686 } 687 688 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE { 689 if (window != parent_) 690 window->GetRootWindow()->RemoveRootWindowObserver(this); 691 } 692 693 // Overridden RootWindowObserver: 694 virtual void OnRootWindowHostMoved(const aura::RootWindow* root, 695 const gfx::Point& new_origin) OVERRIDE { 696 // This is for the desktop case (i.e. Aura desktop). 697 SendScreenRects(); 698 } 699 700 private: 701 void SendScreenRects() { 702 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())-> 703 SendScreenRects(); 704 } 705 706 WebContentsViewAura* view_; 707 708 // We cache the old parent so that we can unregister when it's not the parent 709 // anymore. 710 aura::Window* parent_; 711 712 DISALLOW_COPY_AND_ASSIGN(WindowObserver); 713}; 714 715#if defined(OS_WIN) 716// Constrained windows are added as children of the WebContent's view which may 717// overlap with windowed NPAPI plugins. In that case, tell the RWHV so that it 718// can update the plugins' cutout rects accordingly. 719class WebContentsViewAura::ChildWindowObserver : public aura::WindowObserver, 720 public WebContentsObserver { 721 public: 722 explicit ChildWindowObserver(WebContentsViewAura* view) 723 : WebContentsObserver(view->web_contents_), 724 view_(view), 725 web_contents_destroyed_(false) { 726 view_->window_->AddObserver(this); 727 } 728 729 virtual ~ChildWindowObserver() { 730 view_->window_->RemoveObserver(this); 731 const aura::Window::Windows& children = view_->window_->children(); 732 for (size_t i = 0; i < children.size(); ++i) 733 children[i]->RemoveObserver(this); 734 } 735 736 // Overridden from aura::WindowObserver: 737 virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE { 738 // If new child windows are added to the WebContent's view, tell the RWHV. 739 // We also start watching them to know when their size is updated. Of 740 // course, ignore the shadow window that contains the RWHV and child windows 741 // of the child windows that we are watching. 742 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( 743 view_->web_contents_->GetRenderWidgetHostView()); 744 aura::Window* content_window = view ? view->GetNativeView() : NULL; 745 if (new_window->parent() == view_->window_ && 746 new_window != content_window) { 747 new_window->AddObserver(this); 748 UpdateConstrainedWindows(NULL); 749 } 750 } 751 752 virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE { 753 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( 754 view_->web_contents_->GetRenderWidgetHostView()); 755 aura::Window* content_window = view ? view->GetNativeView() : NULL; 756 if (window->parent() == view_->window_ && 757 window != content_window) { 758 window->RemoveObserver(this); 759 UpdateConstrainedWindows(window); 760 } 761 } 762 763 virtual void OnWindowBoundsChanged(aura::Window* window, 764 const gfx::Rect& old_bounds, 765 const gfx::Rect& new_bounds) OVERRIDE { 766 if (window->parent() == view_->window_ && 767 window != view_->GetContentNativeView()) { 768 UpdateConstrainedWindows(NULL); 769 } 770 } 771 772 // Overridden from WebContentsObserver: 773 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { 774 web_contents_destroyed_ = true; 775 } 776 777 private: 778 void UpdateConstrainedWindows(aura::Window* exclude) { 779 if (web_contents_destroyed_) 780 return; 781 782 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( 783 view_->web_contents_->GetRenderWidgetHostView()); 784 if (!view) 785 return; 786 787 std::vector<gfx::Rect> constrained_windows; 788 const aura::Window::Windows& children = view_->window_->children(); 789 aura::Window* content = view_->GetContentNativeView(); 790 for (size_t i = 0; i < children.size(); ++i) { 791 if (children[i] != content && children[i] != exclude) 792 constrained_windows.push_back(children[i]->GetBoundsInRootWindow()); 793 } 794 795 view->UpdateConstrainedWindowRects(constrained_windows); 796 } 797 798 WebContentsViewAura* view_; 799 bool web_contents_destroyed_; 800 801 DISALLOW_COPY_AND_ASSIGN(ChildWindowObserver); 802}; 803#endif 804 805//////////////////////////////////////////////////////////////////////////////// 806// WebContentsViewAura, public: 807 808WebContentsViewAura::WebContentsViewAura( 809 WebContentsImpl* web_contents, 810 WebContentsViewDelegate* delegate) 811 : web_contents_(web_contents), 812 delegate_(delegate), 813 current_drag_op_(WebKit::WebDragOperationNone), 814 drag_dest_delegate_(NULL), 815 current_rvh_for_drag_(NULL), 816 overscroll_change_brightness_(false), 817 current_overscroll_gesture_(OVERSCROLL_NONE), 818 completed_overscroll_gesture_(OVERSCROLL_NONE), 819 touch_editable_(TouchEditableImplAura::Create()) { 820} 821 822//////////////////////////////////////////////////////////////////////////////// 823// WebContentsViewAura, private: 824 825WebContentsViewAura::~WebContentsViewAura() { 826 if (!window_) 827 return; 828 829 window_observer_.reset(); 830#if defined(OS_WIN) 831 child_window_observer_.reset(); 832#endif 833 // Window needs a valid delegate during its destructor, so we explicitly 834 // delete it here. 835 window_.reset(); 836} 837 838void WebContentsViewAura::SetupOverlayWindowForTesting() { 839 if (navigation_overlay_) 840 navigation_overlay_->SetupForTesting(); 841} 842 843void WebContentsViewAura::SetTouchEditableForTest( 844 TouchEditableImplAura* touch_editable) { 845 touch_editable_.reset(touch_editable); 846 AttachTouchEditableToRenderView(); 847} 848 849void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) { 850 if (web_contents_->GetInterstitialPage()) 851 web_contents_->GetInterstitialPage()->SetSize(size); 852 RenderWidgetHostView* rwhv = 853 web_contents_->GetRenderWidgetHostView(); 854 if (rwhv) 855 rwhv->SetSize(size); 856} 857 858void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) { 859 aura::RootWindow* root_window = GetNativeView()->GetRootWindow(); 860 gfx::Point screen_loc = 861 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 862 gfx::Point client_loc = screen_loc; 863 RenderViewHost* rvh = web_contents_->GetRenderViewHost(); 864 aura::Window* window = rvh->GetView()->GetNativeView(); 865 aura::Window::ConvertPointToTarget(root_window, window, &client_loc); 866 if (!web_contents_) 867 return; 868 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(), 869 screen_loc.x(), screen_loc.y(), ops); 870} 871 872void WebContentsViewAura::PrepareOverscrollWindow() { 873 // If there is an existing |overscroll_window_| which is in the middle of an 874 // animation, then destroying the window here causes the animation to be 875 // completed immidiately, which triggers |OnImplicitAnimationsCompleted()| 876 // callback, and that tries to reset |overscroll_window_| again, causing a 877 // double-free. So use a temporary variable here. 878 if (overscroll_window_) { 879 base::AutoReset<OverscrollMode> reset_state(¤t_overscroll_gesture_, 880 current_overscroll_gesture_); 881 scoped_ptr<aura::Window> reset_window(overscroll_window_.release()); 882 } 883 884 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate( 885 web_contents_, 886 current_overscroll_gesture_); 887 overscroll_window_.reset(new aura::Window(overscroll_delegate)); 888 overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL); 889 overscroll_window_->SetTransparent(true); 890 overscroll_window_->Init(ui::LAYER_TEXTURED); 891 overscroll_window_->layer()->SetMasksToBounds(false); 892 overscroll_window_->SetName("OverscrollOverlay"); 893 894 overscroll_change_brightness_ = overscroll_delegate->has_image(); 895 window_->AddChild(overscroll_window_.get()); 896 897 gfx::Rect bounds = gfx::Rect(window_->bounds().size()); 898 if (ShouldNavigateForward(web_contents_->GetController(), 899 current_overscroll_gesture_)) { 900 // The overlay will be sliding in from the right edge towards the left in 901 // non-RTL, or sliding in from the left edge towards the right in RTL. 902 // So position the overlay window accordingly. 903 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0); 904 } 905 906 aura::Window* animate_window = GetWindowToAnimateForOverscroll(); 907 if (animate_window == overscroll_window_) 908 window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView()); 909 else 910 window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView()); 911 912 UpdateOverscrollWindowBrightness(0.f); 913 914 overscroll_window_->SetBounds(bounds); 915 overscroll_window_->Show(); 916 917 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer())); 918} 919 920void WebContentsViewAura::PrepareContentWindowForOverscroll() { 921 StopObservingImplicitAnimations(); 922 aura::Window* content = GetContentNativeView(); 923 content->layer()->GetAnimator()->AbortAllAnimations(); 924 content->SetTransform(gfx::Transform()); 925 content->layer()->SetLayerBrightness(0.f); 926} 927 928void WebContentsViewAura::ResetOverscrollTransform() { 929 if (!web_contents_->GetRenderWidgetHostView()) 930 return; 931 aura::Window* target = GetWindowToAnimateForOverscroll(); 932 if (!target) 933 return; 934 { 935 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 936 settings.SetPreemptionStrategy( 937 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 938 settings.SetTweenType(gfx::Tween::EASE_OUT); 939 settings.AddObserver(this); 940 target->SetTransform(gfx::Transform()); 941 } 942 { 943 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 944 settings.SetPreemptionStrategy( 945 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 946 settings.SetTweenType(gfx::Tween::EASE_OUT); 947 UpdateOverscrollWindowBrightness(0.f); 948 } 949} 950 951void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) { 952 if (!web_contents_->GetRenderWidgetHostView()) 953 return; 954 955 // Animate out the current view first. Navigate to the requested history at 956 // the end of the animation. 957 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 958 return; 959 960 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated", 961 current_overscroll_gesture_, OVERSCROLL_COUNT); 962 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>( 963 overscroll_window_->delegate()); 964 delegate->stop_forwarding_events(); 965 966 completed_overscroll_gesture_ = mode; 967 aura::Window* target = GetWindowToAnimateForOverscroll(); 968 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 969 settings.SetPreemptionStrategy( 970 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 971 settings.SetTweenType(gfx::Tween::EASE_OUT); 972 settings.AddObserver(this); 973 gfx::Transform transform; 974 int content_width = 975 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width(); 976 int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width; 977 transform.Translate(translate_x, 0); 978 target->SetTransform(transform); 979 UpdateOverscrollWindowBrightness(translate_x); 980} 981 982aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() { 983 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 984 return NULL; 985 986 return ShouldNavigateForward(web_contents_->GetController(), 987 current_overscroll_gesture_) ? 988 overscroll_window_.get() : GetContentNativeView(); 989} 990 991gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x, 992 int delta_y) { 993 if (current_overscroll_gesture_ == OVERSCROLL_NORTH || 994 current_overscroll_gesture_ == OVERSCROLL_SOUTH) { 995 return gfx::Vector2d(0, delta_y); 996 } 997 // For horizontal overscroll, scroll freely if a navigation is possible. Do a 998 // resistive scroll otherwise. 999 const NavigationControllerImpl& controller = web_contents_->GetController(); 1000 const gfx::Rect& bounds = GetViewBounds(); 1001 if (ShouldNavigateForward(controller, current_overscroll_gesture_)) 1002 return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0); 1003 else if (ShouldNavigateBack(controller, current_overscroll_gesture_)) 1004 return gfx::Vector2d(std::min(bounds.width(), delta_x), 0); 1005 return gfx::Vector2d(); 1006} 1007 1008void WebContentsViewAura::PrepareOverscrollNavigationOverlay() { 1009 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>( 1010 overscroll_window_->delegate()); 1011 overscroll_window_->SchedulePaintInRect( 1012 gfx::Rect(overscroll_window_->bounds().size())); 1013 overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size())); 1014 overscroll_window_->SetTransform(gfx::Transform()); 1015 navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(), 1016 delegate); 1017 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura( 1018 web_contents_->GetRenderWidgetHostView())); 1019} 1020 1021void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) { 1022 if (!overscroll_change_brightness_) 1023 return; 1024 1025 const float kBrightnessMin = -.1f; 1026 const float kBrightnessMax = -.01f; 1027 1028 float ratio = fabs(delta_x) / GetViewBounds().width(); 1029 ratio = std::min(1.f, ratio); 1030 if (base::i18n::IsRTL()) 1031 ratio = 1.f - ratio; 1032 float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ? 1033 kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) : 1034 kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin); 1035 brightness = std::max(kBrightnessMin, brightness); 1036 brightness = std::min(kBrightnessMax, brightness); 1037 aura::Window* window = GetWindowToAnimateForOverscroll(); 1038 window->layer()->SetLayerBrightness(brightness); 1039} 1040 1041void WebContentsViewAura::AttachTouchEditableToRenderView() { 1042 if (!touch_editable_) 1043 return; 1044 RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura( 1045 web_contents_->GetRenderWidgetHostView()); 1046 touch_editable_->AttachToView(rwhva); 1047} 1048 1049void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y) { 1050 if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled()) 1051 web_contents_->GetDelegate()->OverscrollUpdate(delta_y); 1052} 1053 1054//////////////////////////////////////////////////////////////////////////////// 1055// WebContentsViewAura, WebContentsView implementation: 1056 1057gfx::NativeView WebContentsViewAura::GetNativeView() const { 1058 return window_.get(); 1059} 1060 1061gfx::NativeView WebContentsViewAura::GetContentNativeView() const { 1062 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 1063 return rwhv ? rwhv->GetNativeView() : NULL; 1064} 1065 1066gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const { 1067 return window_->GetToplevelWindow(); 1068} 1069 1070void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const { 1071 *out = window_->GetBoundsInScreen(); 1072} 1073 1074void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status, 1075 int error_code) { 1076 // Set the focus to the parent because neither the view window nor this 1077 // window can handle key events. 1078 if (window_->HasFocus() && window_->parent()) 1079 window_->parent()->Focus(); 1080} 1081 1082void WebContentsViewAura::SizeContents(const gfx::Size& size) { 1083 gfx::Rect bounds = window_->bounds(); 1084 if (bounds.size() != size) { 1085 bounds.set_size(size); 1086 window_->SetBounds(bounds); 1087 } else { 1088 // Our size matches what we want but the renderers size may not match. 1089 // Pretend we were resized so that the renderers size is updated too. 1090 SizeChangedCommon(size); 1091 } 1092} 1093 1094void WebContentsViewAura::Focus() { 1095 if (web_contents_->GetInterstitialPage()) { 1096 web_contents_->GetInterstitialPage()->Focus(); 1097 return; 1098 } 1099 1100 if (delegate_.get() && delegate_->Focus()) 1101 return; 1102 1103 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 1104 if (rwhv) 1105 rwhv->Focus(); 1106} 1107 1108void WebContentsViewAura::SetInitialFocus() { 1109 if (web_contents_->FocusLocationBarByDefault()) 1110 web_contents_->SetFocusToLocationBar(false); 1111 else 1112 Focus(); 1113} 1114 1115void WebContentsViewAura::StoreFocus() { 1116 if (delegate_) 1117 delegate_->StoreFocus(); 1118} 1119 1120void WebContentsViewAura::RestoreFocus() { 1121 if (delegate_) 1122 delegate_->RestoreFocus(); 1123} 1124 1125DropData* WebContentsViewAura::GetDropData() const { 1126 return current_drop_data_.get(); 1127} 1128 1129gfx::Rect WebContentsViewAura::GetViewBounds() const { 1130 return window_->GetBoundsInScreen(); 1131} 1132 1133//////////////////////////////////////////////////////////////////////////////// 1134// WebContentsViewAura, WebContentsViewPort implementation: 1135 1136void WebContentsViewAura::CreateView( 1137 const gfx::Size& initial_size, gfx::NativeView context) { 1138 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as 1139 // if the bookmark bar is not shown and you create a new tab). The right 1140 // value is set shortly after this, so its safe to ignore. 1141 1142 window_.reset(new aura::Window(this)); 1143 window_->set_owned_by_parent(false); 1144 window_->SetType(aura::client::WINDOW_TYPE_CONTROL); 1145 window_->SetTransparent(false); 1146 window_->Init(ui::LAYER_NOT_DRAWN); 1147 aura::RootWindow* root_window = context ? context->GetRootWindow() : NULL; 1148 if (root_window) { 1149 // There are places where there is no context currently because object 1150 // hierarchies are built before they're attached to a Widget. (See 1151 // views::WebView as an example; GetWidget() returns NULL at the point 1152 // where we are created.) 1153 // 1154 // It should be OK to not set a default parent since such users will 1155 // explicitly add this WebContentsViewAura to their tree after they create 1156 // us. 1157 if (root_window) { 1158 window_->SetDefaultParentByRootWindow( 1159 root_window, root_window->GetBoundsInScreen()); 1160 } 1161 } 1162 window_->layer()->SetMasksToBounds(true); 1163 window_->SetName("WebContentsViewAura"); 1164 1165 window_observer_.reset(new WindowObserver(this)); 1166#if defined(OS_WIN) 1167 child_window_observer_.reset(new ChildWindowObserver(this)); 1168#endif 1169 1170 // delegate_->GetDragDestDelegate() creates a new delegate on every call. 1171 // Hence, we save a reference to it locally. Similar model is used on other 1172 // platforms as well. 1173 if (delegate_) 1174 drag_dest_delegate_ = delegate_->GetDragDestDelegate(); 1175} 1176 1177RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget( 1178 RenderWidgetHost* render_widget_host) { 1179 if (render_widget_host->GetView()) { 1180 // During testing, the view will already be set up in most cases to the 1181 // test view, so we don't want to clobber it with a real one. To verify that 1182 // this actually is happening (and somebody isn't accidentally creating the 1183 // view twice), we check for the RVH Factory, which will be set when we're 1184 // making special ones (which go along with the special views). 1185 DCHECK(RenderViewHostFactory::has_factory()); 1186 return render_widget_host->GetView(); 1187 } 1188 1189 RenderWidgetHostView* view = 1190 RenderWidgetHostView::CreateViewForWidget(render_widget_host); 1191 view->InitAsChild(NULL); 1192 GetNativeView()->AddChild(view->GetNativeView()); 1193 1194 if (navigation_overlay_.get() && navigation_overlay_->has_window()) { 1195 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view)); 1196 } 1197 1198 RenderWidgetHostImpl* host_impl = 1199 RenderWidgetHostImpl::From(render_widget_host); 1200 1201 if (!host_impl->is_hidden()) 1202 view->Show(); 1203 1204 // We listen to drag drop events in the newly created view's window. 1205 aura::client::SetDragDropDelegate(view->GetNativeView(), this); 1206 1207 if (host_impl->overscroll_controller() && 1208 (!web_contents_->GetDelegate() || 1209 web_contents_->GetDelegate()->CanOverscrollContent())) { 1210 host_impl->overscroll_controller()->set_delegate(this); 1211 if (!navigation_overlay_) 1212 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_)); 1213 } 1214 1215 AttachTouchEditableToRenderView(); 1216 return view; 1217} 1218 1219RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget( 1220 RenderWidgetHost* render_widget_host) { 1221 return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); 1222} 1223 1224void WebContentsViewAura::SetPageTitle(const string16& title) { 1225 window_->set_title(title); 1226} 1227 1228void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) { 1229} 1230 1231void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) { 1232 if (navigation_overlay_.get() && navigation_overlay_->has_window()) { 1233 navigation_overlay_->StartObservingView( 1234 ToRenderWidgetHostViewAura(host->GetView())); 1235 } 1236 AttachTouchEditableToRenderView(); 1237} 1238 1239void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) { 1240 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>( 1241 web_contents_->GetRenderViewHost()); 1242 if (host) { 1243 host->SetOverscrollControllerEnabled(enabled); 1244 if (enabled) 1245 host->overscroll_controller()->set_delegate(this); 1246 } 1247 1248 if (!enabled) 1249 navigation_overlay_.reset(); 1250 else if (!navigation_overlay_) 1251 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_)); 1252} 1253 1254//////////////////////////////////////////////////////////////////////////////// 1255// WebContentsViewAura, RenderViewHostDelegateView implementation: 1256 1257void WebContentsViewAura::ShowContextMenu(const ContextMenuParams& params) { 1258 if (touch_editable_) 1259 touch_editable_->EndTouchEditing(); 1260 if (delegate_) { 1261 delegate_->ShowContextMenu(params); 1262 // WARNING: we may have been deleted during the call to ShowContextMenu(). 1263 } 1264} 1265 1266void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds, 1267 int item_height, 1268 double item_font_size, 1269 int selected_item, 1270 const std::vector<MenuItem>& items, 1271 bool right_aligned, 1272 bool allow_multiple_selection) { 1273 // External popup menus are only used on Mac and Android. 1274 NOTIMPLEMENTED(); 1275} 1276 1277void WebContentsViewAura::StartDragging( 1278 const DropData& drop_data, 1279 WebKit::WebDragOperationsMask operations, 1280 const gfx::ImageSkia& image, 1281 const gfx::Vector2d& image_offset, 1282 const DragEventSourceInfo& event_info) { 1283 aura::RootWindow* root_window = GetNativeView()->GetRootWindow(); 1284 if (!aura::client::GetDragDropClient(root_window)) { 1285 web_contents_->SystemDragEnded(); 1286 return; 1287 } 1288 1289 if (touch_editable_) 1290 touch_editable_->EndTouchEditing(); 1291 1292 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider(); 1293 PrepareDragData(drop_data, provider); 1294 1295 ui::OSExchangeData data(provider); // takes ownership of |provider|. 1296 1297 if (!image.isNull()) { 1298 drag_utils::SetDragImageOnDataObject(image, 1299 gfx::Size(image.width(), image.height()), image_offset, &data); 1300 } 1301 1302 scoped_ptr<WebDragSourceAura> drag_source( 1303 new WebDragSourceAura(GetNativeView(), web_contents_)); 1304 1305 // We need to enable recursive tasks on the message loop so we can get 1306 // updates while in the system DoDragDrop loop. 1307 int result_op = 0; 1308 { 1309 gfx::NativeView content_native_view = GetContentNativeView(); 1310 base::MessageLoop::ScopedNestableTaskAllower allow( 1311 base::MessageLoop::current()); 1312 result_op = aura::client::GetDragDropClient(root_window) 1313 ->StartDragAndDrop(data, 1314 root_window, 1315 content_native_view, 1316 event_info.event_location, 1317 ConvertFromWeb(operations), 1318 event_info.event_source); 1319 } 1320 1321 // Bail out immediately if the contents view window is gone. Note that it is 1322 // not safe to access any class members in this case since |this| may already 1323 // be destroyed. The local variable |drag_source| will still be valid though, 1324 // so we can use it to determine if the window is gone. 1325 if (!drag_source->window()) { 1326 // Note that in this case, we don't need to call SystemDragEnded() since the 1327 // renderer is going away. 1328 return; 1329 } 1330 1331 EndDrag(ConvertToWeb(result_op)); 1332 web_contents_->SystemDragEnded(); 1333} 1334 1335void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) { 1336 current_drag_op_ = operation; 1337} 1338 1339void WebContentsViewAura::GotFocus() { 1340 if (web_contents_->GetDelegate()) 1341 web_contents_->GetDelegate()->WebContentsFocused(web_contents_); 1342} 1343 1344void WebContentsViewAura::TakeFocus(bool reverse) { 1345 if (web_contents_->GetDelegate() && 1346 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) && 1347 delegate_.get()) { 1348 delegate_->TakeFocus(reverse); 1349 } 1350} 1351 1352//////////////////////////////////////////////////////////////////////////////// 1353// WebContentsViewAura, OverscrollControllerDelegate implementation: 1354 1355void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) { 1356 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 1357 return; 1358 1359 aura::Window* target = GetWindowToAnimateForOverscroll(); 1360 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 1361 settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); 1362 gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y); 1363 gfx::Transform transform; 1364 1365 // Vertical overscrolls don't participate in the navigation gesture. 1366 if (current_overscroll_gesture_ != OVERSCROLL_NORTH && 1367 current_overscroll_gesture_ != OVERSCROLL_SOUTH) { 1368 transform.Translate(translate.x(), translate.y()); 1369 target->SetTransform(transform); 1370 UpdateOverscrollWindowBrightness(delta_x); 1371 } 1372 1373 OverscrollUpdateForWebContentsDelegate(translate.y()); 1374} 1375 1376void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) { 1377 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT); 1378 OverscrollUpdateForWebContentsDelegate(0); 1379 NavigationControllerImpl& controller = web_contents_->GetController(); 1380 if (ShouldNavigateForward(controller, mode) || 1381 ShouldNavigateBack(controller, mode)) { 1382 CompleteOverscrollNavigation(mode); 1383 return; 1384 } 1385 1386 ResetOverscrollTransform(); 1387} 1388 1389void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode, 1390 OverscrollMode new_mode) { 1391 // Reset any in-progress overscroll animation first. 1392 ResetOverscrollTransform(); 1393 1394 if (new_mode != OVERSCROLL_NONE && touch_editable_) 1395 touch_editable_->OverscrollStarted(); 1396 1397 if (new_mode == OVERSCROLL_NONE || 1398 !GetContentNativeView() || 1399 ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) && 1400 navigation_overlay_.get() && navigation_overlay_->has_window())) { 1401 current_overscroll_gesture_ = OVERSCROLL_NONE; 1402 OverscrollUpdateForWebContentsDelegate(0); 1403 } else { 1404 aura::Window* target = GetWindowToAnimateForOverscroll(); 1405 if (target) { 1406 StopObservingImplicitAnimations(); 1407 target->layer()->GetAnimator()->AbortAllAnimations(); 1408 } 1409 // Cleanup state of the content window first, because that can reset the 1410 // value of |current_overscroll_gesture_|. 1411 PrepareContentWindowForOverscroll(); 1412 1413 current_overscroll_gesture_ = new_mode; 1414 if (current_overscroll_gesture_ == OVERSCROLL_EAST || 1415 current_overscroll_gesture_ == OVERSCROLL_WEST) 1416 PrepareOverscrollWindow(); 1417 1418 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT); 1419 } 1420 completed_overscroll_gesture_ = OVERSCROLL_NONE; 1421} 1422 1423//////////////////////////////////////////////////////////////////////////////// 1424// WebContentsViewAura, ui::ImplicitAnimationObserver implementation: 1425 1426void WebContentsViewAura::OnImplicitAnimationsCompleted() { 1427 overscroll_shadow_.reset(); 1428 1429 if (ShouldNavigateForward(web_contents_->GetController(), 1430 completed_overscroll_gesture_)) { 1431 PrepareOverscrollNavigationOverlay(); 1432 web_contents_->GetController().GoForward(); 1433 } else if (ShouldNavigateBack(web_contents_->GetController(), 1434 completed_overscroll_gesture_)) { 1435 PrepareOverscrollNavigationOverlay(); 1436 web_contents_->GetController().GoBack(); 1437 } else { 1438 if (touch_editable_) 1439 touch_editable_->OverscrollCompleted(); 1440 } 1441 1442 aura::Window* content = GetContentNativeView(); 1443 if (content) { 1444 content->SetTransform(gfx::Transform()); 1445 content->layer()->SetLayerBrightness(0.f); 1446 } 1447 current_overscroll_gesture_ = OVERSCROLL_NONE; 1448 completed_overscroll_gesture_ = OVERSCROLL_NONE; 1449 overscroll_window_.reset(); 1450} 1451 1452//////////////////////////////////////////////////////////////////////////////// 1453// WebContentsViewAura, aura::WindowDelegate implementation: 1454 1455gfx::Size WebContentsViewAura::GetMinimumSize() const { 1456 return gfx::Size(); 1457} 1458 1459gfx::Size WebContentsViewAura::GetMaximumSize() const { 1460 return gfx::Size(); 1461} 1462 1463void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds, 1464 const gfx::Rect& new_bounds) { 1465 SizeChangedCommon(new_bounds.size()); 1466 if (delegate_) 1467 delegate_->SizeChanged(new_bounds.size()); 1468 1469 // Constrained web dialogs, need to be kept centered over our content area. 1470 for (size_t i = 0; i < window_->children().size(); i++) { 1471 if (window_->children()[i]->GetProperty( 1472 aura::client::kConstrainedWindowKey)) { 1473 gfx::Rect bounds = window_->children()[i]->bounds(); 1474 bounds.set_origin( 1475 gfx::Point((new_bounds.width() - bounds.width()) / 2, 1476 (new_bounds.height() - bounds.height()) / 2)); 1477 window_->children()[i]->SetBounds(bounds); 1478 } 1479 } 1480} 1481 1482gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) { 1483 return gfx::kNullCursor; 1484} 1485 1486int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const { 1487 return HTCLIENT; 1488} 1489 1490bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling( 1491 aura::Window* child, 1492 const gfx::Point& location) { 1493 return true; 1494} 1495 1496bool WebContentsViewAura::CanFocus() { 1497 // Do not take the focus if the render widget host view is gone because 1498 // neither the view window nor this window can handle key events. 1499 return web_contents_->GetRenderWidgetHostView() != NULL; 1500} 1501 1502void WebContentsViewAura::OnCaptureLost() { 1503} 1504 1505void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) { 1506} 1507 1508void WebContentsViewAura::OnDeviceScaleFactorChanged( 1509 float device_scale_factor) { 1510} 1511 1512void WebContentsViewAura::OnWindowDestroying() { 1513 // This means the destructor is going to be called soon. If there is an 1514 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL), 1515 // then destroying it in the WebContentsViewAura destructor can trigger other 1516 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So 1517 // destroy the overscroll window here. 1518 navigation_overlay_.reset(); 1519 overscroll_window_.reset(); 1520} 1521 1522void WebContentsViewAura::OnWindowDestroyed() { 1523} 1524 1525void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) { 1526 if (visible) 1527 web_contents_->WasShown(); 1528 else 1529 web_contents_->WasHidden(); 1530} 1531 1532bool WebContentsViewAura::HasHitTestMask() const { 1533 return false; 1534} 1535 1536void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const { 1537} 1538 1539void WebContentsViewAura::DidRecreateLayer(ui::Layer *old_layer, 1540 ui::Layer *new_layer) { 1541} 1542 1543//////////////////////////////////////////////////////////////////////////////// 1544// WebContentsViewAura, ui::EventHandler implementation: 1545 1546void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) { 1547} 1548 1549void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) { 1550 if (!web_contents_->GetDelegate()) 1551 return; 1552 1553 switch (event->type()) { 1554 case ui::ET_MOUSE_PRESSED: 1555 web_contents_->GetDelegate()->ActivateContents(web_contents_); 1556 break; 1557 case ui::ET_MOUSE_MOVED: 1558 case ui::ET_MOUSE_EXITED: 1559 web_contents_->GetDelegate()->ContentsMouseEvent( 1560 web_contents_, 1561 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(), 1562 event->type() == ui::ET_MOUSE_MOVED); 1563 break; 1564 default: 1565 break; 1566 } 1567} 1568 1569//////////////////////////////////////////////////////////////////////////////// 1570// WebContentsViewAura, aura::client::DragDropDelegate implementation: 1571 1572void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) { 1573 if (drag_dest_delegate_) 1574 drag_dest_delegate_->DragInitialize(web_contents_); 1575 1576 current_drop_data_.reset(new DropData()); 1577 1578 PrepareDropData(current_drop_data_.get(), event.data()); 1579 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); 1580 1581 gfx::Point screen_pt = 1582 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 1583 current_rvh_for_drag_ = web_contents_->GetRenderViewHost(); 1584 web_contents_->GetRenderViewHost()->DragTargetDragEnter( 1585 *current_drop_data_.get(), event.location(), screen_pt, op, 1586 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1587 1588 if (drag_dest_delegate_) { 1589 drag_dest_delegate_->OnReceiveDragData(event.data()); 1590 drag_dest_delegate_->OnDragEnter(); 1591 } 1592} 1593 1594int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) { 1595 DCHECK(current_rvh_for_drag_); 1596 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1597 OnDragEntered(event); 1598 1599 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); 1600 gfx::Point screen_pt = 1601 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 1602 web_contents_->GetRenderViewHost()->DragTargetDragOver( 1603 event.location(), screen_pt, op, 1604 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1605 1606 if (drag_dest_delegate_) 1607 drag_dest_delegate_->OnDragOver(); 1608 1609 return ConvertFromWeb(current_drag_op_); 1610} 1611 1612void WebContentsViewAura::OnDragExited() { 1613 DCHECK(current_rvh_for_drag_); 1614 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1615 return; 1616 1617 web_contents_->GetRenderViewHost()->DragTargetDragLeave(); 1618 if (drag_dest_delegate_) 1619 drag_dest_delegate_->OnDragLeave(); 1620 1621 current_drop_data_.reset(); 1622} 1623 1624int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) { 1625 DCHECK(current_rvh_for_drag_); 1626 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1627 OnDragEntered(event); 1628 1629 web_contents_->GetRenderViewHost()->DragTargetDrop( 1630 event.location(), 1631 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(), 1632 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1633 if (drag_dest_delegate_) 1634 drag_dest_delegate_->OnDrop(); 1635 current_drop_data_.reset(); 1636 return current_drag_op_; 1637} 1638 1639} // namespace content 1640