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.
5 #include "content/browser/web_contents/web_contents_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/files/file_util.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_guest.h"
13 #include "content/browser/download/drag_download_util.h"
14 #include "content/browser/frame_host/interstitial_page_impl.h"
15 #include "content/browser/frame_host/navigation_entry_impl.h"
16 #include "content/browser/renderer_host/dip_util.h"
17 #include "content/browser/renderer_host/overscroll_controller.h"
18 #include "content/browser/renderer_host/render_view_host_factory.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
22 #include "content/browser/renderer_host/web_input_event_aura.h"
23 #include "content/browser/web_contents/aura/gesture_nav_simple.h"
24 #include "content/browser/web_contents/aura/image_window_delegate.h"
25 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
26 #include "content/browser/web_contents/aura/shadow_layer_delegate.h"
27 #include "content/browser/web_contents/aura/window_slider.h"
28 #include "content/browser/web_contents/touch_editable_impl_aura.h"
29 #include "content/browser/web_contents/web_contents_impl.h"
30 #include "content/public/browser/content_browser_client.h"
31 #include "content/public/browser/notification_observer.h"
32 #include "content/public/browser/notification_registrar.h"
33 #include "content/public/browser/notification_source.h"
34 #include "content/public/browser/notification_types.h"
35 #include "content/public/browser/overscroll_configuration.h"
36 #include "content/public/browser/render_view_host.h"
37 #include "content/public/browser/render_widget_host.h"
38 #include "content/public/browser/render_widget_host_view.h"
39 #include "content/public/browser/web_contents_delegate.h"
40 #include "content/public/browser/web_contents_observer.h"
41 #include "content/public/browser/web_contents_view_delegate.h"
42 #include "content/public/browser/web_drag_dest_delegate.h"
43 #include "content/public/common/content_client.h"
44 #include "content/public/common/content_switches.h"
45 #include "content/public/common/drop_data.h"
46 #include "net/base/filename_util.h"
47 #include "third_party/WebKit/public/web/WebInputEvent.h"
48 #include "ui/aura/client/aura_constants.h"
49 #include "ui/aura/client/window_tree_client.h"
50 #include "ui/aura/env.h"
51 #include "ui/aura/window.h"
52 #include "ui/aura/window_observer.h"
53 #include "ui/aura/window_tree_host.h"
54 #include "ui/aura/window_tree_host_observer.h"
55 #include "ui/base/clipboard/clipboard.h"
56 #include "ui/base/clipboard/custom_data_helper.h"
57 #include "ui/base/dragdrop/drag_drop_types.h"
58 #include "ui/base/dragdrop/drag_utils.h"
59 #include "ui/base/dragdrop/drop_target_event.h"
60 #include "ui/base/dragdrop/os_exchange_data.h"
61 #include "ui/base/hit_test.h"
62 #include "ui/compositor/layer.h"
63 #include "ui/compositor/scoped_layer_animation_settings.h"
64 #include "ui/events/event.h"
65 #include "ui/events/event_utils.h"
66 #include "ui/gfx/canvas.h"
67 #include "ui/gfx/image/image.h"
68 #include "ui/gfx/image/image_png_rep.h"
69 #include "ui/gfx/image/image_skia.h"
70 #include "ui/gfx/native_widget_types.h"
71 #include "ui/gfx/screen.h"
72 #include "ui/wm/public/drag_drop_client.h"
73 #include "ui/wm/public/drag_drop_delegate.h"
76 #include "content/browser/accessibility/browser_accessibility_manager.h"
77 #include "content/browser/accessibility/browser_accessibility_win.h"
78 #include "ui/base/win/hidden_window.h"
82 WebContentsView* CreateWebContentsView(
83 WebContentsImpl* web_contents,
84 WebContentsViewDelegate* delegate,
85 RenderViewHostDelegateView** render_view_host_delegate_view) {
86 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
87 *render_view_host_delegate_view = rv;
93 bool IsScrollEndEffectEnabled() {
94 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
95 switches::kScrollEndEffect) == "1";
98 bool ShouldNavigateForward(const NavigationController& controller,
99 OverscrollMode mode) {
100 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
101 controller.CanGoForward();
104 bool ShouldNavigateBack(const NavigationController& controller,
105 OverscrollMode mode) {
106 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
107 controller.CanGoBack();
110 RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
111 RenderWidgetHostView* view) {
112 if (!view || RenderViewHostFactory::has_factory())
113 return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests.
115 RenderViewHost* rvh = RenderViewHost::From(view->GetRenderWidgetHost());
116 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
117 rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
118 if (BrowserPluginGuest::IsGuest(web_contents))
120 return static_cast<RenderWidgetHostViewAura*>(view);
123 // The window delegate for the overscroll window. This redirects trackpad events
124 // to the web-contents window. The delegate destroys itself when the window is
126 class OverscrollWindowDelegate : public ImageWindowDelegate {
128 OverscrollWindowDelegate(WebContentsImpl* web_contents,
129 OverscrollMode overscroll_mode)
130 : web_contents_(web_contents),
131 forward_events_(true) {
132 const NavigationControllerImpl& controller = web_contents->GetController();
133 const NavigationEntryImpl* entry = NULL;
134 if (ShouldNavigateForward(controller, overscroll_mode)) {
135 entry = NavigationEntryImpl::FromNavigationEntry(
136 controller.GetEntryAtOffset(1));
137 } else if (ShouldNavigateBack(controller, overscroll_mode)) {
138 entry = NavigationEntryImpl::FromNavigationEntry(
139 controller.GetEntryAtOffset(-1));
143 if (entry && entry->screenshot().get()) {
144 std::vector<gfx::ImagePNGRep> image_reps;
145 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
146 image = gfx::Image(image_reps);
151 void stop_forwarding_events() { forward_events_ = false; }
154 ~OverscrollWindowDelegate() override {}
156 aura::Window* web_contents_window() {
157 return web_contents_->GetView()->GetContentNativeView();
160 // Overridden from ui::EventHandler.
161 void OnScrollEvent(ui::ScrollEvent* event) override {
162 if (forward_events_ && web_contents_window())
163 web_contents_window()->delegate()->OnScrollEvent(event);
166 void OnGestureEvent(ui::GestureEvent* event) override {
167 if (forward_events_ && web_contents_window())
168 web_contents_window()->delegate()->OnGestureEvent(event);
171 WebContentsImpl* web_contents_;
173 // The window is displayed both during the gesture, and after the gesture
174 // while the navigation is in progress. During the gesture, it is necessary to
175 // forward input events to the content page (e.g. when the overscroll window
176 // slides under the cursor and starts receiving scroll events). However, once
177 // the gesture is complete, and the window is being displayed as an overlay
178 // window during navigation, events should not be forwarded anymore.
179 bool forward_events_;
181 DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
184 // Listens to all mouse drag events during a drag and drop and sends them to
186 class WebDragSourceAura : public NotificationObserver {
188 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
190 contents_(contents) {
192 NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
193 Source<WebContents>(contents));
196 ~WebDragSourceAura() override {}
198 // NotificationObserver:
199 void Observe(int type,
200 const NotificationSource& source,
201 const NotificationDetails& details) override {
202 if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
205 // Cancel the drag if it is still in progress.
206 aura::client::DragDropClient* dnd_client =
207 aura::client::GetDragDropClient(window_->GetRootWindow());
208 if (dnd_client && dnd_client->IsDragDropInProgress())
209 dnd_client->DragCancel();
215 aura::Window* window() const { return window_; }
218 aura::Window* window_;
219 WebContentsImpl* contents_;
220 NotificationRegistrar registrar_;
222 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
225 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
226 // Fill out the OSExchangeData with a file contents, synthesizing a name if
228 void PrepareDragForFileContents(const DropData& drop_data,
229 ui::OSExchangeData::Provider* provider) {
230 base::FilePath file_name =
231 base::FilePath::FromUTF16Unsafe(drop_data.file_description_filename);
232 // Images without ALT text will only have a file extension so we need to
233 // synthesize one from the provided extension and URL.
234 if (file_name.BaseName().RemoveExtension().empty()) {
235 const base::FilePath::StringType extension = file_name.Extension();
236 // Retrieve the name from the URL.
237 file_name = net::GenerateFileName(drop_data.url, "", "", "", "", "")
238 .ReplaceExtension(extension);
240 provider->SetFileContents(file_name, drop_data.file_contents);
245 void PrepareDragForDownload(
246 const DropData& drop_data,
247 ui::OSExchangeData::Provider* provider,
248 WebContentsImpl* web_contents) {
249 const GURL& page_url = web_contents->GetLastCommittedURL();
250 const std::string& page_encoding = web_contents->GetEncoding();
252 // Parse the download metadata.
253 base::string16 mime_type;
254 base::FilePath file_name;
256 if (!ParseDownloadMetadata(drop_data.download_metadata,
262 // Generate the file name based on both mime type and proposed file name.
263 std::string default_name =
264 GetContentClient()->browser()->GetDefaultDownloadName();
265 base::FilePath generated_download_file_name =
266 net::GenerateFileName(download_url,
269 base::UTF16ToUTF8(file_name.value()),
270 base::UTF16ToUTF8(mime_type),
273 // http://crbug.com/332579
274 base::ThreadRestrictions::ScopedAllowIO allow_file_operations;
276 base::FilePath temp_dir_path;
277 if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
281 base::FilePath download_path =
282 temp_dir_path.Append(generated_download_file_name);
284 // We cannot know when the target application will be done using the temporary
285 // file, so schedule it to be deleted after rebooting.
286 base::DeleteFileAfterReboot(download_path);
287 base::DeleteFileAfterReboot(temp_dir_path);
289 // Provide the data as file (CF_HDROP). A temporary download file with the
290 // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
291 scoped_refptr<DragDownloadFile> download_file =
292 new DragDownloadFile(
296 Referrer(page_url, drop_data.referrer_policy),
299 ui::OSExchangeData::DownloadFileInfo file_download(base::FilePath(),
300 download_file.get());
301 provider->SetDownloadFileInfo(file_download);
303 #endif // defined(OS_WIN)
305 // Returns the CustomFormat to store file system files.
306 const ui::OSExchangeData::CustomFormat& GetFileSystemFileCustomFormat() {
307 static const char kFormatString[] = "chromium/x-file-system-files";
308 CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat,
310 (ui::Clipboard::GetFormatType(kFormatString)));
314 // Writes file system files to the pickle.
315 void WriteFileSystemFilesToPickle(
316 const std::vector<DropData::FileSystemFileInfo>& file_system_files,
318 pickle->WriteSizeT(file_system_files.size());
319 for (size_t i = 0; i < file_system_files.size(); ++i) {
320 pickle->WriteString(file_system_files[i].url.spec());
321 pickle->WriteInt64(file_system_files[i].size);
325 // Reads file system files from the pickle.
326 bool ReadFileSystemFilesFromPickle(
327 const Pickle& pickle,
328 std::vector<DropData::FileSystemFileInfo>* file_system_files) {
329 PickleIterator iter(pickle);
331 size_t num_files = 0;
332 if (!pickle.ReadSizeT(&iter, &num_files))
334 file_system_files->resize(num_files);
336 for (size_t i = 0; i < num_files; ++i) {
337 std::string url_string;
339 if (!pickle.ReadString(&iter, &url_string) ||
340 !pickle.ReadInt64(&iter, &size))
343 GURL url(url_string);
347 (*file_system_files)[i].url = url;
348 (*file_system_files)[i].size = size;
353 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
354 void PrepareDragData(const DropData& drop_data,
355 ui::OSExchangeData::Provider* provider,
356 WebContentsImpl* web_contents) {
357 provider->MarkOriginatedFromRenderer();
359 // Put download before file contents to prefer the download of a image over
360 // its thumbnail link.
361 if (!drop_data.download_metadata.empty())
362 PrepareDragForDownload(drop_data, provider, web_contents);
364 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
365 // We set the file contents before the URL because the URL also sets file
366 // contents (to a .URL shortcut). We want to prefer file content data over
367 // a shortcut so we add it first.
368 if (!drop_data.file_contents.empty())
369 PrepareDragForFileContents(drop_data, provider);
371 // Call SetString() before SetURL() when we actually have a custom string.
372 // SetURL() will itself do SetString() when a string hasn't been set yet,
373 // but we want to prefer drop_data.text.string() over the URL string if it
375 if (!drop_data.text.string().empty())
376 provider->SetString(drop_data.text.string());
377 if (drop_data.url.is_valid())
378 provider->SetURL(drop_data.url, drop_data.url_title);
379 if (!drop_data.html.string().empty())
380 provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
381 if (!drop_data.filenames.empty())
382 provider->SetFilenames(drop_data.filenames);
383 if (!drop_data.file_system_files.empty()) {
385 WriteFileSystemFilesToPickle(drop_data.file_system_files, &pickle);
386 provider->SetPickledData(GetFileSystemFileCustomFormat(), pickle);
388 if (!drop_data.custom_data.empty()) {
390 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
391 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
396 // Utility to fill a DropData object from ui::OSExchangeData.
397 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
398 drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
400 base::string16 plain_text;
401 data.GetString(&plain_text);
402 if (!plain_text.empty())
403 drop_data->text = base::NullableString16(plain_text, false);
406 base::string16 url_title;
408 ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES, &url, &url_title);
409 if (url.is_valid()) {
410 drop_data->url = url;
411 drop_data->url_title = url_title;
416 data.GetHtml(&html, &html_base_url);
418 drop_data->html = base::NullableString16(html, false);
419 if (html_base_url.is_valid())
420 drop_data->html_base_url = html_base_url;
422 data.GetFilenames(&drop_data->filenames);
425 std::vector<DropData::FileSystemFileInfo> file_system_files;
426 if (data.GetPickledData(GetFileSystemFileCustomFormat(), &pickle) &&
427 ReadFileSystemFilesFromPickle(pickle, &file_system_files))
428 drop_data->file_system_files = file_system_files;
430 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
431 ui::ReadCustomDataIntoMap(
432 pickle.data(), pickle.size(), &drop_data->custom_data);
435 // Utilities to convert between blink::WebDragOperationsMask and
436 // ui::DragDropTypes.
437 int ConvertFromWeb(blink::WebDragOperationsMask ops) {
438 int drag_op = ui::DragDropTypes::DRAG_NONE;
439 if (ops & blink::WebDragOperationCopy)
440 drag_op |= ui::DragDropTypes::DRAG_COPY;
441 if (ops & blink::WebDragOperationMove)
442 drag_op |= ui::DragDropTypes::DRAG_MOVE;
443 if (ops & blink::WebDragOperationLink)
444 drag_op |= ui::DragDropTypes::DRAG_LINK;
448 blink::WebDragOperationsMask ConvertToWeb(int drag_op) {
449 int web_drag_op = blink::WebDragOperationNone;
450 if (drag_op & ui::DragDropTypes::DRAG_COPY)
451 web_drag_op |= blink::WebDragOperationCopy;
452 if (drag_op & ui::DragDropTypes::DRAG_MOVE)
453 web_drag_op |= blink::WebDragOperationMove;
454 if (drag_op & ui::DragDropTypes::DRAG_LINK)
455 web_drag_op |= blink::WebDragOperationLink;
456 return (blink::WebDragOperationsMask) web_drag_op;
459 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
460 int web_input_event_modifiers = 0;
461 if (aura_event_flags & ui::EF_SHIFT_DOWN)
462 web_input_event_modifiers |= blink::WebInputEvent::ShiftKey;
463 if (aura_event_flags & ui::EF_CONTROL_DOWN)
464 web_input_event_modifiers |= blink::WebInputEvent::ControlKey;
465 if (aura_event_flags & ui::EF_ALT_DOWN)
466 web_input_event_modifiers |= blink::WebInputEvent::AltKey;
467 if (aura_event_flags & ui::EF_COMMAND_DOWN)
468 web_input_event_modifiers |= blink::WebInputEvent::MetaKey;
469 return web_input_event_modifiers;
474 class WebContentsViewAura::WindowObserver
475 : public aura::WindowObserver, public aura::WindowTreeHostObserver {
477 explicit WindowObserver(WebContentsViewAura* view)
480 view_->window_->AddObserver(this);
483 if (view_->window_->GetRootWindow())
484 view_->window_->GetRootWindow()->AddObserver(this);
488 ~WindowObserver() override {
489 view_->window_->RemoveObserver(this);
490 if (view_->window_->GetHost())
491 view_->window_->GetHost()->RemoveObserver(this);
493 host_window_->RemoveObserver(this);
496 const aura::Window::Windows& children = host_window_->children();
497 for (size_t i = 0; i < children.size(); ++i)
498 children[i]->RemoveObserver(this);
501 aura::Window* root_window = view_->window_->GetRootWindow();
503 root_window->RemoveObserver(this);
504 const aura::Window::Windows& root_children = root_window->children();
505 for (size_t i = 0; i < root_children.size(); ++i)
506 root_children[i]->RemoveObserver(this);
511 // Overridden from aura::WindowObserver:
512 void OnWindowHierarchyChanged(
513 const aura::WindowObserver::HierarchyChangeParams& params) override {
514 if (params.receiver != view_->window_.get() ||
515 !params.target->Contains(view_->window_.get())) {
519 // Use the new parent's root window for calculating HiDPI subpixel offset.
520 RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
521 view_->web_contents_->GetRenderWidgetHostView());
523 rwhv->SnapToPhysicalPixelBoundary();
527 // Constrained windows are added as children of the parent's parent's view
528 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
529 // so that it can update the plugins' cutout rects accordingly.
530 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
531 // going to be deprecated in a year, this is ok for now. The test for this is
532 // PrintPreviewTest.WindowedNPAPIPluginHidden.
533 virtual void OnWindowAdded(aura::Window* new_window) override {
534 if (!new_window->Contains(view_->window_.get())) {
535 // Skip the case when the parent moves to the root window.
536 if (new_window != host_window_) {
537 // Observe sibling windows of the WebContents, or children of the root
539 if (new_window->parent() == host_window_ ||
540 new_window->parent() == view_->window_->GetRootWindow()) {
541 new_window->AddObserver(this);
546 if (new_window->parent() == host_window_) {
547 UpdateConstrainedWindows(NULL);
551 virtual void OnWillRemoveWindow(aura::Window* window) override {
552 if (window == view_->window_)
555 window->RemoveObserver(this);
556 UpdateConstrainedWindows(window);
559 virtual void OnWindowVisibilityChanged(aura::Window* window,
560 bool visible) override {
561 if (window == view_->window_ ||
562 window->parent() == host_window_ ||
563 window->parent() == view_->window_->GetRootWindow()) {
564 UpdateConstrainedWindows(NULL);
569 void OnWindowParentChanged(aura::Window* window,
570 aura::Window* parent) override {
571 if (window != view_->window_)
574 aura::Window* host_window =
575 window->GetProperty(aura::client::kHostWindowKey);
577 host_window = parent;
580 host_window_->RemoveObserver(this);
584 const aura::Window::Windows& children = host_window_->children();
585 for (size_t i = 0; i < children.size(); ++i)
586 children[i]->RemoveObserver(this);
587 RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
588 view_->web_contents_->GetRenderWidgetHostView());
590 rwhv->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
593 // When we get parented to the root window, the code below will watch the
594 // host window, aka root window. Since we already watch the root window on
595 // Windows, unregister first so that the debug check doesn't fire.
596 if (host_window && host_window == window->GetRootWindow())
597 host_window->RemoveObserver(this);
599 // We need to undo the above if we were parented to the root window and then
600 // got parented to another window. At that point, the code before the ifdef
601 // would have stopped watching the root window.
602 if (window->GetRootWindow() &&
603 host_window != window->GetRootWindow() &&
604 !window->GetRootWindow()->HasObserver(this)) {
605 window->GetRootWindow()->AddObserver(this);
609 host_window_ = host_window;
611 host_window->AddObserver(this);
613 if (host_window != window->GetRootWindow()) {
614 const aura::Window::Windows& children = host_window->children();
615 for (size_t i = 0; i < children.size(); ++i) {
616 if (!children[i]->Contains(view_->window_.get()))
617 children[i]->AddObserver(this);
624 void OnWindowBoundsChanged(aura::Window* window,
625 const gfx::Rect& old_bounds,
626 const gfx::Rect& new_bounds) override {
627 if (window == host_window_ || window == view_->window_) {
629 if (view_->touch_editable_)
630 view_->touch_editable_->UpdateEditingController();
633 UpdateConstrainedWindows(NULL);
638 void OnWindowDestroying(aura::Window* window) override {
639 if (window == host_window_) {
640 host_window_->RemoveObserver(this);
645 void OnWindowAddedToRootWindow(aura::Window* window) override {
646 if (window == view_->window_) {
647 window->GetHost()->AddObserver(this);
649 if (!window->GetRootWindow()->HasObserver(this))
650 window->GetRootWindow()->AddObserver(this);
651 if (view_->legacy_hwnd_) {
652 view_->legacy_hwnd_->UpdateParent(
653 window->GetHost()->GetAcceleratedWidget());
659 void OnWindowRemovingFromRootWindow(aura::Window* window,
660 aura::Window* new_root) override {
661 if (window == view_->window_) {
662 window->GetHost()->RemoveObserver(this);
664 window->GetRootWindow()->RemoveObserver(this);
666 const aura::Window::Windows& root_children =
667 window->GetRootWindow()->children();
668 for (size_t i = 0; i < root_children.size(); ++i) {
669 if (root_children[i] != view_->window_ &&
670 root_children[i] != host_window_) {
671 root_children[i]->RemoveObserver(this);
675 if (view_->legacy_hwnd_)
676 view_->legacy_hwnd_->UpdateParent(ui::GetHiddenWindow());
681 // Overridden WindowTreeHostObserver:
682 void OnHostMoved(const aura::WindowTreeHost* host,
683 const gfx::Point& new_origin) override {
685 "WebContentsViewAura::WindowObserver::OnHostMoved",
686 "new_origin", new_origin.ToString());
688 // This is for the desktop case (i.e. Aura desktop).
693 void SendScreenRects() {
694 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
699 void UpdateConstrainedWindows(aura::Window* exclude) {
700 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
701 view_->web_contents_->GetRenderWidgetHostView());
705 std::vector<gfx::Rect> constrained_windows;
707 const aura::Window::Windows& children = host_window_->children();
708 for (size_t i = 0; i < children.size(); ++i) {
709 if (!children[i]->Contains(view_->window_.get()) &&
710 children[i] != exclude &&
711 children[i]->IsVisible()) {
712 constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
717 aura::Window* root_window = view_->window_->GetRootWindow();
718 const aura::Window::Windows& root_children = root_window->children();
720 for (size_t i = 0; i < root_children.size(); ++i) {
721 if (root_children[i]->IsVisible() &&
722 !root_children[i]->Contains(view_->window_.get())) {
723 constrained_windows.push_back(
724 root_children[i]->GetBoundsInRootWindow());
729 view->UpdateConstrainedWindowRects(constrained_windows);
733 WebContentsViewAura* view_;
735 // The parent window that hosts the constrained windows. We cache the old host
736 // view so that we can unregister when it's not the parent anymore.
737 aura::Window* host_window_;
739 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
742 ////////////////////////////////////////////////////////////////////////////////
743 // WebContentsViewAura, public:
745 WebContentsViewAura::WebContentsViewAura(
746 WebContentsImpl* web_contents,
747 WebContentsViewDelegate* delegate)
748 : web_contents_(web_contents),
750 current_drag_op_(blink::WebDragOperationNone),
751 drag_dest_delegate_(NULL),
752 current_rvh_for_drag_(NULL),
753 overscroll_change_brightness_(false),
754 current_overscroll_gesture_(OVERSCROLL_NONE),
755 completed_overscroll_gesture_(OVERSCROLL_NONE),
756 touch_editable_(TouchEditableImplAura::Create()),
757 is_or_was_visible_(false) {
760 ////////////////////////////////////////////////////////////////////////////////
761 // WebContentsViewAura, private:
763 WebContentsViewAura::~WebContentsViewAura() {
767 window_observer_.reset();
768 window_->RemoveObserver(this);
770 // Window needs a valid delegate during its destructor, so we explicitly
775 void WebContentsViewAura::SetTouchEditableForTest(
776 TouchEditableImplAura* touch_editable) {
777 touch_editable_.reset(touch_editable);
778 AttachTouchEditableToRenderView();
781 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
782 if (web_contents_->GetInterstitialPage())
783 web_contents_->GetInterstitialPage()->SetSize(size);
784 RenderWidgetHostView* rwhv =
785 web_contents_->GetRenderWidgetHostView();
790 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
791 aura::Window* root_window = GetNativeView()->GetRootWindow();
792 gfx::Point screen_loc =
793 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
794 gfx::Point client_loc = screen_loc;
795 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
796 aura::Window* window = rvh->GetView()->GetNativeView();
797 aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
800 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
801 screen_loc.x(), screen_loc.y(), ops);
804 void WebContentsViewAura::InstallOverscrollControllerDelegate(
805 RenderWidgetHostViewAura* view) {
806 const std::string value = base::CommandLine::ForCurrentProcess()->
807 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation);
809 navigation_overlay_.reset();
813 navigation_overlay_.reset();
814 if (!gesture_nav_simple_)
815 gesture_nav_simple_.reset(new GestureNavSimple(web_contents_));
816 view->overscroll_controller()->set_delegate(gesture_nav_simple_.get());
819 view->overscroll_controller()->set_delegate(this);
820 if (!navigation_overlay_)
821 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
824 void WebContentsViewAura::PrepareOverscrollWindow() {
825 // If there is an existing |overscroll_window_| which is in the middle of an
826 // animation, then destroying the window here causes the animation to be
827 // completed immediately, which triggers |OnImplicitAnimationsCompleted()|
828 // callback, and that tries to reset |overscroll_window_| again, causing a
829 // double-free. So use a temporary variable here.
830 if (overscroll_window_) {
831 base::AutoReset<OverscrollMode> reset_state(¤t_overscroll_gesture_,
832 current_overscroll_gesture_);
833 scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
836 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
838 current_overscroll_gesture_);
839 overscroll_window_.reset(new aura::Window(overscroll_delegate));
840 overscroll_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
841 overscroll_window_->SetTransparent(true);
842 overscroll_window_->Init(aura::WINDOW_LAYER_TEXTURED);
843 overscroll_window_->layer()->SetMasksToBounds(false);
844 overscroll_window_->SetName("OverscrollOverlay");
846 overscroll_change_brightness_ = overscroll_delegate->has_image();
847 window_->AddChild(overscroll_window_.get());
849 gfx::Rect bounds = gfx::Rect(window_->bounds().size());
850 if (ShouldNavigateForward(web_contents_->GetController(),
851 current_overscroll_gesture_)) {
852 // The overlay will be sliding in from the right edge towards the left in
853 // non-RTL, or sliding in from the left edge towards the right in RTL.
854 // So position the overlay window accordingly.
855 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
858 aura::Window* animate_window = GetWindowToAnimateForOverscroll();
859 if (animate_window == overscroll_window_)
860 window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
862 window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
864 UpdateOverscrollWindowBrightness(0.f);
866 overscroll_window_->SetBounds(bounds);
867 overscroll_window_->Show();
869 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
872 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
873 StopObservingImplicitAnimations();
874 aura::Window* content = GetContentNativeView();
875 content->layer()->GetAnimator()->AbortAllAnimations();
876 content->SetTransform(gfx::Transform());
877 content->layer()->SetLayerBrightness(0.f);
880 void WebContentsViewAura::ResetOverscrollTransform() {
881 if (!web_contents_->GetRenderWidgetHostView())
883 aura::Window* target = GetWindowToAnimateForOverscroll();
887 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
888 settings.SetPreemptionStrategy(
889 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
890 settings.SetTweenType(gfx::Tween::EASE_OUT);
891 settings.AddObserver(this);
892 target->SetTransform(gfx::Transform());
895 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
896 settings.SetPreemptionStrategy(
897 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
898 settings.SetTweenType(gfx::Tween::EASE_OUT);
899 UpdateOverscrollWindowBrightness(0.f);
903 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
904 if (!web_contents_->GetRenderWidgetHostView())
907 // Animate out the current view first. Navigate to the requested history at
908 // the end of the animation.
909 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
912 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
913 current_overscroll_gesture_, OVERSCROLL_COUNT);
914 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
915 overscroll_window_->delegate());
916 delegate->stop_forwarding_events();
918 completed_overscroll_gesture_ = mode;
919 aura::Window* target = GetWindowToAnimateForOverscroll();
920 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
921 settings.SetPreemptionStrategy(
922 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
923 settings.SetTweenType(gfx::Tween::EASE_OUT);
924 settings.AddObserver(this);
925 gfx::Transform transform;
927 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
928 float translate_x = static_cast<float>(mode == OVERSCROLL_WEST ?
929 -content_width : content_width);
930 transform.Translate(translate_x, 0);
931 target->SetTransform(transform);
932 UpdateOverscrollWindowBrightness(translate_x);
935 aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
936 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
939 return ShouldNavigateForward(web_contents_->GetController(),
940 current_overscroll_gesture_) ?
941 overscroll_window_.get() : GetContentNativeView();
944 gfx::Vector2dF WebContentsViewAura::GetTranslationForOverscroll(float delta_x,
946 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
947 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
948 return gfx::Vector2dF(0, delta_y);
950 // For horizontal overscroll, scroll freely if a navigation is possible. Do a
951 // resistive scroll otherwise.
952 const NavigationControllerImpl& controller = web_contents_->GetController();
953 const gfx::Rect& bounds = GetViewBounds();
954 const float bounds_width = static_cast<float>(bounds.width());
955 if (ShouldNavigateForward(controller, current_overscroll_gesture_))
956 return gfx::Vector2dF(std::max(-bounds_width, delta_x), 0);
957 else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
958 return gfx::Vector2dF(std::min(bounds_width, delta_x), 0);
959 return gfx::Vector2dF();
962 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
963 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
964 overscroll_window_->delegate());
965 overscroll_window_->SchedulePaintInRect(
966 gfx::Rect(overscroll_window_->bounds().size()));
967 overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size()));
968 overscroll_window_->SetTransform(gfx::Transform());
969 navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
971 navigation_overlay_->StartObserving();
974 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
975 if (!overscroll_change_brightness_)
978 const float kBrightnessMin = -.1f;
979 const float kBrightnessMax = -.01f;
981 float ratio = fabs(delta_x) / GetViewBounds().width();
982 ratio = std::min(1.f, ratio);
983 if (base::i18n::IsRTL())
985 float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ?
986 kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) :
987 kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin);
988 brightness = std::max(kBrightnessMin, brightness);
989 brightness = std::min(kBrightnessMax, brightness);
990 aura::Window* window = GetWindowToAnimateForOverscroll();
991 window->layer()->SetLayerBrightness(brightness);
994 void WebContentsViewAura::AttachTouchEditableToRenderView() {
995 if (!touch_editable_)
997 RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
998 web_contents_->GetRenderWidgetHostView());
999 touch_editable_->AttachToView(rwhva);
1002 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
1004 if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
1005 web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
1008 ////////////////////////////////////////////////////////////////////////////////
1009 // WebContentsViewAura, WebContentsView implementation:
1011 gfx::NativeView WebContentsViewAura::GetNativeView() const {
1012 return window_.get();
1015 gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
1016 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1017 return rwhv ? rwhv->GetNativeView() : NULL;
1020 gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
1021 return window_->GetToplevelWindow();
1024 void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
1025 *out = window_->GetBoundsInScreen();
1028 void WebContentsViewAura::SizeContents(const gfx::Size& size) {
1029 gfx::Rect bounds = window_->bounds();
1030 if (bounds.size() != size) {
1031 bounds.set_size(size);
1032 window_->SetBounds(bounds);
1035 legacy_hwnd_->SetBounds(window_->GetBoundsInRootWindow());
1038 // Our size matches what we want but the renderers size may not match.
1039 // Pretend we were resized so that the renderers size is updated too.
1040 SizeChangedCommon(size);
1044 void WebContentsViewAura::Focus() {
1045 if (web_contents_->GetInterstitialPage()) {
1046 web_contents_->GetInterstitialPage()->Focus();
1050 if (delegate_.get() && delegate_->Focus())
1053 RenderWidgetHostView* rwhv =
1054 web_contents_->GetFullscreenRenderWidgetHostView();
1056 rwhv = web_contents_->GetRenderWidgetHostView();
1061 void WebContentsViewAura::SetInitialFocus() {
1062 if (web_contents_->FocusLocationBarByDefault())
1063 web_contents_->SetFocusToLocationBar(false);
1068 void WebContentsViewAura::StoreFocus() {
1070 delegate_->StoreFocus();
1073 void WebContentsViewAura::RestoreFocus() {
1075 delegate_->RestoreFocus();
1078 DropData* WebContentsViewAura::GetDropData() const {
1079 return current_drop_data_.get();
1082 gfx::Rect WebContentsViewAura::GetViewBounds() const {
1083 return window_->GetBoundsInScreen();
1086 ////////////////////////////////////////////////////////////////////////////////
1087 // WebContentsViewAura, WebContentsView implementation:
1089 void WebContentsViewAura::CreateView(
1090 const gfx::Size& initial_size, gfx::NativeView context) {
1091 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1092 // if the bookmark bar is not shown and you create a new tab). The right
1093 // value is set shortly after this, so its safe to ignore.
1095 aura::Env::CreateInstance(true);
1096 window_.reset(new aura::Window(this));
1097 window_->set_owned_by_parent(false);
1098 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
1099 window_->SetTransparent(false);
1100 window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
1101 window_->AddObserver(this);
1102 aura::Window* root_window = context ? context->GetRootWindow() : NULL;
1104 // There are places where there is no context currently because object
1105 // hierarchies are built before they're attached to a Widget. (See
1106 // views::WebView as an example; GetWidget() returns NULL at the point
1107 // where we are created.)
1109 // It should be OK to not set a default parent since such users will
1110 // explicitly add this WebContentsViewAura to their tree after they create
1113 aura::client::ParentWindowWithContext(
1114 window_.get(), root_window, root_window->GetBoundsInScreen());
1117 window_->layer()->SetMasksToBounds(true);
1118 window_->SetName("WebContentsViewAura");
1120 // WindowObserver is not interesting and is problematic for Browser Plugin
1122 // The use cases for WindowObserver do not apply to Browser Plugins:
1123 // 1) guests do not support NPAPI plugins.
1124 // 2) guests' window bounds are supposed to come from its embedder.
1125 if (!BrowserPluginGuest::IsGuest(web_contents_))
1126 window_observer_.reset(new WindowObserver(this));
1128 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1129 // Hence, we save a reference to it locally. Similar model is used on other
1130 // platforms as well.
1132 drag_dest_delegate_ = delegate_->GetDragDestDelegate();
1135 if (context && context->GetHost()) {
1136 HWND parent_hwnd = context->GetHost()->GetAcceleratedWidget();
1138 legacy_hwnd_.reset(LegacyRenderWidgetHostHWND::Create(parent_hwnd, this));
1143 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
1144 RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
1145 if (render_widget_host->GetView()) {
1146 // During testing, the view will already be set up in most cases to the
1147 // test view, so we don't want to clobber it with a real one. To verify that
1148 // this actually is happening (and somebody isn't accidentally creating the
1149 // view twice), we check for the RVH Factory, which will be set when we're
1150 // making special ones (which go along with the special views).
1151 DCHECK(RenderViewHostFactory::has_factory());
1152 return static_cast<RenderWidgetHostViewBase*>(
1153 render_widget_host->GetView());
1156 RenderWidgetHostViewAura* view =
1157 new RenderWidgetHostViewAura(render_widget_host, is_guest_view_hack);
1158 view->InitAsChild(NULL);
1159 GetNativeView()->AddChild(view->GetNativeView());
1161 if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1162 navigation_overlay_->StartObserving();
1165 RenderWidgetHostImpl* host_impl =
1166 RenderWidgetHostImpl::From(render_widget_host);
1168 if (!host_impl->is_hidden())
1171 // We listen to drag drop events in the newly created view's window.
1172 aura::client::SetDragDropDelegate(view->GetNativeView(), this);
1174 if (view->overscroll_controller() &&
1175 (!web_contents_->GetDelegate() ||
1176 web_contents_->GetDelegate()->CanOverscrollContent())) {
1177 InstallOverscrollControllerDelegate(view);
1180 AttachTouchEditableToRenderView();
1184 view->SetLegacyRenderWidgetHostHWND(legacy_hwnd_.get());
1190 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
1191 RenderWidgetHost* render_widget_host) {
1192 RenderWidgetHostViewAura* view =
1193 new RenderWidgetHostViewAura(render_widget_host, false);
1196 view->SetLegacyRenderWidgetHostHWND(legacy_hwnd_.get());
1201 void WebContentsViewAura::SetPageTitle(const base::string16& title) {
1202 window_->SetTitle(title);
1205 void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
1208 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
1209 if (navigation_overlay_.get() && navigation_overlay_->has_window())
1210 navigation_overlay_->StartObserving();
1211 AttachTouchEditableToRenderView();
1214 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
1215 RenderWidgetHostViewAura* view =
1216 ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
1218 view->SetOverscrollControllerEnabled(enabled);
1220 InstallOverscrollControllerDelegate(view);
1224 navigation_overlay_.reset();
1225 else if (!navigation_overlay_)
1226 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1229 ////////////////////////////////////////////////////////////////////////////////
1230 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1232 void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
1233 const ContextMenuParams& params) {
1234 if (touch_editable_) {
1235 touch_editable_->EndTouchEditing(false);
1238 delegate_->ShowContextMenu(render_frame_host, params);
1239 // WARNING: we may have been deleted during the call to ShowContextMenu().
1243 void WebContentsViewAura::StartDragging(
1244 const DropData& drop_data,
1245 blink::WebDragOperationsMask operations,
1246 const gfx::ImageSkia& image,
1247 const gfx::Vector2d& image_offset,
1248 const DragEventSourceInfo& event_info) {
1249 aura::Window* root_window = GetNativeView()->GetRootWindow();
1250 if (!aura::client::GetDragDropClient(root_window)) {
1251 web_contents_->SystemDragEnded();
1255 if (touch_editable_)
1256 touch_editable_->EndTouchEditing(false);
1258 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
1259 PrepareDragData(drop_data, provider, web_contents_);
1261 ui::OSExchangeData data(provider); // takes ownership of |provider|.
1263 if (!image.isNull())
1264 drag_utils::SetDragImageOnDataObject(image, image_offset, &data);
1266 scoped_ptr<WebDragSourceAura> drag_source(
1267 new WebDragSourceAura(GetNativeView(), web_contents_));
1269 // We need to enable recursive tasks on the message loop so we can get
1270 // updates while in the system DoDragDrop loop.
1273 gfx::NativeView content_native_view = GetContentNativeView();
1274 base::MessageLoop::ScopedNestableTaskAllower allow(
1275 base::MessageLoop::current());
1276 result_op = aura::client::GetDragDropClient(root_window)
1277 ->StartDragAndDrop(data,
1279 content_native_view,
1280 event_info.event_location,
1281 ConvertFromWeb(operations),
1282 event_info.event_source);
1285 // Bail out immediately if the contents view window is gone. Note that it is
1286 // not safe to access any class members in this case since |this| may already
1287 // be destroyed. The local variable |drag_source| will still be valid though,
1288 // so we can use it to determine if the window is gone.
1289 if (!drag_source->window()) {
1290 // Note that in this case, we don't need to call SystemDragEnded() since the
1291 // renderer is going away.
1295 EndDrag(ConvertToWeb(result_op));
1296 web_contents_->SystemDragEnded();
1299 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
1300 current_drag_op_ = operation;
1303 void WebContentsViewAura::GotFocus() {
1304 if (web_contents_->GetDelegate())
1305 web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
1308 void WebContentsViewAura::TakeFocus(bool reverse) {
1309 if (web_contents_->GetDelegate() &&
1310 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1312 delegate_->TakeFocus(reverse);
1316 void WebContentsViewAura::ShowDisambiguationPopup(
1317 const gfx::Rect& target_rect,
1318 const SkBitmap& zoomed_bitmap,
1319 const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
1320 const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
1322 delegate_->ShowDisambiguationPopup(target_rect, zoomed_bitmap,
1323 window_.get(), gesture_cb, mouse_cb);
1327 void WebContentsViewAura::HideDisambiguationPopup() {
1329 delegate_->HideDisambiguationPopup();
1332 ////////////////////////////////////////////////////////////////////////////////
1333 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1335 gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
1336 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1337 if (!rwhv || !rwhv->IsShowing())
1340 return rwhv->GetViewBounds();
1343 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1344 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1347 aura::Window* target = GetWindowToAnimateForOverscroll();
1348 gfx::Vector2dF translate = GetTranslationForOverscroll(delta_x, delta_y);
1349 gfx::Transform transform;
1351 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
1352 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
1353 OverscrollUpdateForWebContentsDelegate(translate.y());
1355 // Only horizontal overscrolls participate in the navigation gesture.
1356 transform.Translate(translate.x(), translate.y());
1357 target->SetTransform(transform);
1358 UpdateOverscrollWindowBrightness(delta_x);
1361 return !translate.IsZero();
1364 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1365 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
1366 if (web_contents_->GetDelegate() &&
1367 IsScrollEndEffectEnabled() &&
1368 (mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
1369 web_contents_->GetDelegate()->OverscrollComplete();
1371 NavigationControllerImpl& controller = web_contents_->GetController();
1372 if (ShouldNavigateForward(controller, mode) ||
1373 ShouldNavigateBack(controller, mode)) {
1374 CompleteOverscrollNavigation(mode);
1378 ResetOverscrollTransform();
1381 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1382 OverscrollMode new_mode) {
1383 // Reset any in-progress overscroll animation first.
1384 ResetOverscrollTransform();
1386 if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
1387 OverscrollUpdateForWebContentsDelegate(0);
1389 if (new_mode != OVERSCROLL_NONE && touch_editable_)
1390 touch_editable_->OverscrollStarted();
1392 if (new_mode == OVERSCROLL_NONE ||
1393 !GetContentNativeView() ||
1394 ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
1395 navigation_overlay_.get() && navigation_overlay_->has_window())) {
1396 current_overscroll_gesture_ = OVERSCROLL_NONE;
1398 aura::Window* target = GetWindowToAnimateForOverscroll();
1400 StopObservingImplicitAnimations();
1401 target->layer()->GetAnimator()->AbortAllAnimations();
1403 // Cleanup state of the content window first, because that can reset the
1404 // value of |current_overscroll_gesture_|.
1405 PrepareContentWindowForOverscroll();
1407 current_overscroll_gesture_ = new_mode;
1408 if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
1409 current_overscroll_gesture_ == OVERSCROLL_WEST)
1410 PrepareOverscrollWindow();
1412 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
1414 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1417 ////////////////////////////////////////////////////////////////////////////////
1418 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1420 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1421 overscroll_shadow_.reset();
1423 if (ShouldNavigateForward(web_contents_->GetController(),
1424 completed_overscroll_gesture_)) {
1425 web_contents_->GetController().GoForward();
1426 PrepareOverscrollNavigationOverlay();
1427 } else if (ShouldNavigateBack(web_contents_->GetController(),
1428 completed_overscroll_gesture_)) {
1429 web_contents_->GetController().GoBack();
1430 PrepareOverscrollNavigationOverlay();
1432 if (touch_editable_)
1433 touch_editable_->OverscrollCompleted();
1436 aura::Window* content = GetContentNativeView();
1438 content->SetTransform(gfx::Transform());
1439 content->layer()->SetLayerBrightness(0.f);
1441 current_overscroll_gesture_ = OVERSCROLL_NONE;
1442 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1443 overscroll_window_.reset();
1446 ////////////////////////////////////////////////////////////////////////////////
1447 // WebContentsViewAura, aura::WindowDelegate implementation:
1449 gfx::Size WebContentsViewAura::GetMinimumSize() const {
1453 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1457 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1458 const gfx::Rect& new_bounds) {
1459 SizeChangedCommon(new_bounds.size());
1461 delegate_->SizeChanged(new_bounds.size());
1463 // Constrained web dialogs, need to be kept centered over our content area.
1464 for (size_t i = 0; i < window_->children().size(); i++) {
1465 if (window_->children()[i]->GetProperty(
1466 aura::client::kConstrainedWindowKey)) {
1467 gfx::Rect bounds = window_->children()[i]->bounds();
1469 gfx::Point((new_bounds.width() - bounds.width()) / 2,
1470 (new_bounds.height() - bounds.height()) / 2));
1471 window_->children()[i]->SetBounds(bounds);
1476 gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1477 return gfx::kNullCursor;
1480 int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1484 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1485 aura::Window* child,
1486 const gfx::Point& location) {
1490 bool WebContentsViewAura::CanFocus() {
1491 // Do not take the focus if the render widget host view aura is gone or
1492 // is in the process of shutting down because neither the view window nor
1493 // this window can handle key events.
1494 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
1495 web_contents_->GetRenderWidgetHostView());
1496 if (view != NULL && !view->IsClosing())
1502 void WebContentsViewAura::OnCaptureLost() {
1505 void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
1508 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1509 float device_scale_factor) {
1512 void WebContentsViewAura::OnWindowDestroying(aura::Window* window) {
1513 // This means the destructor is going to be called soon. If there is an
1514 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1515 // then destroying it in the WebContentsViewAura destructor can trigger other
1516 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1517 // destroy the overscroll window here.
1518 navigation_overlay_.reset();
1519 overscroll_window_.reset();
1522 void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) {
1525 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1528 bool WebContentsViewAura::HasHitTestMask() const {
1532 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1535 ////////////////////////////////////////////////////////////////////////////////
1536 // WebContentsViewAura, ui::EventHandler implementation:
1538 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1541 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1542 if (!web_contents_->GetDelegate())
1545 switch (event->type()) {
1546 case ui::ET_MOUSE_PRESSED:
1547 web_contents_->GetDelegate()->ActivateContents(web_contents_);
1549 case ui::ET_MOUSE_MOVED:
1550 case ui::ET_MOUSE_EXITED:
1551 web_contents_->GetDelegate()->ContentsMouseEvent(
1553 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1554 event->type() == ui::ET_MOUSE_MOVED);
1561 ////////////////////////////////////////////////////////////////////////////////
1562 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1564 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1565 current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1566 current_drop_data_.reset(new DropData());
1568 PrepareDropData(current_drop_data_.get(), event.data());
1569 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1571 // Give the delegate an opportunity to cancel the drag.
1572 if (web_contents_->GetDelegate() &&
1573 !web_contents_->GetDelegate()->CanDragEnter(
1574 web_contents_, *current_drop_data_.get(), op)) {
1575 current_drop_data_.reset(NULL);
1579 if (drag_dest_delegate_)
1580 drag_dest_delegate_->DragInitialize(web_contents_);
1582 gfx::Point screen_pt =
1583 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1584 web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1585 *current_drop_data_.get(), event.location(), screen_pt, op,
1586 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1588 if (drag_dest_delegate_) {
1589 drag_dest_delegate_->OnReceiveDragData(event.data());
1590 drag_dest_delegate_->OnDragEnter();
1594 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1595 DCHECK(current_rvh_for_drag_);
1596 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1597 OnDragEntered(event);
1599 if (!current_drop_data_)
1600 return ui::DragDropTypes::DRAG_NONE;
1602 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1603 gfx::Point screen_pt =
1604 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1605 web_contents_->GetRenderViewHost()->DragTargetDragOver(
1606 event.location(), screen_pt, op,
1607 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1609 if (drag_dest_delegate_)
1610 drag_dest_delegate_->OnDragOver();
1612 return ConvertFromWeb(current_drag_op_);
1615 void WebContentsViewAura::OnDragExited() {
1616 DCHECK(current_rvh_for_drag_);
1617 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1620 if (!current_drop_data_)
1623 web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1624 if (drag_dest_delegate_)
1625 drag_dest_delegate_->OnDragLeave();
1627 current_drop_data_.reset();
1630 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1631 DCHECK(current_rvh_for_drag_);
1632 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1633 OnDragEntered(event);
1635 if (!current_drop_data_)
1636 return ui::DragDropTypes::DRAG_NONE;
1638 web_contents_->GetRenderViewHost()->DragTargetDrop(
1640 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1641 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1642 if (drag_dest_delegate_)
1643 drag_dest_delegate_->OnDrop();
1644 current_drop_data_.reset();
1645 return ConvertFromWeb(current_drag_op_);
1648 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
1650 // Ignore any visibility changes in the hierarchy below.
1651 if (window != window_.get() && window_->Contains(window))
1654 UpdateWebContentsVisibility(visible);
1657 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible) {
1658 if (!is_or_was_visible_) {
1659 // We should not hide the web contents before it was shown the first time,
1660 // since resources would immediately be destroyed and only re-created after
1661 // content got loaded. In this state the window content is undefined and can
1663 // However - the page load mechanism requires an activation call through a
1664 // visibility call to (re)load.
1666 is_or_was_visible_ = true;
1667 web_contents_->WasShown();
1672 if (!web_contents_->should_normally_be_visible())
1673 web_contents_->WasShown();
1675 if (web_contents_->should_normally_be_visible())
1676 web_contents_->WasHidden();
1683 if (visible && GetNativeView() && GetNativeView()->GetHost()) {
1684 legacy_hwnd_->UpdateParent(
1685 GetNativeView()->GetHost()->GetAcceleratedWidget());
1686 legacy_hwnd_->SetBounds(window_->GetBoundsInRootWindow());
1687 legacy_hwnd_->Show();
1689 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
1690 // hidden window on the same lines as Windowed plugin windows.
1691 legacy_hwnd_->UpdateParent(ui::GetHiddenWindow());
1692 legacy_hwnd_->Hide();
1698 gfx::NativeViewAccessible
1699 WebContentsViewAura::GetNativeViewAccessible() {
1700 BrowserAccessibilityManager* manager =
1701 web_contents_->GetRootBrowserAccessibilityManager();
1705 return manager->GetRoot()->ToBrowserAccessibilityWin();
1709 } // namespace content