web_contents_view_aura.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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_aura.h" 6 7#include "base/auto_reset.h" 8#include "base/metrics/histogram.h" 9#include "base/utf_string_conversions.h" 10#include "content/browser/renderer_host/dip_util.h" 11#include "content/browser/renderer_host/overscroll_controller.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/renderer_host/render_widget_host_impl.h" 15#include "content/browser/renderer_host/render_widget_host_view_aura.h" 16#include "content/browser/web_contents/aura/image_window_delegate.h" 17#include "content/browser/web_contents/aura/shadow_layer_delegate.h" 18#include "content/browser/web_contents/interstitial_page_impl.h" 19#include "content/browser/web_contents/navigation_entry_impl.h" 20#include "content/browser/web_contents/touch_editable_impl_aura.h" 21#include "content/browser/web_contents/web_contents_impl.h" 22#include "content/public/browser/notification_observer.h" 23#include "content/public/browser/notification_registrar.h" 24#include "content/public/browser/notification_source.h" 25#include "content/public/browser/notification_types.h" 26#include "content/public/browser/overscroll_configuration.h" 27#include "content/public/browser/render_view_host.h" 28#include "content/public/browser/render_widget_host.h" 29#include "content/public/browser/render_widget_host_view.h" 30#include "content/public/browser/web_contents_delegate.h" 31#include "content/public/browser/web_contents_observer.h" 32#include "content/public/browser/web_contents_view_delegate.h" 33#include "content/public/browser/web_drag_dest_delegate.h" 34#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" 35#include "ui/aura/client/aura_constants.h" 36#include "ui/aura/client/drag_drop_client.h" 37#include "ui/aura/client/drag_drop_delegate.h" 38#include "ui/aura/root_window.h" 39#include "ui/aura/root_window_observer.h" 40#include "ui/aura/window.h" 41#include "ui/aura/window_observer.h" 42#include "ui/base/clipboard/custom_data_helper.h" 43#include "ui/base/dragdrop/drag_drop_types.h" 44#include "ui/base/dragdrop/drag_utils.h" 45#include "ui/base/dragdrop/os_exchange_data.h" 46#include "ui/base/events/event.h" 47#include "ui/base/events/event_utils.h" 48#include "ui/base/hit_test.h" 49#include "ui/compositor/layer.h" 50#include "ui/compositor/scoped_layer_animation_settings.h" 51#include "ui/gfx/canvas.h" 52#include "ui/gfx/image/image.h" 53#include "ui/gfx/image/image_png_rep.h" 54#include "ui/gfx/image/image_skia.h" 55#include "ui/gfx/screen.h" 56#include "webkit/glue/webdropdata.h" 57 58#if defined(OS_WIN) 59#include "ui/base/clipboard/clipboard_util_win.h" 60#endif 61 62namespace content { 63WebContentsViewPort* CreateWebContentsView( 64 WebContentsImpl* web_contents, 65 WebContentsViewDelegate* delegate, 66 RenderViewHostDelegateView** render_view_host_delegate_view) { 67 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate); 68 *render_view_host_delegate_view = rv; 69 return rv; 70} 71 72namespace { 73 74bool ShouldNavigateForward(const NavigationController& controller, 75 OverscrollMode mode) { 76 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) && 77 controller.CanGoForward(); 78} 79 80bool ShouldNavigateBack(const NavigationController& controller, 81 OverscrollMode mode) { 82 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) && 83 controller.CanGoBack(); 84} 85 86RenderWidgetHostViewAura* ToRenderWidgetHostViewAura( 87 RenderWidgetHostView* view) { 88 if (!view || RenderViewHostFactory::has_factory()) 89 return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests. 90 RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>( 91 view->GetRenderWidgetHost()->GetProcess()); 92 if (process->IsGuest()) 93 return NULL; 94 return static_cast<RenderWidgetHostViewAura*>(view); 95} 96 97// The window delegate for the overscroll window. This redirects trackpad events 98// to the web-contents window. The delegate destroys itself when the window is 99// destroyed. 100class OverscrollWindowDelegate : public ImageWindowDelegate { 101 public: 102 OverscrollWindowDelegate(WebContentsImpl* web_contents, 103 OverscrollMode overscroll_mode) 104 : web_contents_(web_contents), 105 forward_events_(true) { 106 const NavigationControllerImpl& controller = web_contents->GetController(); 107 const NavigationEntryImpl* entry = NULL; 108 if (ShouldNavigateForward(controller, overscroll_mode)) { 109 entry = NavigationEntryImpl::FromNavigationEntry( 110 controller.GetEntryAtOffset(1)); 111 } else if (ShouldNavigateBack(controller, overscroll_mode)) { 112 entry = NavigationEntryImpl::FromNavigationEntry( 113 controller.GetEntryAtOffset(-1)); 114 } 115 116 gfx::Image image; 117 if (entry && entry->screenshot()) { 118 std::vector<gfx::ImagePNGRep> image_reps; 119 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 120 ui::GetScaleFactorForNativeView(web_contents_window()))); 121 image = gfx::Image(image_reps); 122 } 123 SetImage(image); 124 } 125 126 void stop_forwarding_events() { forward_events_ = false; } 127 128 private: 129 virtual ~OverscrollWindowDelegate() {} 130 131 aura::Window* web_contents_window() { 132 return web_contents_->GetView()->GetContentNativeView(); 133 } 134 135 // Overridden from ui::EventHandler. 136 virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE { 137 if (forward_events_ && web_contents_window()) 138 web_contents_window()->delegate()->OnScrollEvent(event); 139 } 140 141 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 142 if (forward_events_ && web_contents_window()) 143 web_contents_window()->delegate()->OnGestureEvent(event); 144 } 145 146 WebContents* web_contents_; 147 148 // The window is displayed both during the gesture, and after the gesture 149 // while the navigation is in progress. During the gesture, it is necessary to 150 // forward input events to the content page (e.g. when the overscroll window 151 // slides under the cursor and starts receiving scroll events). However, once 152 // the gesture is complete, and the window is being displayed as an overlay 153 // window during navigation, events should not be forwarded anymore. 154 bool forward_events_; 155 156 DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate); 157}; 158 159// Listens to all mouse drag events during a drag and drop and sends them to 160// the renderer. 161class WebDragSourceAura : public base::MessageLoopForUI::Observer, 162 public NotificationObserver { 163 public: 164 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents) 165 : window_(window), 166 contents_(contents) { 167 base::MessageLoopForUI::current()->AddObserver(this); 168 registrar_.Add(this, 169 NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 170 Source<WebContents>(contents)); 171 } 172 173 virtual ~WebDragSourceAura() { 174 base::MessageLoopForUI::current()->RemoveObserver(this); 175 } 176 177 // MessageLoop::Observer implementation: 178 virtual base::EventStatus WillProcessEvent( 179 const base::NativeEvent& event) OVERRIDE { 180 return base::EVENT_CONTINUE; 181 } 182 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { 183 if (!contents_) 184 return; 185 ui::EventType type = ui::EventTypeFromNative(event); 186 RenderViewHost* rvh = NULL; 187 switch (type) { 188 case ui::ET_MOUSE_DRAGGED: 189 rvh = contents_->GetRenderViewHost(); 190 if (rvh) { 191 gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event); 192 gfx::Point screen_loc = ConvertPointToDIP(rvh->GetView(), 193 screen_loc_in_pixel); 194 gfx::Point client_loc = screen_loc; 195 aura::Window* window = rvh->GetView()->GetNativeView(); 196 aura::Window::ConvertPointToTarget(window->GetRootWindow(), 197 window, &client_loc); 198 contents_->DragSourceMovedTo(client_loc.x(), client_loc.y(), 199 screen_loc.x(), screen_loc.y()); 200 } 201 break; 202 default: 203 break; 204 } 205 } 206 207 virtual void Observe(int type, 208 const NotificationSource& source, 209 const NotificationDetails& details) OVERRIDE { 210 if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED) 211 return; 212 213 // Cancel the drag if it is still in progress. 214 aura::client::DragDropClient* dnd_client = 215 aura::client::GetDragDropClient(window_->GetRootWindow()); 216 if (dnd_client && dnd_client->IsDragDropInProgress()) 217 dnd_client->DragCancel(); 218 219 window_ = NULL; 220 contents_ = NULL; 221 } 222 223 aura::Window* window() const { return window_; } 224 225 private: 226 aura::Window* window_; 227 WebContentsImpl* contents_; 228 NotificationRegistrar registrar_; 229 230 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura); 231}; 232 233// Utility to fill a ui::OSExchangeDataProvider object from WebDropData. 234void PrepareDragData(const WebDropData& drop_data, 235 ui::OSExchangeData::Provider* provider) { 236 if (!drop_data.text.string().empty()) 237 provider->SetString(drop_data.text.string()); 238 if (drop_data.url.is_valid()) 239 provider->SetURL(drop_data.url, drop_data.url_title); 240 if (!drop_data.html.string().empty()) 241 provider->SetHtml(drop_data.html.string(), drop_data.html_base_url); 242 if (!drop_data.filenames.empty()) { 243 std::vector<ui::OSExchangeData::FileInfo> filenames; 244 for (std::vector<WebDropData::FileInfo>::const_iterator it = 245 drop_data.filenames.begin(); 246 it != drop_data.filenames.end(); ++it) { 247 filenames.push_back( 248 ui::OSExchangeData::FileInfo( 249 base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)), 250 base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->display_name)))); 251 } 252 provider->SetFilenames(filenames); 253 } 254 if (!drop_data.custom_data.empty()) { 255 Pickle pickle; 256 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle); 257#if defined(OS_WIN) 258 provider->SetPickledData( 259 ui::ClipboardUtil::GetWebCustomDataFormat()->cfFormat, pickle); 260#else 261 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), 262 pickle); 263#endif 264 } 265} 266 267// Utility to fill a WebDropData object from ui::OSExchangeData. 268void PrepareWebDropData(WebDropData* drop_data, 269 const ui::OSExchangeData& data) { 270 string16 plain_text; 271 data.GetString(&plain_text); 272 if (!plain_text.empty()) 273 drop_data->text = NullableString16(plain_text, false); 274 275 GURL url; 276 string16 url_title; 277 data.GetURLAndTitle(&url, &url_title); 278 if (url.is_valid()) { 279 drop_data->url = url; 280 drop_data->url_title = url_title; 281 } 282 283 string16 html; 284 GURL html_base_url; 285 data.GetHtml(&html, &html_base_url); 286 if (!html.empty()) 287 drop_data->html = NullableString16(html, false); 288 if (html_base_url.is_valid()) 289 drop_data->html_base_url = html_base_url; 290 291 std::vector<ui::OSExchangeData::FileInfo> files; 292 if (data.GetFilenames(&files) && !files.empty()) { 293 for (std::vector<ui::OSExchangeData::FileInfo>::const_iterator 294 it = files.begin(); it != files.end(); ++it) { 295 drop_data->filenames.push_back( 296 WebDropData::FileInfo( 297 UTF8ToUTF16(it->path.AsUTF8Unsafe()), 298 UTF8ToUTF16(it->display_name.AsUTF8Unsafe()))); 299 } 300 } 301 302 Pickle pickle; 303#if defined(OS_WIN) 304 if (data.GetPickledData(ui::ClipboardUtil::GetWebCustomDataFormat()->cfFormat, 305 &pickle)) 306#else 307 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), 308 &pickle)) 309#endif 310 ui::ReadCustomDataIntoMap(pickle.data(), pickle.size(), 311 &drop_data->custom_data); 312} 313 314// Utilities to convert between WebKit::WebDragOperationsMask and 315// ui::DragDropTypes. 316int ConvertFromWeb(WebKit::WebDragOperationsMask ops) { 317 int drag_op = ui::DragDropTypes::DRAG_NONE; 318 if (ops & WebKit::WebDragOperationCopy) 319 drag_op |= ui::DragDropTypes::DRAG_COPY; 320 if (ops & WebKit::WebDragOperationMove) 321 drag_op |= ui::DragDropTypes::DRAG_MOVE; 322 if (ops & WebKit::WebDragOperationLink) 323 drag_op |= ui::DragDropTypes::DRAG_LINK; 324 return drag_op; 325} 326 327WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) { 328 int web_drag_op = WebKit::WebDragOperationNone; 329 if (drag_op & ui::DragDropTypes::DRAG_COPY) 330 web_drag_op |= WebKit::WebDragOperationCopy; 331 if (drag_op & ui::DragDropTypes::DRAG_MOVE) 332 web_drag_op |= WebKit::WebDragOperationMove; 333 if (drag_op & ui::DragDropTypes::DRAG_LINK) 334 web_drag_op |= WebKit::WebDragOperationLink; 335 return (WebKit::WebDragOperationsMask) web_drag_op; 336} 337 338int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) { 339 int web_input_event_modifiers = 0; 340 if (aura_event_flags & ui::EF_SHIFT_DOWN) 341 web_input_event_modifiers |= WebKit::WebInputEvent::ShiftKey; 342 if (aura_event_flags & ui::EF_CONTROL_DOWN) 343 web_input_event_modifiers |= WebKit::WebInputEvent::ControlKey; 344 if (aura_event_flags & ui::EF_ALT_DOWN) 345 web_input_event_modifiers |= WebKit::WebInputEvent::AltKey; 346 if (aura_event_flags & ui::EF_COMMAND_DOWN) 347 web_input_event_modifiers |= WebKit::WebInputEvent::MetaKey; 348 return web_input_event_modifiers; 349} 350 351} // namespace 352 353// When a history navigation is triggered at the end of an overscroll 354// navigation, it is necessary to show the history-screenshot until the page is 355// done navigating and painting. This class accomplishes this by showing the 356// screenshot window on top of the page until the page has completed loading and 357// painting. 358class OverscrollNavigationOverlay : 359 public RenderWidgetHostViewAura::PaintObserver { 360 public: 361 OverscrollNavigationOverlay() 362 : view_(NULL), 363 loading_complete_(false), 364 received_paint_update_(false), 365 compositor_updated_(false), 366 has_screenshot_(false), 367 need_paint_update_(true) { 368 } 369 370 virtual ~OverscrollNavigationOverlay() { 371 if (view_) 372 view_->set_paint_observer(NULL); 373 } 374 375 bool has_window() const { return !!window_.get(); } 376 377 void StartObservingView(RenderWidgetHostViewAura* view) { 378 if (view_) 379 view_->set_paint_observer(NULL); 380 381 loading_complete_ = false; 382 received_paint_update_ = false; 383 compositor_updated_ = false; 384 view_ = view; 385 if (view_) 386 view_->set_paint_observer(this); 387 388 // Make sure the overlay window is on top. 389 if (window_.get() && window_->parent()) 390 window_->parent()->StackChildAtTop(window_.get()); 391 } 392 393 void SetOverlayWindow(scoped_ptr<aura::Window> window, bool has_screenshot) { 394 window_ = window.Pass(); 395 if (window_.get() && window_->parent()) 396 window_->parent()->StackChildAtTop(window_.get()); 397 has_screenshot_ = has_screenshot; 398 } 399 400 void SetupForTesting() { 401 need_paint_update_ = false; 402 } 403 404 private: 405 // Stop observing the page if the page-load has completed and the page has 406 // been painted. 407 void StopObservingIfDone() { 408 // If there is a screenshot displayed in the overlay window, then wait for 409 // the navigated page to complete loading and some paint update before 410 // hiding the overlay. 411 // If there is no screenshot in the overlay window, then hide this view 412 // as soon as there is any new painting notification. 413 if ((need_paint_update_ && !received_paint_update_) || 414 (has_screenshot_ && !loading_complete_)) { 415 return; 416 } 417 418 window_.reset(); 419 if (view_) { 420 view_->set_paint_observer(NULL); 421 view_ = NULL; 422 } 423 } 424 425 // Overridden from RenderWidgetHostViewAura::PaintObserver: 426 virtual void OnPaintComplete() OVERRIDE { 427 received_paint_update_ = true; 428 StopObservingIfDone(); 429 } 430 431 virtual void OnCompositingComplete() OVERRIDE { 432 received_paint_update_ = compositor_updated_; 433 StopObservingIfDone(); 434 } 435 436 virtual void OnUpdateCompositorContent() OVERRIDE { 437 compositor_updated_ = true; 438 } 439 440 virtual void OnPageLoadComplete() OVERRIDE { 441 loading_complete_ = true; 442 StopObservingIfDone(); 443 } 444 445 virtual void OnViewDestroyed() OVERRIDE { 446 DCHECK(view_); 447 view_->set_paint_observer(NULL); 448 view_ = NULL; 449 } 450 451 scoped_ptr<aura::Window> window_; 452 RenderWidgetHostViewAura* view_; 453 bool loading_complete_; 454 bool received_paint_update_; 455 bool compositor_updated_; 456 bool has_screenshot_; 457 458 // During tests, the aura windows don't get any paint updates. So the overlay 459 // container keeps waiting for a paint update it never receives, causing a 460 // timeout. So during tests, disable the wait for paint updates. 461 bool need_paint_update_; 462 463 DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay); 464}; 465 466class WebContentsViewAura::WindowObserver 467 : public aura::WindowObserver, public aura::RootWindowObserver { 468 public: 469 explicit WindowObserver(WebContentsViewAura* view) 470 : view_(view), 471 parent_(NULL) { 472 view_->window_->AddObserver(this); 473 } 474 475 virtual ~WindowObserver() { 476 view_->window_->RemoveObserver(this); 477 if (view_->window_->GetRootWindow()) 478 view_->window_->GetRootWindow()->RemoveRootWindowObserver(this); 479 if (parent_) 480 parent_->RemoveObserver(this); 481 } 482 483 // Overridden from aura::WindowObserver: 484 virtual void OnWindowParentChanged(aura::Window* window, 485 aura::Window* parent) OVERRIDE { 486 if (window == parent_) 487 return; 488 if (parent_) 489 parent_->RemoveObserver(this); 490 parent_ = parent; 491 if (parent) 492 parent->AddObserver(this); 493 } 494 495 virtual void OnWindowBoundsChanged(aura::Window* window, 496 const gfx::Rect& old_bounds, 497 const gfx::Rect& new_bounds) OVERRIDE { 498 SendScreenRects(); 499 if (view_->touch_editable_) 500 view_->touch_editable_->UpdateEditingController(); 501 } 502 503 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE { 504 if (window != parent_) 505 window->GetRootWindow()->AddRootWindowObserver(this); 506 } 507 508 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE { 509 if (window != parent_) 510 window->GetRootWindow()->RemoveRootWindowObserver(this); 511 } 512 513 // Overridden RootWindowObserver: 514 virtual void OnRootWindowMoved(const aura::RootWindow* root, 515 const gfx::Point& new_origin) OVERRIDE { 516 // This is for the desktop case (i.e. Aura desktop). 517 SendScreenRects(); 518 } 519 520 private: 521 void SendScreenRects() { 522 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())-> 523 SendScreenRects(); 524 } 525 526 WebContentsViewAura* view_; 527 528 // We cache the old parent so that we can unregister when it's not the parent 529 // anymore. 530 aura::Window* parent_; 531 532 DISALLOW_COPY_AND_ASSIGN(WindowObserver); 533}; 534 535#if defined(OS_WIN) 536// Constrained windows are added as children of the WebContent's view which may 537// overlap with windowed NPAPI plugins. In that case, tell the RWHV so that it 538// can update the plugins' cutout rects accordingly. 539class WebContentsViewAura::ChildWindowObserver : public aura::WindowObserver, 540 public WebContentsObserver { 541 public: 542 explicit ChildWindowObserver(WebContentsViewAura* view) 543 : WebContentsObserver(view->web_contents_), 544 view_(view), 545 web_contents_destroyed_(false) { 546 view_->window_->AddObserver(this); 547 } 548 549 virtual ~ChildWindowObserver() { 550 view_->window_->RemoveObserver(this); 551 const aura::Window::Windows& children = view_->window_->children(); 552 for (size_t i = 0; i < children.size(); ++i) 553 children[i]->RemoveObserver(this); 554 } 555 556 // Overridden from aura::WindowObserver: 557 virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE { 558 // If new child windows are added to the WebContent's view, tell the RWHV. 559 // We also start watching them to know when their size is updated. Of 560 // course, ignore the shadow window that contains the RWHV and child windows 561 // of the child windows that we are watching. 562 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( 563 view_->web_contents_->GetRenderWidgetHostView()); 564 aura::Window* content_window = view ? view->GetNativeView() : NULL; 565 if (new_window->parent() == view_->window_ && 566 new_window != content_window) { 567 new_window->AddObserver(this); 568 UpdateConstrainedWindows(NULL); 569 } 570 } 571 572 virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE { 573 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( 574 view_->web_contents_->GetRenderWidgetHostView()); 575 aura::Window* content_window = view ? view->GetNativeView() : NULL; 576 if (window->parent() == view_->window_ && 577 window != content_window) { 578 window->RemoveObserver(this); 579 UpdateConstrainedWindows(window); 580 } 581 } 582 583 virtual void OnWindowBoundsChanged(aura::Window* window, 584 const gfx::Rect& old_bounds, 585 const gfx::Rect& new_bounds) OVERRIDE { 586 if (window->parent() == view_->window_ && 587 window != view_->GetContentNativeView()) { 588 UpdateConstrainedWindows(NULL); 589 } 590 } 591 592 // Overridden from WebContentsObserver: 593 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { 594 web_contents_destroyed_ = true; 595 } 596 597 private: 598 void UpdateConstrainedWindows(aura::Window* exclude) { 599 if (web_contents_destroyed_) 600 return; 601 602 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( 603 view_->web_contents_->GetRenderWidgetHostView()); 604 if (!view) 605 return; 606 607 std::vector<gfx::Rect> constrained_windows; 608 const aura::Window::Windows& children = view_->window_->children(); 609 aura::Window* content = view_->GetContentNativeView(); 610 for (size_t i = 0; i < children.size(); ++i) { 611 if (children[i] != content && children[i] != exclude) 612 constrained_windows.push_back(children[i]->GetBoundsInRootWindow()); 613 } 614 615 view->UpdateConstrainedWindowRects(constrained_windows); 616 } 617 618 WebContentsViewAura* view_; 619 bool web_contents_destroyed_; 620 621 DISALLOW_COPY_AND_ASSIGN(ChildWindowObserver); 622}; 623#endif 624 625//////////////////////////////////////////////////////////////////////////////// 626// WebContentsViewAura, public: 627 628WebContentsViewAura::WebContentsViewAura( 629 WebContentsImpl* web_contents, 630 WebContentsViewDelegate* delegate) 631 : web_contents_(web_contents), 632 delegate_(delegate), 633 current_drag_op_(WebKit::WebDragOperationNone), 634 drag_dest_delegate_(NULL), 635 current_rvh_for_drag_(NULL), 636 overscroll_change_brightness_(false), 637 current_overscroll_gesture_(OVERSCROLL_NONE), 638 completed_overscroll_gesture_(OVERSCROLL_NONE), 639 touch_editable_(TouchEditableImplAura::Create()) { 640} 641 642//////////////////////////////////////////////////////////////////////////////// 643// WebContentsViewAura, private: 644 645WebContentsViewAura::~WebContentsViewAura() { 646 if (!window_) 647 return; 648 649 window_observer_.reset(); 650#if defined(OS_WIN) 651 child_window_observer_.reset(); 652#endif 653 // Window needs a valid delegate during its destructor, so we explicitly 654 // delete it here. 655 window_.reset(); 656} 657 658void WebContentsViewAura::SetupOverlayWindowForTesting() { 659 if (navigation_overlay_) 660 navigation_overlay_->SetupForTesting(); 661} 662 663void WebContentsViewAura::SetTouchEditableForTest( 664 TouchEditableImplAura* touch_editable) { 665 touch_editable_.reset(touch_editable); 666 AttachTouchEditableToRenderView(); 667} 668 669void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) { 670 if (web_contents_->GetInterstitialPage()) 671 web_contents_->GetInterstitialPage()->SetSize(size); 672 RenderWidgetHostView* rwhv = 673 web_contents_->GetRenderWidgetHostView(); 674 if (rwhv) 675 rwhv->SetSize(size); 676} 677 678void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) { 679 aura::RootWindow* root_window = GetNativeView()->GetRootWindow(); 680 gfx::Point screen_loc = 681 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 682 gfx::Point client_loc = screen_loc; 683 RenderViewHost* rvh = web_contents_->GetRenderViewHost(); 684 aura::Window* window = rvh->GetView()->GetNativeView(); 685 aura::Window::ConvertPointToTarget(root_window, window, &client_loc); 686 if (!web_contents_) 687 return; 688 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(), 689 screen_loc.x(), screen_loc.y(), ops); 690} 691 692void WebContentsViewAura::PrepareOverscrollWindow() { 693 // If there is an existing |overscroll_window_| which is in the middle of an 694 // animation, then destroying the window here causes the animation to be 695 // completed immidiately, which triggers |OnImplicitAnimationsCompleted()| 696 // callback, and that tries to reset |overscroll_window_| again, causing a 697 // double-free. So use a temporary variable here. 698 if (overscroll_window_) { 699 base::AutoReset<OverscrollMode> reset_state(¤t_overscroll_gesture_, 700 current_overscroll_gesture_); 701 scoped_ptr<aura::Window> reset_window(overscroll_window_.release()); 702 } 703 704 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate( 705 web_contents_, 706 current_overscroll_gesture_); 707 overscroll_window_.reset(new aura::Window(overscroll_delegate)); 708 overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL); 709 overscroll_window_->SetTransparent(true); 710 overscroll_window_->Init(ui::LAYER_TEXTURED); 711 overscroll_window_->layer()->SetMasksToBounds(false); 712 overscroll_window_->SetName("OverscrollOverlay"); 713 714 overscroll_change_brightness_ = overscroll_delegate->has_image(); 715 window_->AddChild(overscroll_window_.get()); 716 717 gfx::Rect bounds = gfx::Rect(window_->bounds().size()); 718 if (ShouldNavigateForward(web_contents_->GetController(), 719 current_overscroll_gesture_)) { 720 // The overlay will be sliding in from the right edge towards the left in 721 // non-RTL, or sliding in from the left edge towards the right in RTL. 722 // So position the overlay window accordingly. 723 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0); 724 } 725 726 aura::Window* animate_window = GetWindowToAnimateForOverscroll(); 727 if (animate_window == overscroll_window_) 728 window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView()); 729 else 730 window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView()); 731 732 UpdateOverscrollWindowBrightness(0.f); 733 734 overscroll_window_->SetBounds(bounds); 735 overscroll_window_->Show(); 736 737 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window)); 738} 739 740void WebContentsViewAura::PrepareContentWindowForOverscroll() { 741 aura::Window* content = GetContentNativeView(); 742 ui::ScopedLayerAnimationSettings settings(content->layer()->GetAnimator()); 743 settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); 744 content->SetTransform(gfx::Transform()); 745 content->layer()->SetLayerBrightness(0.f); 746} 747 748void WebContentsViewAura::ResetOverscrollTransform() { 749 if (!web_contents_->GetRenderWidgetHostView()) 750 return; 751 aura::Window* target = GetWindowToAnimateForOverscroll(); 752 if (!target) 753 return; 754 { 755 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 756 settings.SetPreemptionStrategy( 757 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 758 settings.SetTweenType(ui::Tween::EASE_OUT); 759 settings.AddObserver(this); 760 target->SetTransform(gfx::Transform()); 761 } 762 { 763 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 764 settings.SetPreemptionStrategy( 765 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 766 settings.SetTweenType(ui::Tween::EASE_OUT); 767 UpdateOverscrollWindowBrightness(0.f); 768 } 769} 770 771void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) { 772 if (!web_contents_->GetRenderWidgetHostView()) 773 return; 774 775 // Animate out the current view first. Navigate to the requested history at 776 // the end of the animation. 777 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 778 return; 779 780 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated", 781 current_overscroll_gesture_, OVERSCROLL_COUNT); 782 783 completed_overscroll_gesture_ = mode; 784 aura::Window* target = GetWindowToAnimateForOverscroll(); 785 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 786 settings.SetPreemptionStrategy( 787 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 788 settings.SetTweenType(ui::Tween::EASE_OUT); 789 settings.AddObserver(this); 790 gfx::Transform transform; 791 int content_width = 792 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width(); 793 int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width; 794 transform.Translate(translate_x, 0); 795 target->SetTransform(transform); 796 UpdateOverscrollWindowBrightness(translate_x); 797} 798 799aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() { 800 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 801 return NULL; 802 803 return ShouldNavigateForward(web_contents_->GetController(), 804 current_overscroll_gesture_) ? 805 overscroll_window_.get() : GetContentNativeView(); 806} 807 808gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x, 809 int delta_y) { 810 if (current_overscroll_gesture_ == OVERSCROLL_NORTH || 811 current_overscroll_gesture_ == OVERSCROLL_SOUTH) { 812 // Ignore vertical overscroll. 813 return gfx::Vector2d(); 814 } 815 816 // For horizontal overscroll, scroll freely if a navigation is possible. Do a 817 // resistive scroll otherwise. 818 const NavigationControllerImpl& controller = web_contents_->GetController(); 819 const gfx::Rect& bounds = GetViewBounds(); 820 if (ShouldNavigateForward(controller, current_overscroll_gesture_)) 821 return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0); 822 else if (ShouldNavigateBack(controller, current_overscroll_gesture_)) 823 return gfx::Vector2d(std::min(bounds.width(), delta_x), 0); 824 825 return gfx::Vector2d(); 826} 827 828void WebContentsViewAura::PrepareOverscrollNavigationOverlay() { 829 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>( 830 overscroll_window_->delegate()); 831 delegate->stop_forwarding_events(); 832 overscroll_window_->SchedulePaintInRect( 833 gfx::Rect(overscroll_window_->bounds().size())); 834 navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(), 835 delegate->has_image()); 836 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura( 837 web_contents_->GetRenderWidgetHostView())); 838} 839 840void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) { 841 if (!overscroll_change_brightness_) 842 return; 843 844 const float kBrightnessMin = -.1f; 845 const float kBrightnessMax = -.01f; 846 847 float ratio = fabs(delta_x) / GetViewBounds().width(); 848 ratio = std::min(1.f, ratio); 849 if (base::i18n::IsRTL()) 850 ratio = 1.f - ratio; 851 float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ? 852 kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) : 853 kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin); 854 brightness = std::max(kBrightnessMin, brightness); 855 brightness = std::min(kBrightnessMax, brightness); 856 aura::Window* window = GetWindowToAnimateForOverscroll(); 857 window->layer()->SetLayerBrightness(brightness); 858} 859 860void WebContentsViewAura::AttachTouchEditableToRenderView() { 861 if (!touch_editable_) 862 return; 863 RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura( 864 web_contents_->GetRenderWidgetHostView()); 865 touch_editable_->AttachToView(rwhva); 866} 867 868//////////////////////////////////////////////////////////////////////////////// 869// WebContentsViewAura, WebContentsView implementation: 870 871gfx::NativeView WebContentsViewAura::GetNativeView() const { 872 return window_.get(); 873} 874 875gfx::NativeView WebContentsViewAura::GetContentNativeView() const { 876 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 877 return rwhv ? rwhv->GetNativeView() : NULL; 878} 879 880gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const { 881 return window_->GetToplevelWindow(); 882} 883 884void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const { 885 *out = window_->GetBoundsInScreen(); 886} 887 888void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status, 889 int error_code) { 890 // Set the focus to the parent because neither the view window nor this 891 // window can handle key events. 892 if (window_->HasFocus() && window_->parent()) 893 window_->parent()->Focus(); 894} 895 896void WebContentsViewAura::SizeContents(const gfx::Size& size) { 897 gfx::Rect bounds = window_->bounds(); 898 if (bounds.size() != size) { 899 bounds.set_size(size); 900 window_->SetBounds(bounds); 901 } else { 902 // Our size matches what we want but the renderers size may not match. 903 // Pretend we were resized so that the renderers size is updated too. 904 SizeChangedCommon(size); 905 } 906} 907 908void WebContentsViewAura::Focus() { 909 if (web_contents_->GetInterstitialPage()) { 910 web_contents_->GetInterstitialPage()->Focus(); 911 return; 912 } 913 914 if (delegate_.get() && delegate_->Focus()) 915 return; 916 917 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 918 if (rwhv) 919 rwhv->Focus(); 920} 921 922void WebContentsViewAura::SetInitialFocus() { 923 if (web_contents_->FocusLocationBarByDefault()) 924 web_contents_->SetFocusToLocationBar(false); 925 else 926 Focus(); 927} 928 929void WebContentsViewAura::StoreFocus() { 930 if (delegate_) 931 delegate_->StoreFocus(); 932} 933 934void WebContentsViewAura::RestoreFocus() { 935 if (delegate_) 936 delegate_->RestoreFocus(); 937} 938 939WebDropData* WebContentsViewAura::GetDropData() const { 940 return current_drop_data_.get(); 941} 942 943gfx::Rect WebContentsViewAura::GetViewBounds() const { 944 return window_->GetBoundsInScreen(); 945} 946 947//////////////////////////////////////////////////////////////////////////////// 948// WebContentsViewAura, WebContentsViewPort implementation: 949 950void WebContentsViewAura::CreateView( 951 const gfx::Size& initial_size, gfx::NativeView context) { 952 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as 953 // if the bookmark bar is not shown and you create a new tab). The right 954 // value is set shortly after this, so its safe to ignore. 955 956 window_.reset(new aura::Window(this)); 957 window_->set_owned_by_parent(false); 958 window_->SetType(aura::client::WINDOW_TYPE_CONTROL); 959 window_->SetTransparent(false); 960 window_->Init(ui::LAYER_NOT_DRAWN); 961 aura::RootWindow* root_window = context ? context->GetRootWindow() : NULL; 962 if (root_window) { 963 // There are places where there is no context currently because object 964 // hierarchies are built before they're attached to a Widget. (See 965 // views::WebView as an example; GetWidget() returns NULL at the point 966 // where we are created.) 967 // 968 // It should be OK to not set a default parent since such users will 969 // explicitly add this WebContentsViewAura to their tree after they create 970 // us. 971 if (root_window) { 972 window_->SetDefaultParentByRootWindow( 973 root_window, root_window->GetBoundsInScreen()); 974 } 975 } 976 window_->layer()->SetMasksToBounds(true); 977 window_->SetName("WebContentsViewAura"); 978 979 window_observer_.reset(new WindowObserver(this)); 980#if defined(OS_WIN) 981 child_window_observer_.reset(new ChildWindowObserver(this)); 982#endif 983 984 // delegate_->GetDragDestDelegate() creates a new delegate on every call. 985 // Hence, we save a reference to it locally. Similar model is used on other 986 // platforms as well. 987 if (delegate_) 988 drag_dest_delegate_ = delegate_->GetDragDestDelegate(); 989} 990 991RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget( 992 RenderWidgetHost* render_widget_host) { 993 if (render_widget_host->GetView()) { 994 // During testing, the view will already be set up in most cases to the 995 // test view, so we don't want to clobber it with a real one. To verify that 996 // this actually is happening (and somebody isn't accidentally creating the 997 // view twice), we check for the RVH Factory, which will be set when we're 998 // making special ones (which go along with the special views). 999 DCHECK(RenderViewHostFactory::has_factory()); 1000 return render_widget_host->GetView(); 1001 } 1002 1003 RenderWidgetHostView* view = 1004 RenderWidgetHostView::CreateViewForWidget(render_widget_host); 1005 view->InitAsChild(NULL); 1006 GetNativeView()->AddChild(view->GetNativeView()); 1007 1008 if (navigation_overlay_.get() && navigation_overlay_->has_window()) { 1009 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view)); 1010 } 1011 1012 view->Show(); 1013 1014 // We listen to drag drop events in the newly created view's window. 1015 aura::client::SetDragDropDelegate(view->GetNativeView(), this); 1016 1017 RenderWidgetHostImpl* host_impl = 1018 RenderWidgetHostImpl::From(render_widget_host); 1019 if (host_impl->overscroll_controller() && 1020 (!web_contents_->GetDelegate() || 1021 web_contents_->GetDelegate()->CanOverscrollContent())) { 1022 host_impl->overscroll_controller()->set_delegate(this); 1023 if (!navigation_overlay_) 1024 navigation_overlay_.reset(new OverscrollNavigationOverlay()); 1025 } 1026 1027 AttachTouchEditableToRenderView(); 1028 return view; 1029} 1030 1031RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget( 1032 RenderWidgetHost* render_widget_host) { 1033 return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); 1034} 1035 1036void WebContentsViewAura::SetPageTitle(const string16& title) { 1037 window_->set_title(title); 1038} 1039 1040void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) { 1041} 1042 1043void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) { 1044 if (navigation_overlay_.get() && navigation_overlay_->has_window()) { 1045 navigation_overlay_->StartObservingView( 1046 ToRenderWidgetHostViewAura(host->GetView())); 1047 } 1048 AttachTouchEditableToRenderView(); 1049} 1050 1051void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) { 1052 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>( 1053 web_contents_->GetRenderViewHost()); 1054 if (host) { 1055 host->SetOverscrollControllerEnabled(enabled); 1056 if (enabled) 1057 host->overscroll_controller()->set_delegate(this); 1058 } 1059} 1060 1061//////////////////////////////////////////////////////////////////////////////// 1062// WebContentsViewAura, RenderViewHostDelegateView implementation: 1063 1064void WebContentsViewAura::ShowContextMenu( 1065 const ContextMenuParams& params, 1066 ContextMenuSourceType type) { 1067 if (delegate_) 1068 delegate_->ShowContextMenu(params, type); 1069 if (touch_editable_) 1070 touch_editable_->EndTouchEditing(); 1071 1072} 1073 1074void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds, 1075 int item_height, 1076 double item_font_size, 1077 int selected_item, 1078 const std::vector<WebMenuItem>& items, 1079 bool right_aligned, 1080 bool allow_multiple_selection) { 1081 // External popup menus are only used on Mac and Android. 1082 NOTIMPLEMENTED(); 1083} 1084 1085void WebContentsViewAura::StartDragging( 1086 const WebDropData& drop_data, 1087 WebKit::WebDragOperationsMask operations, 1088 const gfx::ImageSkia& image, 1089 const gfx::Vector2d& image_offset, 1090 const DragEventSourceInfo& event_info) { 1091 aura::RootWindow* root_window = GetNativeView()->GetRootWindow(); 1092 if (!aura::client::GetDragDropClient(root_window)) { 1093 web_contents_->SystemDragEnded(); 1094 return; 1095 } 1096 1097 if (touch_editable_) 1098 touch_editable_->EndTouchEditing(); 1099 1100 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider(); 1101 PrepareDragData(drop_data, provider); 1102 1103 ui::OSExchangeData data(provider); // takes ownership of |provider|. 1104 1105 if (!image.isNull()) { 1106 drag_utils::SetDragImageOnDataObject(image, 1107 gfx::Size(image.width(), image.height()), image_offset, &data); 1108 } 1109 1110 scoped_ptr<WebDragSourceAura> drag_source( 1111 new WebDragSourceAura(GetNativeView(), web_contents_)); 1112 1113 // We need to enable recursive tasks on the message loop so we can get 1114 // updates while in the system DoDragDrop loop. 1115 int result_op = 0; 1116 { 1117 gfx::NativeView content_native_view = GetContentNativeView(); 1118 base::MessageLoop::ScopedNestableTaskAllower allow( 1119 base::MessageLoop::current()); 1120 result_op = aura::client::GetDragDropClient(root_window) 1121 ->StartDragAndDrop(data, 1122 root_window, 1123 content_native_view, 1124 event_info.event_location, 1125 ConvertFromWeb(operations), 1126 event_info.event_source); 1127 } 1128 1129 // Bail out immediately if the contents view window is gone. Note that it is 1130 // not safe to access any class members in this case since |this| may already 1131 // be destroyed. The local variable |drag_source| will still be valid though, 1132 // so we can use it to determine if the window is gone. 1133 if (!drag_source->window()) { 1134 // Note that in this case, we don't need to call SystemDragEnded() since the 1135 // renderer is going away. 1136 return; 1137 } 1138 1139 EndDrag(ConvertToWeb(result_op)); 1140 web_contents_->SystemDragEnded(); 1141} 1142 1143void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) { 1144 current_drag_op_ = operation; 1145} 1146 1147void WebContentsViewAura::GotFocus() { 1148 if (web_contents_->GetDelegate()) 1149 web_contents_->GetDelegate()->WebContentsFocused(web_contents_); 1150} 1151 1152void WebContentsViewAura::TakeFocus(bool reverse) { 1153 if (web_contents_->GetDelegate() && 1154 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) && 1155 delegate_.get()) { 1156 delegate_->TakeFocus(reverse); 1157 } 1158} 1159 1160//////////////////////////////////////////////////////////////////////////////// 1161// WebContentsViewAura, OverscrollControllerDelegate implementation: 1162 1163void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) { 1164 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 1165 return; 1166 1167 aura::Window* target = GetWindowToAnimateForOverscroll(); 1168 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 1169 settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); 1170 gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y); 1171 gfx::Transform transform; 1172 transform.Translate(translate.x(), translate.y()); 1173 target->SetTransform(transform); 1174 1175 UpdateOverscrollWindowBrightness(delta_x); 1176} 1177 1178void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) { 1179 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT); 1180 1181 NavigationControllerImpl& controller = web_contents_->GetController(); 1182 if (ShouldNavigateForward(controller, mode) || 1183 ShouldNavigateBack(controller, mode)) { 1184 CompleteOverscrollNavigation(mode); 1185 return; 1186 } 1187 1188 ResetOverscrollTransform(); 1189} 1190 1191void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode, 1192 OverscrollMode new_mode) { 1193 // Reset any in-progress overscroll animation first. 1194 ResetOverscrollTransform(); 1195 1196 if (new_mode == OVERSCROLL_NONE || 1197 !GetContentNativeView() || 1198 (navigation_overlay_.get() && navigation_overlay_->has_window())) { 1199 current_overscroll_gesture_ = OVERSCROLL_NONE; 1200 } else { 1201 // Cleanup state of the content window first, because that can reset the 1202 // value of |current_overscroll_gesture_|. 1203 PrepareContentWindowForOverscroll(); 1204 1205 current_overscroll_gesture_ = new_mode; 1206 PrepareOverscrollWindow(); 1207 1208 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT); 1209 } 1210 completed_overscroll_gesture_ = OVERSCROLL_NONE; 1211} 1212 1213//////////////////////////////////////////////////////////////////////////////// 1214// WebContentsViewAura, ui::ImplicitAnimationObserver implementation: 1215 1216void WebContentsViewAura::OnImplicitAnimationsCompleted() { 1217 overscroll_shadow_.reset(); 1218 1219 if (ShouldNavigateForward(web_contents_->GetController(), 1220 completed_overscroll_gesture_)) { 1221 PrepareOverscrollNavigationOverlay(); 1222 web_contents_->GetController().GoForward(); 1223 } else if (ShouldNavigateBack(web_contents_->GetController(), 1224 completed_overscroll_gesture_)) { 1225 PrepareOverscrollNavigationOverlay(); 1226 web_contents_->GetController().GoBack(); 1227 } 1228 1229 aura::Window* content = GetContentNativeView(); 1230 if (content) { 1231 content->SetTransform(gfx::Transform()); 1232 content->layer()->SetLayerBrightness(0.f); 1233 } 1234 current_overscroll_gesture_ = OVERSCROLL_NONE; 1235 completed_overscroll_gesture_ = OVERSCROLL_NONE; 1236 overscroll_window_.reset(); 1237} 1238 1239//////////////////////////////////////////////////////////////////////////////// 1240// WebContentsViewAura, aura::WindowDelegate implementation: 1241 1242gfx::Size WebContentsViewAura::GetMinimumSize() const { 1243 return gfx::Size(); 1244} 1245 1246gfx::Size WebContentsViewAura::GetMaximumSize() const { 1247 return gfx::Size(); 1248} 1249 1250void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds, 1251 const gfx::Rect& new_bounds) { 1252 SizeChangedCommon(new_bounds.size()); 1253 if (delegate_) 1254 delegate_->SizeChanged(new_bounds.size()); 1255 1256 // Constrained web dialogs, need to be kept centered over our content area. 1257 for (size_t i = 0; i < window_->children().size(); i++) { 1258 if (window_->children()[i]->GetProperty( 1259 aura::client::kConstrainedWindowKey)) { 1260 gfx::Rect bounds = window_->children()[i]->bounds(); 1261 bounds.set_origin( 1262 gfx::Point((new_bounds.width() - bounds.width()) / 2, 1263 (new_bounds.height() - bounds.height()) / 2)); 1264 window_->children()[i]->SetBounds(bounds); 1265 } 1266 } 1267} 1268 1269gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) { 1270 return gfx::kNullCursor; 1271} 1272 1273int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const { 1274 return HTCLIENT; 1275} 1276 1277bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling( 1278 aura::Window* child, 1279 const gfx::Point& location) { 1280 return true; 1281} 1282 1283bool WebContentsViewAura::CanFocus() { 1284 // Do not take the focus if the render widget host view is gone because 1285 // neither the view window nor this window can handle key events. 1286 return web_contents_->GetRenderWidgetHostView() != NULL; 1287} 1288 1289void WebContentsViewAura::OnCaptureLost() { 1290} 1291 1292void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) { 1293} 1294 1295void WebContentsViewAura::OnDeviceScaleFactorChanged( 1296 float device_scale_factor) { 1297} 1298 1299void WebContentsViewAura::OnWindowDestroying() { 1300 // This means the destructor is going to be called soon. If there is an 1301 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL), 1302 // then destroying it in the WebContentsViewAura destructor can trigger other 1303 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So 1304 // destroy the overscroll window here. 1305 navigation_overlay_.reset(); 1306 overscroll_window_.reset(); 1307} 1308 1309void WebContentsViewAura::OnWindowDestroyed() { 1310} 1311 1312void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) { 1313 if (visible) 1314 web_contents_->WasShown(); 1315 else 1316 web_contents_->WasHidden(); 1317} 1318 1319bool WebContentsViewAura::HasHitTestMask() const { 1320 return false; 1321} 1322 1323void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const { 1324} 1325 1326scoped_refptr<ui::Texture> WebContentsViewAura::CopyTexture() { 1327 // The layer we create doesn't have an external texture, so this should never 1328 // get invoked. 1329 NOTREACHED(); 1330 return scoped_refptr<ui::Texture>(); 1331} 1332 1333//////////////////////////////////////////////////////////////////////////////// 1334// WebContentsViewAura, ui::EventHandler implementation: 1335 1336void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) { 1337} 1338 1339void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) { 1340 if (!web_contents_->GetDelegate()) 1341 return; 1342 1343 switch (event->type()) { 1344 case ui::ET_MOUSE_PRESSED: 1345 web_contents_->GetDelegate()->ActivateContents(web_contents_); 1346 break; 1347 case ui::ET_MOUSE_MOVED: 1348 web_contents_->GetDelegate()->ContentsMouseEvent( 1349 web_contents_, 1350 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(), 1351 true); 1352 break; 1353 default: 1354 break; 1355 } 1356} 1357 1358//////////////////////////////////////////////////////////////////////////////// 1359// WebContentsViewAura, aura::client::DragDropDelegate implementation: 1360 1361void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) { 1362 if (drag_dest_delegate_) 1363 drag_dest_delegate_->DragInitialize(web_contents_); 1364 1365 current_drop_data_.reset(new WebDropData()); 1366 1367 PrepareWebDropData(current_drop_data_.get(), event.data()); 1368 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); 1369 1370 gfx::Point screen_pt = 1371 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 1372 current_rvh_for_drag_ = web_contents_->GetRenderViewHost(); 1373 web_contents_->GetRenderViewHost()->DragTargetDragEnter( 1374 *current_drop_data_.get(), event.location(), screen_pt, op, 1375 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1376 1377 if (drag_dest_delegate_) { 1378 drag_dest_delegate_->OnReceiveDragData(event.data()); 1379 drag_dest_delegate_->OnDragEnter(); 1380 } 1381} 1382 1383int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) { 1384 DCHECK(current_rvh_for_drag_); 1385 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1386 OnDragEntered(event); 1387 1388 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); 1389 gfx::Point screen_pt = 1390 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 1391 web_contents_->GetRenderViewHost()->DragTargetDragOver( 1392 event.location(), screen_pt, op, 1393 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1394 1395 if (drag_dest_delegate_) 1396 drag_dest_delegate_->OnDragOver(); 1397 1398 return ConvertFromWeb(current_drag_op_); 1399} 1400 1401void WebContentsViewAura::OnDragExited() { 1402 DCHECK(current_rvh_for_drag_); 1403 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1404 return; 1405 1406 web_contents_->GetRenderViewHost()->DragTargetDragLeave(); 1407 if (drag_dest_delegate_) 1408 drag_dest_delegate_->OnDragLeave(); 1409 1410 current_drop_data_.reset(); 1411} 1412 1413int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) { 1414 DCHECK(current_rvh_for_drag_); 1415 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1416 OnDragEntered(event); 1417 1418 web_contents_->GetRenderViewHost()->DragTargetDrop( 1419 event.location(), 1420 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(), 1421 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1422 if (drag_dest_delegate_) 1423 drag_dest_delegate_->OnDrop(); 1424 current_drop_data_.reset(); 1425 return current_drag_op_; 1426} 1427 1428} // namespace content 1429