web_contents_view_aura.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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 StopObservingImplicitAnimations(); 742 aura::Window* content = GetContentNativeView(); 743 content->layer()->GetAnimator()->AbortAllAnimations(); 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 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>( 783 overscroll_window_->delegate()); 784 delegate->stop_forwarding_events(); 785 786 completed_overscroll_gesture_ = mode; 787 aura::Window* target = GetWindowToAnimateForOverscroll(); 788 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 789 settings.SetPreemptionStrategy( 790 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 791 settings.SetTweenType(ui::Tween::EASE_OUT); 792 settings.AddObserver(this); 793 gfx::Transform transform; 794 int content_width = 795 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width(); 796 int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width; 797 transform.Translate(translate_x, 0); 798 target->SetTransform(transform); 799 UpdateOverscrollWindowBrightness(translate_x); 800} 801 802aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() { 803 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 804 return NULL; 805 806 return ShouldNavigateForward(web_contents_->GetController(), 807 current_overscroll_gesture_) ? 808 overscroll_window_.get() : GetContentNativeView(); 809} 810 811gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x, 812 int delta_y) { 813 if (current_overscroll_gesture_ == OVERSCROLL_NORTH || 814 current_overscroll_gesture_ == OVERSCROLL_SOUTH) { 815 // Ignore vertical overscroll. 816 return gfx::Vector2d(); 817 } 818 819 // For horizontal overscroll, scroll freely if a navigation is possible. Do a 820 // resistive scroll otherwise. 821 const NavigationControllerImpl& controller = web_contents_->GetController(); 822 const gfx::Rect& bounds = GetViewBounds(); 823 if (ShouldNavigateForward(controller, current_overscroll_gesture_)) 824 return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0); 825 else if (ShouldNavigateBack(controller, current_overscroll_gesture_)) 826 return gfx::Vector2d(std::min(bounds.width(), delta_x), 0); 827 828 return gfx::Vector2d(); 829} 830 831void WebContentsViewAura::PrepareOverscrollNavigationOverlay() { 832 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>( 833 overscroll_window_->delegate()); 834 overscroll_window_->SchedulePaintInRect( 835 gfx::Rect(overscroll_window_->bounds().size())); 836 navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(), 837 delegate->has_image()); 838 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura( 839 web_contents_->GetRenderWidgetHostView())); 840} 841 842void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) { 843 if (!overscroll_change_brightness_) 844 return; 845 846 const float kBrightnessMin = -.1f; 847 const float kBrightnessMax = -.01f; 848 849 float ratio = fabs(delta_x) / GetViewBounds().width(); 850 ratio = std::min(1.f, ratio); 851 if (base::i18n::IsRTL()) 852 ratio = 1.f - ratio; 853 float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ? 854 kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) : 855 kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin); 856 brightness = std::max(kBrightnessMin, brightness); 857 brightness = std::min(kBrightnessMax, brightness); 858 aura::Window* window = GetWindowToAnimateForOverscroll(); 859 window->layer()->SetLayerBrightness(brightness); 860} 861 862void WebContentsViewAura::AttachTouchEditableToRenderView() { 863 if (!touch_editable_) 864 return; 865 RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura( 866 web_contents_->GetRenderWidgetHostView()); 867 touch_editable_->AttachToView(rwhva); 868} 869 870//////////////////////////////////////////////////////////////////////////////// 871// WebContentsViewAura, WebContentsView implementation: 872 873gfx::NativeView WebContentsViewAura::GetNativeView() const { 874 return window_.get(); 875} 876 877gfx::NativeView WebContentsViewAura::GetContentNativeView() const { 878 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 879 return rwhv ? rwhv->GetNativeView() : NULL; 880} 881 882gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const { 883 return window_->GetToplevelWindow(); 884} 885 886void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const { 887 *out = window_->GetBoundsInScreen(); 888} 889 890void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status, 891 int error_code) { 892 // Set the focus to the parent because neither the view window nor this 893 // window can handle key events. 894 if (window_->HasFocus() && window_->parent()) 895 window_->parent()->Focus(); 896} 897 898void WebContentsViewAura::SizeContents(const gfx::Size& size) { 899 gfx::Rect bounds = window_->bounds(); 900 if (bounds.size() != size) { 901 bounds.set_size(size); 902 window_->SetBounds(bounds); 903 } else { 904 // Our size matches what we want but the renderers size may not match. 905 // Pretend we were resized so that the renderers size is updated too. 906 SizeChangedCommon(size); 907 } 908} 909 910void WebContentsViewAura::Focus() { 911 if (web_contents_->GetInterstitialPage()) { 912 web_contents_->GetInterstitialPage()->Focus(); 913 return; 914 } 915 916 if (delegate_.get() && delegate_->Focus()) 917 return; 918 919 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); 920 if (rwhv) 921 rwhv->Focus(); 922} 923 924void WebContentsViewAura::SetInitialFocus() { 925 if (web_contents_->FocusLocationBarByDefault()) 926 web_contents_->SetFocusToLocationBar(false); 927 else 928 Focus(); 929} 930 931void WebContentsViewAura::StoreFocus() { 932 if (delegate_) 933 delegate_->StoreFocus(); 934} 935 936void WebContentsViewAura::RestoreFocus() { 937 if (delegate_) 938 delegate_->RestoreFocus(); 939} 940 941WebDropData* WebContentsViewAura::GetDropData() const { 942 return current_drop_data_.get(); 943} 944 945gfx::Rect WebContentsViewAura::GetViewBounds() const { 946 return window_->GetBoundsInScreen(); 947} 948 949//////////////////////////////////////////////////////////////////////////////// 950// WebContentsViewAura, WebContentsViewPort implementation: 951 952void WebContentsViewAura::CreateView( 953 const gfx::Size& initial_size, gfx::NativeView context) { 954 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as 955 // if the bookmark bar is not shown and you create a new tab). The right 956 // value is set shortly after this, so its safe to ignore. 957 958 window_.reset(new aura::Window(this)); 959 window_->set_owned_by_parent(false); 960 window_->SetType(aura::client::WINDOW_TYPE_CONTROL); 961 window_->SetTransparent(false); 962 window_->Init(ui::LAYER_NOT_DRAWN); 963 aura::RootWindow* root_window = context ? context->GetRootWindow() : NULL; 964 if (root_window) { 965 // There are places where there is no context currently because object 966 // hierarchies are built before they're attached to a Widget. (See 967 // views::WebView as an example; GetWidget() returns NULL at the point 968 // where we are created.) 969 // 970 // It should be OK to not set a default parent since such users will 971 // explicitly add this WebContentsViewAura to their tree after they create 972 // us. 973 if (root_window) { 974 window_->SetDefaultParentByRootWindow( 975 root_window, root_window->GetBoundsInScreen()); 976 } 977 } 978 window_->layer()->SetMasksToBounds(true); 979 window_->SetName("WebContentsViewAura"); 980 981 window_observer_.reset(new WindowObserver(this)); 982#if defined(OS_WIN) 983 child_window_observer_.reset(new ChildWindowObserver(this)); 984#endif 985 986 // delegate_->GetDragDestDelegate() creates a new delegate on every call. 987 // Hence, we save a reference to it locally. Similar model is used on other 988 // platforms as well. 989 if (delegate_) 990 drag_dest_delegate_ = delegate_->GetDragDestDelegate(); 991} 992 993RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget( 994 RenderWidgetHost* render_widget_host) { 995 if (render_widget_host->GetView()) { 996 // During testing, the view will already be set up in most cases to the 997 // test view, so we don't want to clobber it with a real one. To verify that 998 // this actually is happening (and somebody isn't accidentally creating the 999 // view twice), we check for the RVH Factory, which will be set when we're 1000 // making special ones (which go along with the special views). 1001 DCHECK(RenderViewHostFactory::has_factory()); 1002 return render_widget_host->GetView(); 1003 } 1004 1005 RenderWidgetHostView* view = 1006 RenderWidgetHostView::CreateViewForWidget(render_widget_host); 1007 view->InitAsChild(NULL); 1008 GetNativeView()->AddChild(view->GetNativeView()); 1009 1010 if (navigation_overlay_.get() && navigation_overlay_->has_window()) { 1011 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view)); 1012 } 1013 1014 view->Show(); 1015 1016 // We listen to drag drop events in the newly created view's window. 1017 aura::client::SetDragDropDelegate(view->GetNativeView(), this); 1018 1019 RenderWidgetHostImpl* host_impl = 1020 RenderWidgetHostImpl::From(render_widget_host); 1021 if (host_impl->overscroll_controller() && 1022 (!web_contents_->GetDelegate() || 1023 web_contents_->GetDelegate()->CanOverscrollContent())) { 1024 host_impl->overscroll_controller()->set_delegate(this); 1025 if (!navigation_overlay_) 1026 navigation_overlay_.reset(new OverscrollNavigationOverlay()); 1027 } 1028 1029 AttachTouchEditableToRenderView(); 1030 return view; 1031} 1032 1033RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget( 1034 RenderWidgetHost* render_widget_host) { 1035 return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); 1036} 1037 1038void WebContentsViewAura::SetPageTitle(const string16& title) { 1039 window_->set_title(title); 1040} 1041 1042void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) { 1043} 1044 1045void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) { 1046 if (navigation_overlay_.get() && navigation_overlay_->has_window()) { 1047 navigation_overlay_->StartObservingView( 1048 ToRenderWidgetHostViewAura(host->GetView())); 1049 } 1050 AttachTouchEditableToRenderView(); 1051} 1052 1053void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) { 1054 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>( 1055 web_contents_->GetRenderViewHost()); 1056 if (host) { 1057 host->SetOverscrollControllerEnabled(enabled); 1058 if (enabled) 1059 host->overscroll_controller()->set_delegate(this); 1060 } 1061} 1062 1063//////////////////////////////////////////////////////////////////////////////// 1064// WebContentsViewAura, RenderViewHostDelegateView implementation: 1065 1066void WebContentsViewAura::ShowContextMenu( 1067 const ContextMenuParams& params, 1068 ContextMenuSourceType type) { 1069 if (delegate_) 1070 delegate_->ShowContextMenu(params, type); 1071 if (touch_editable_) 1072 touch_editable_->EndTouchEditing(); 1073 1074} 1075 1076void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds, 1077 int item_height, 1078 double item_font_size, 1079 int selected_item, 1080 const std::vector<WebMenuItem>& items, 1081 bool right_aligned, 1082 bool allow_multiple_selection) { 1083 // External popup menus are only used on Mac and Android. 1084 NOTIMPLEMENTED(); 1085} 1086 1087void WebContentsViewAura::StartDragging( 1088 const WebDropData& drop_data, 1089 WebKit::WebDragOperationsMask operations, 1090 const gfx::ImageSkia& image, 1091 const gfx::Vector2d& image_offset, 1092 const DragEventSourceInfo& event_info) { 1093 aura::RootWindow* root_window = GetNativeView()->GetRootWindow(); 1094 if (!aura::client::GetDragDropClient(root_window)) { 1095 web_contents_->SystemDragEnded(); 1096 return; 1097 } 1098 1099 if (touch_editable_) 1100 touch_editable_->EndTouchEditing(); 1101 1102 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider(); 1103 PrepareDragData(drop_data, provider); 1104 1105 ui::OSExchangeData data(provider); // takes ownership of |provider|. 1106 1107 if (!image.isNull()) { 1108 drag_utils::SetDragImageOnDataObject(image, 1109 gfx::Size(image.width(), image.height()), image_offset, &data); 1110 } 1111 1112 scoped_ptr<WebDragSourceAura> drag_source( 1113 new WebDragSourceAura(GetNativeView(), web_contents_)); 1114 1115 // We need to enable recursive tasks on the message loop so we can get 1116 // updates while in the system DoDragDrop loop. 1117 int result_op = 0; 1118 { 1119 gfx::NativeView content_native_view = GetContentNativeView(); 1120 base::MessageLoop::ScopedNestableTaskAllower allow( 1121 base::MessageLoop::current()); 1122 result_op = aura::client::GetDragDropClient(root_window) 1123 ->StartDragAndDrop(data, 1124 root_window, 1125 content_native_view, 1126 event_info.event_location, 1127 ConvertFromWeb(operations), 1128 event_info.event_source); 1129 } 1130 1131 // Bail out immediately if the contents view window is gone. Note that it is 1132 // not safe to access any class members in this case since |this| may already 1133 // be destroyed. The local variable |drag_source| will still be valid though, 1134 // so we can use it to determine if the window is gone. 1135 if (!drag_source->window()) { 1136 // Note that in this case, we don't need to call SystemDragEnded() since the 1137 // renderer is going away. 1138 return; 1139 } 1140 1141 EndDrag(ConvertToWeb(result_op)); 1142 web_contents_->SystemDragEnded(); 1143} 1144 1145void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) { 1146 current_drag_op_ = operation; 1147} 1148 1149void WebContentsViewAura::GotFocus() { 1150 if (web_contents_->GetDelegate()) 1151 web_contents_->GetDelegate()->WebContentsFocused(web_contents_); 1152} 1153 1154void WebContentsViewAura::TakeFocus(bool reverse) { 1155 if (web_contents_->GetDelegate() && 1156 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) && 1157 delegate_.get()) { 1158 delegate_->TakeFocus(reverse); 1159 } 1160} 1161 1162//////////////////////////////////////////////////////////////////////////////// 1163// WebContentsViewAura, OverscrollControllerDelegate implementation: 1164 1165void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) { 1166 if (current_overscroll_gesture_ == OVERSCROLL_NONE) 1167 return; 1168 1169 aura::Window* target = GetWindowToAnimateForOverscroll(); 1170 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); 1171 settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); 1172 gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y); 1173 gfx::Transform transform; 1174 transform.Translate(translate.x(), translate.y()); 1175 target->SetTransform(transform); 1176 1177 UpdateOverscrollWindowBrightness(delta_x); 1178} 1179 1180void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) { 1181 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT); 1182 1183 NavigationControllerImpl& controller = web_contents_->GetController(); 1184 if (ShouldNavigateForward(controller, mode) || 1185 ShouldNavigateBack(controller, mode)) { 1186 CompleteOverscrollNavigation(mode); 1187 return; 1188 } 1189 1190 ResetOverscrollTransform(); 1191} 1192 1193void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode, 1194 OverscrollMode new_mode) { 1195 // Reset any in-progress overscroll animation first. 1196 ResetOverscrollTransform(); 1197 1198 if (new_mode == OVERSCROLL_NONE || 1199 !GetContentNativeView() || 1200 (navigation_overlay_.get() && navigation_overlay_->has_window())) { 1201 current_overscroll_gesture_ = OVERSCROLL_NONE; 1202 } else { 1203 aura::Window* target = GetWindowToAnimateForOverscroll(); 1204 if (target) { 1205 StopObservingImplicitAnimations(); 1206 target->layer()->GetAnimator()->AbortAllAnimations(); 1207 } 1208 // Cleanup state of the content window first, because that can reset the 1209 // value of |current_overscroll_gesture_|. 1210 PrepareContentWindowForOverscroll(); 1211 1212 current_overscroll_gesture_ = new_mode; 1213 PrepareOverscrollWindow(); 1214 1215 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT); 1216 } 1217 completed_overscroll_gesture_ = OVERSCROLL_NONE; 1218} 1219 1220//////////////////////////////////////////////////////////////////////////////// 1221// WebContentsViewAura, ui::ImplicitAnimationObserver implementation: 1222 1223void WebContentsViewAura::OnImplicitAnimationsCompleted() { 1224 overscroll_shadow_.reset(); 1225 1226 if (ShouldNavigateForward(web_contents_->GetController(), 1227 completed_overscroll_gesture_)) { 1228 PrepareOverscrollNavigationOverlay(); 1229 web_contents_->GetController().GoForward(); 1230 } else if (ShouldNavigateBack(web_contents_->GetController(), 1231 completed_overscroll_gesture_)) { 1232 PrepareOverscrollNavigationOverlay(); 1233 web_contents_->GetController().GoBack(); 1234 } 1235 1236 aura::Window* content = GetContentNativeView(); 1237 if (content) { 1238 content->SetTransform(gfx::Transform()); 1239 content->layer()->SetLayerBrightness(0.f); 1240 } 1241 current_overscroll_gesture_ = OVERSCROLL_NONE; 1242 completed_overscroll_gesture_ = OVERSCROLL_NONE; 1243 overscroll_window_.reset(); 1244} 1245 1246//////////////////////////////////////////////////////////////////////////////// 1247// WebContentsViewAura, aura::WindowDelegate implementation: 1248 1249gfx::Size WebContentsViewAura::GetMinimumSize() const { 1250 return gfx::Size(); 1251} 1252 1253gfx::Size WebContentsViewAura::GetMaximumSize() const { 1254 return gfx::Size(); 1255} 1256 1257void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds, 1258 const gfx::Rect& new_bounds) { 1259 SizeChangedCommon(new_bounds.size()); 1260 if (delegate_) 1261 delegate_->SizeChanged(new_bounds.size()); 1262 1263 // Constrained web dialogs, need to be kept centered over our content area. 1264 for (size_t i = 0; i < window_->children().size(); i++) { 1265 if (window_->children()[i]->GetProperty( 1266 aura::client::kConstrainedWindowKey)) { 1267 gfx::Rect bounds = window_->children()[i]->bounds(); 1268 bounds.set_origin( 1269 gfx::Point((new_bounds.width() - bounds.width()) / 2, 1270 (new_bounds.height() - bounds.height()) / 2)); 1271 window_->children()[i]->SetBounds(bounds); 1272 } 1273 } 1274} 1275 1276gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) { 1277 return gfx::kNullCursor; 1278} 1279 1280int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const { 1281 return HTCLIENT; 1282} 1283 1284bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling( 1285 aura::Window* child, 1286 const gfx::Point& location) { 1287 return true; 1288} 1289 1290bool WebContentsViewAura::CanFocus() { 1291 // Do not take the focus if the render widget host view is gone because 1292 // neither the view window nor this window can handle key events. 1293 return web_contents_->GetRenderWidgetHostView() != NULL; 1294} 1295 1296void WebContentsViewAura::OnCaptureLost() { 1297} 1298 1299void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) { 1300} 1301 1302void WebContentsViewAura::OnDeviceScaleFactorChanged( 1303 float device_scale_factor) { 1304} 1305 1306void WebContentsViewAura::OnWindowDestroying() { 1307 // This means the destructor is going to be called soon. If there is an 1308 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL), 1309 // then destroying it in the WebContentsViewAura destructor can trigger other 1310 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So 1311 // destroy the overscroll window here. 1312 navigation_overlay_.reset(); 1313 overscroll_window_.reset(); 1314} 1315 1316void WebContentsViewAura::OnWindowDestroyed() { 1317} 1318 1319void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) { 1320 if (visible) 1321 web_contents_->WasShown(); 1322 else 1323 web_contents_->WasHidden(); 1324} 1325 1326bool WebContentsViewAura::HasHitTestMask() const { 1327 return false; 1328} 1329 1330void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const { 1331} 1332 1333scoped_refptr<ui::Texture> WebContentsViewAura::CopyTexture() { 1334 // The layer we create doesn't have an external texture, so this should never 1335 // get invoked. 1336 NOTREACHED(); 1337 return scoped_refptr<ui::Texture>(); 1338} 1339 1340//////////////////////////////////////////////////////////////////////////////// 1341// WebContentsViewAura, ui::EventHandler implementation: 1342 1343void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) { 1344} 1345 1346void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) { 1347 if (!web_contents_->GetDelegate()) 1348 return; 1349 1350 switch (event->type()) { 1351 case ui::ET_MOUSE_PRESSED: 1352 web_contents_->GetDelegate()->ActivateContents(web_contents_); 1353 break; 1354 case ui::ET_MOUSE_MOVED: 1355 web_contents_->GetDelegate()->ContentsMouseEvent( 1356 web_contents_, 1357 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(), 1358 true); 1359 break; 1360 default: 1361 break; 1362 } 1363} 1364 1365//////////////////////////////////////////////////////////////////////////////// 1366// WebContentsViewAura, aura::client::DragDropDelegate implementation: 1367 1368void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) { 1369 if (drag_dest_delegate_) 1370 drag_dest_delegate_->DragInitialize(web_contents_); 1371 1372 current_drop_data_.reset(new WebDropData()); 1373 1374 PrepareWebDropData(current_drop_data_.get(), event.data()); 1375 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); 1376 1377 gfx::Point screen_pt = 1378 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 1379 current_rvh_for_drag_ = web_contents_->GetRenderViewHost(); 1380 web_contents_->GetRenderViewHost()->DragTargetDragEnter( 1381 *current_drop_data_.get(), event.location(), screen_pt, op, 1382 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1383 1384 if (drag_dest_delegate_) { 1385 drag_dest_delegate_->OnReceiveDragData(event.data()); 1386 drag_dest_delegate_->OnDragEnter(); 1387 } 1388} 1389 1390int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) { 1391 DCHECK(current_rvh_for_drag_); 1392 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1393 OnDragEntered(event); 1394 1395 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); 1396 gfx::Point screen_pt = 1397 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 1398 web_contents_->GetRenderViewHost()->DragTargetDragOver( 1399 event.location(), screen_pt, op, 1400 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1401 1402 if (drag_dest_delegate_) 1403 drag_dest_delegate_->OnDragOver(); 1404 1405 return ConvertFromWeb(current_drag_op_); 1406} 1407 1408void WebContentsViewAura::OnDragExited() { 1409 DCHECK(current_rvh_for_drag_); 1410 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1411 return; 1412 1413 web_contents_->GetRenderViewHost()->DragTargetDragLeave(); 1414 if (drag_dest_delegate_) 1415 drag_dest_delegate_->OnDragLeave(); 1416 1417 current_drop_data_.reset(); 1418} 1419 1420int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) { 1421 DCHECK(current_rvh_for_drag_); 1422 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost()) 1423 OnDragEntered(event); 1424 1425 web_contents_->GetRenderViewHost()->DragTargetDrop( 1426 event.location(), 1427 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(), 1428 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 1429 if (drag_dest_delegate_) 1430 drag_dest_delegate_->OnDrop(); 1431 current_drop_data_.reset(); 1432 return current_drag_op_; 1433} 1434 1435} // namespace content 1436