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