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/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"
73 WebContentsView* 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;
84 bool IsScrollEndEffectEnabled() {
85 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
86 switches::kScrollEndEffect) == "1";
89 bool ShouldNavigateForward(const NavigationController& controller,
90 OverscrollMode mode) {
91 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
92 controller.CanGoForward();
95 bool ShouldNavigateBack(const NavigationController& controller,
96 OverscrollMode mode) {
97 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
98 controller.CanGoBack();
101 RenderWidgetHostViewAura* 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())
109 return static_cast<RenderWidgetHostViewAura*>(view);
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
115 class OverscrollWindowDelegate : public ImageWindowDelegate {
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));
132 if (entry && entry->screenshot().get()) {
133 std::vector<gfx::ImagePNGRep> image_reps;
134 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
136 ui::GetScaleFactorForNativeView(web_contents_window()))));
137 image = gfx::Image(image_reps);
142 void stop_forwarding_events() { forward_events_ = false; }
145 virtual ~OverscrollWindowDelegate() {}
147 aura::Window* web_contents_window() {
148 return web_contents_->GetView()->GetContentNativeView();
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);
157 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
158 if (forward_events_ && web_contents_window())
159 web_contents_window()->delegate()->OnGestureEvent(event);
162 WebContentsImpl* web_contents_;
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_;
172 DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
175 // Listens to all mouse drag events during a drag and drop and sends them to
177 class WebDragSourceAura : public NotificationObserver {
179 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
181 contents_(contents) {
183 NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
184 Source<WebContents>(contents));
187 virtual ~WebDragSourceAura() {
190 // NotificationObserver:
191 virtual void Observe(int type,
192 const NotificationSource& source,
193 const NotificationDetails& details) OVERRIDE {
194 if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
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();
207 aura::Window* window() const { return window_; }
210 aura::Window* window_;
211 WebContentsImpl* contents_;
212 NotificationRegistrar registrar_;
214 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
217 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
218 // Fill out the OSExchangeData with a file contents, synthesizing a name if
220 void 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);
232 provider->SetFileContents(file_name, drop_data.file_contents);
237 void 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();
244 // Parse the download metadata.
245 base::string16 mime_type;
246 base::FilePath file_name;
248 if (!ParseDownloadMetadata(drop_data.download_metadata,
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,
261 base::UTF16ToUTF8(file_name.value()),
262 base::UTF16ToUTF8(mime_type),
265 // http://crbug.com/332579
266 base::ThreadRestrictions::ScopedAllowIO allow_file_operations;
268 base::FilePath temp_dir_path;
269 if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
273 base::FilePath download_path =
274 temp_dir_path.Append(generated_download_file_name);
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);
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(
288 Referrer(page_url, drop_data.referrer_policy),
291 ui::OSExchangeData::DownloadFileInfo file_download(base::FilePath(),
292 download_file.get());
293 provider->SetDownloadFileInfo(file_download);
295 #endif // defined(OS_WIN)
297 // Returns the CustomFormat to store file system files.
298 const ui::OSExchangeData::CustomFormat& GetFileSystemFileCustomFormat() {
299 static const char kFormatString[] = "chromium/x-file-system-files";
300 CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat,
302 (ui::Clipboard::GetFormatType(kFormatString)));
306 // Writes file system files to the pickle.
307 void WriteFileSystemFilesToPickle(
308 const std::vector<DropData::FileSystemFileInfo>& file_system_files,
310 pickle->WriteUInt64(file_system_files.size());
311 for (size_t i = 0; i < file_system_files.size(); ++i) {
312 pickle->WriteString(file_system_files[i].url.spec());
313 pickle->WriteInt64(file_system_files[i].size);
317 // Reads file system files from the pickle.
318 bool ReadFileSystemFilesFromPickle(
319 const Pickle& pickle,
320 std::vector<DropData::FileSystemFileInfo>* file_system_files) {
321 PickleIterator iter(pickle);
323 uint64 num_files = 0;
324 if (!pickle.ReadUInt64(&iter, &num_files))
326 file_system_files->resize(num_files);
328 for (uint64 i = 0; i < num_files; ++i) {
329 std::string url_string;
331 if (!pickle.ReadString(&iter, &url_string) ||
332 !pickle.ReadInt64(&iter, &size))
335 GURL url(url_string);
339 (*file_system_files)[i].url = url;
340 (*file_system_files)[i].size = size;
345 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
346 void PrepareDragData(const DropData& drop_data,
347 ui::OSExchangeData::Provider* provider,
348 WebContentsImpl* web_contents) {
349 provider->MarkOriginatedFromRenderer();
351 // Put download before file contents to prefer the download of a image over
352 // its thumbnail link.
353 if (!drop_data.download_metadata.empty())
354 PrepareDragForDownload(drop_data, provider, web_contents);
356 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
357 // We set the file contents before the URL because the URL also sets file
358 // contents (to a .URL shortcut). We want to prefer file content data over
359 // a shortcut so we add it first.
360 if (!drop_data.file_contents.empty())
361 PrepareDragForFileContents(drop_data, provider);
363 if (!drop_data.text.string().empty())
364 provider->SetString(drop_data.text.string());
365 if (drop_data.url.is_valid())
366 provider->SetURL(drop_data.url, drop_data.url_title);
367 if (!drop_data.html.string().empty())
368 provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
369 if (!drop_data.filenames.empty())
370 provider->SetFilenames(drop_data.filenames);
371 if (!drop_data.file_system_files.empty()) {
373 WriteFileSystemFilesToPickle(drop_data.file_system_files, &pickle);
374 provider->SetPickledData(GetFileSystemFileCustomFormat(), pickle);
376 if (!drop_data.custom_data.empty()) {
378 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
379 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
384 // Utility to fill a DropData object from ui::OSExchangeData.
385 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
386 drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
388 base::string16 plain_text;
389 data.GetString(&plain_text);
390 if (!plain_text.empty())
391 drop_data->text = base::NullableString16(plain_text, false);
394 base::string16 url_title;
396 ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES, &url, &url_title);
397 if (url.is_valid()) {
398 drop_data->url = url;
399 drop_data->url_title = url_title;
404 data.GetHtml(&html, &html_base_url);
406 drop_data->html = base::NullableString16(html, false);
407 if (html_base_url.is_valid())
408 drop_data->html_base_url = html_base_url;
410 data.GetFilenames(&drop_data->filenames);
413 std::vector<DropData::FileSystemFileInfo> file_system_files;
414 if (data.GetPickledData(GetFileSystemFileCustomFormat(), &pickle) &&
415 ReadFileSystemFilesFromPickle(pickle, &file_system_files))
416 drop_data->file_system_files = file_system_files;
418 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
419 ui::ReadCustomDataIntoMap(
420 pickle.data(), pickle.size(), &drop_data->custom_data);
423 // Utilities to convert between blink::WebDragOperationsMask and
424 // ui::DragDropTypes.
425 int ConvertFromWeb(blink::WebDragOperationsMask ops) {
426 int drag_op = ui::DragDropTypes::DRAG_NONE;
427 if (ops & blink::WebDragOperationCopy)
428 drag_op |= ui::DragDropTypes::DRAG_COPY;
429 if (ops & blink::WebDragOperationMove)
430 drag_op |= ui::DragDropTypes::DRAG_MOVE;
431 if (ops & blink::WebDragOperationLink)
432 drag_op |= ui::DragDropTypes::DRAG_LINK;
436 blink::WebDragOperationsMask ConvertToWeb(int drag_op) {
437 int web_drag_op = blink::WebDragOperationNone;
438 if (drag_op & ui::DragDropTypes::DRAG_COPY)
439 web_drag_op |= blink::WebDragOperationCopy;
440 if (drag_op & ui::DragDropTypes::DRAG_MOVE)
441 web_drag_op |= blink::WebDragOperationMove;
442 if (drag_op & ui::DragDropTypes::DRAG_LINK)
443 web_drag_op |= blink::WebDragOperationLink;
444 return (blink::WebDragOperationsMask) web_drag_op;
447 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
448 int web_input_event_modifiers = 0;
449 if (aura_event_flags & ui::EF_SHIFT_DOWN)
450 web_input_event_modifiers |= blink::WebInputEvent::ShiftKey;
451 if (aura_event_flags & ui::EF_CONTROL_DOWN)
452 web_input_event_modifiers |= blink::WebInputEvent::ControlKey;
453 if (aura_event_flags & ui::EF_ALT_DOWN)
454 web_input_event_modifiers |= blink::WebInputEvent::AltKey;
455 if (aura_event_flags & ui::EF_COMMAND_DOWN)
456 web_input_event_modifiers |= blink::WebInputEvent::MetaKey;
457 return web_input_event_modifiers;
462 class WebContentsViewAura::WindowObserver
463 : public aura::WindowObserver, public aura::WindowTreeHostObserver {
465 explicit WindowObserver(WebContentsViewAura* view)
468 view_->window_->AddObserver(this);
471 if (view_->window_->GetRootWindow())
472 view_->window_->GetRootWindow()->AddObserver(this);
476 virtual ~WindowObserver() {
477 view_->window_->RemoveObserver(this);
478 if (view_->window_->GetHost())
479 view_->window_->GetHost()->RemoveObserver(this);
481 parent_->RemoveObserver(this);
485 const aura::Window::Windows& children = parent_->children();
486 for (size_t i = 0; i < children.size(); ++i)
487 children[i]->RemoveObserver(this);
490 aura::Window* root_window = view_->window_->GetRootWindow();
492 root_window->RemoveObserver(this);
493 const aura::Window::Windows& root_children = root_window->children();
494 for (size_t i = 0; i < root_children.size(); ++i)
495 root_children[i]->RemoveObserver(this);
500 // Overridden from aura::WindowObserver:
502 // Constrained windows are added as children of the parent's parent's view
503 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
504 // so that it can update the plugins' cutout rects accordingly.
505 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
506 // going to be deprecated in a year, this is ok for now. The test for this is
507 // PrintPreviewTest.WindowedNPAPIPluginHidden.
508 virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
509 if (new_window != view_->window_) {
510 // Skip the case when the parent moves to the root window.
511 if (new_window != parent_) {
512 // Observe sibling windows of the WebContents, or children of the root
514 if (new_window->parent() == parent_ ||
515 new_window->parent() == view_->window_->GetRootWindow()) {
516 new_window->AddObserver(this);
521 if (new_window->parent() == parent_) {
522 UpdateConstrainedWindows(NULL);
526 virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
527 if (window == view_->window_)
530 window->RemoveObserver(this);
531 UpdateConstrainedWindows(window);
534 virtual void OnWindowVisibilityChanged(aura::Window* window,
535 bool visible) OVERRIDE {
536 if (window == view_->window_ ||
537 window->parent() == parent_ ||
538 window->parent() == view_->window_->GetRootWindow()) {
539 UpdateConstrainedWindows(NULL);
544 virtual void OnWindowParentChanged(aura::Window* window,
545 aura::Window* parent) OVERRIDE {
546 if (window != view_->window_)
549 parent_->RemoveObserver(this);
553 const aura::Window::Windows& children = parent_->children();
554 for (size_t i = 0; i < children.size(); ++i)
555 children[i]->RemoveObserver(this);
557 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
558 view_->web_contents_->GetRenderWidgetHostView());
560 view->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
563 // When we get parented to the root window, the code below will watch the
564 // parent, aka root window. Since we already watch the root window on
565 // Windows, unregister first so that the debug check doesn't fire.
566 if (parent && parent == window->GetRootWindow())
567 parent->RemoveObserver(this);
569 // We need to undo the above if we were parented to the root window and then
570 // got parented to another window. At that point, the code before the ifdef
571 // would have stopped watching the root window.
572 if (window->GetRootWindow() &&
573 parent != window->GetRootWindow() &&
574 !window->GetRootWindow()->HasObserver(this)) {
575 window->GetRootWindow()->AddObserver(this);
581 parent->AddObserver(this);
583 if (parent != window->GetRootWindow()) {
584 const aura::Window::Windows& children = parent->children();
585 for (size_t i = 0; i < children.size(); ++i) {
586 if (children[i] != view_->window_)
587 children[i]->AddObserver(this);
594 virtual void OnWindowBoundsChanged(aura::Window* window,
595 const gfx::Rect& old_bounds,
596 const gfx::Rect& new_bounds) OVERRIDE {
597 if (window == parent_ || window == view_->window_) {
599 if (view_->touch_editable_)
600 view_->touch_editable_->UpdateEditingController();
603 UpdateConstrainedWindows(NULL);
608 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
609 if (window == view_->window_) {
610 window->GetHost()->AddObserver(this);
612 if (!window->GetRootWindow()->HasObserver(this))
613 window->GetRootWindow()->AddObserver(this);
618 virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
619 aura::Window* new_root) OVERRIDE {
620 if (window == view_->window_) {
621 window->GetHost()->RemoveObserver(this);
623 window->GetRootWindow()->RemoveObserver(this);
625 const aura::Window::Windows& root_children =
626 window->GetRootWindow()->children();
627 for (size_t i = 0; i < root_children.size(); ++i) {
628 if (root_children[i] != view_->window_ && root_children[i] != parent_)
629 root_children[i]->RemoveObserver(this);
635 // Overridden WindowTreeHostObserver:
636 virtual void OnHostMoved(const aura::WindowTreeHost* host,
637 const gfx::Point& new_origin) OVERRIDE {
639 "WebContentsViewAura::WindowObserver::OnHostMoved",
640 "new_origin", new_origin.ToString());
642 // This is for the desktop case (i.e. Aura desktop).
647 void SendScreenRects() {
648 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
653 void UpdateConstrainedWindows(aura::Window* exclude) {
654 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
655 view_->web_contents_->GetRenderWidgetHostView());
659 std::vector<gfx::Rect> constrained_windows;
661 const aura::Window::Windows& children = parent_->children();
662 for (size_t i = 0; i < children.size(); ++i) {
663 if (children[i] != view_->window_ &&
664 children[i] != exclude &&
665 children[i]->IsVisible()) {
666 constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
671 aura::Window* root_window = view_->window_->GetRootWindow();
672 const aura::Window::Windows& root_children = root_window->children();
674 for (size_t i = 0; i < root_children.size(); ++i) {
675 if (root_children[i]->IsVisible() &&
676 !root_children[i]->Contains(view_->window_.get())) {
677 constrained_windows.push_back(
678 root_children[i]->GetBoundsInRootWindow());
683 view->UpdateConstrainedWindowRects(constrained_windows);
687 WebContentsViewAura* view_;
689 // We cache the old parent so that we can unregister when it's not the parent
691 aura::Window* parent_;
693 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
696 ////////////////////////////////////////////////////////////////////////////////
697 // WebContentsViewAura, public:
699 WebContentsViewAura::WebContentsViewAura(
700 WebContentsImpl* web_contents,
701 WebContentsViewDelegate* delegate)
702 : web_contents_(web_contents),
704 current_drag_op_(blink::WebDragOperationNone),
705 drag_dest_delegate_(NULL),
706 current_rvh_for_drag_(NULL),
707 overscroll_change_brightness_(false),
708 current_overscroll_gesture_(OVERSCROLL_NONE),
709 completed_overscroll_gesture_(OVERSCROLL_NONE),
710 touch_editable_(TouchEditableImplAura::Create()) {
713 ////////////////////////////////////////////////////////////////////////////////
714 // WebContentsViewAura, private:
716 WebContentsViewAura::~WebContentsViewAura() {
720 window_observer_.reset();
722 // Window needs a valid delegate during its destructor, so we explicitly
727 void WebContentsViewAura::SetupOverlayWindowForTesting() {
728 if (navigation_overlay_)
729 navigation_overlay_->SetupForTesting();
732 void WebContentsViewAura::SetTouchEditableForTest(
733 TouchEditableImplAura* touch_editable) {
734 touch_editable_.reset(touch_editable);
735 AttachTouchEditableToRenderView();
738 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
739 if (web_contents_->GetInterstitialPage())
740 web_contents_->GetInterstitialPage()->SetSize(size);
741 RenderWidgetHostView* rwhv =
742 web_contents_->GetRenderWidgetHostView();
747 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
748 aura::Window* root_window = GetNativeView()->GetRootWindow();
749 gfx::Point screen_loc =
750 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
751 gfx::Point client_loc = screen_loc;
752 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
753 aura::Window* window = rvh->GetView()->GetNativeView();
754 aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
757 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
758 screen_loc.x(), screen_loc.y(), ops);
761 void WebContentsViewAura::InstallOverscrollControllerDelegate(
762 RenderWidgetHostImpl* host) {
763 const std::string value = CommandLine::ForCurrentProcess()->
764 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation);
766 navigation_overlay_.reset();
770 navigation_overlay_.reset();
771 if (!gesture_nav_simple_)
772 gesture_nav_simple_.reset(new GestureNavSimple(web_contents_));
773 host->overscroll_controller()->set_delegate(gesture_nav_simple_.get());
776 host->overscroll_controller()->set_delegate(this);
777 if (!navigation_overlay_)
778 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
781 void WebContentsViewAura::PrepareOverscrollWindow() {
782 // If there is an existing |overscroll_window_| which is in the middle of an
783 // animation, then destroying the window here causes the animation to be
784 // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
785 // callback, and that tries to reset |overscroll_window_| again, causing a
786 // double-free. So use a temporary variable here.
787 if (overscroll_window_) {
788 base::AutoReset<OverscrollMode> reset_state(¤t_overscroll_gesture_,
789 current_overscroll_gesture_);
790 scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
793 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
795 current_overscroll_gesture_);
796 overscroll_window_.reset(new aura::Window(overscroll_delegate));
797 overscroll_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
798 overscroll_window_->SetTransparent(true);
799 overscroll_window_->Init(aura::WINDOW_LAYER_TEXTURED);
800 overscroll_window_->layer()->SetMasksToBounds(false);
801 overscroll_window_->SetName("OverscrollOverlay");
803 overscroll_change_brightness_ = overscroll_delegate->has_image();
804 window_->AddChild(overscroll_window_.get());
806 gfx::Rect bounds = gfx::Rect(window_->bounds().size());
807 if (ShouldNavigateForward(web_contents_->GetController(),
808 current_overscroll_gesture_)) {
809 // The overlay will be sliding in from the right edge towards the left in
810 // non-RTL, or sliding in from the left edge towards the right in RTL.
811 // So position the overlay window accordingly.
812 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
815 aura::Window* animate_window = GetWindowToAnimateForOverscroll();
816 if (animate_window == overscroll_window_)
817 window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
819 window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
821 UpdateOverscrollWindowBrightness(0.f);
823 overscroll_window_->SetBounds(bounds);
824 overscroll_window_->Show();
826 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
829 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
830 StopObservingImplicitAnimations();
831 aura::Window* content = GetContentNativeView();
832 content->layer()->GetAnimator()->AbortAllAnimations();
833 content->SetTransform(gfx::Transform());
834 content->layer()->SetLayerBrightness(0.f);
837 void WebContentsViewAura::ResetOverscrollTransform() {
838 if (!web_contents_->GetRenderWidgetHostView())
840 aura::Window* target = GetWindowToAnimateForOverscroll();
844 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
845 settings.SetPreemptionStrategy(
846 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
847 settings.SetTweenType(gfx::Tween::EASE_OUT);
848 settings.AddObserver(this);
849 target->SetTransform(gfx::Transform());
852 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
853 settings.SetPreemptionStrategy(
854 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
855 settings.SetTweenType(gfx::Tween::EASE_OUT);
856 UpdateOverscrollWindowBrightness(0.f);
860 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
861 if (!web_contents_->GetRenderWidgetHostView())
864 // Animate out the current view first. Navigate to the requested history at
865 // the end of the animation.
866 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
869 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
870 current_overscroll_gesture_, OVERSCROLL_COUNT);
871 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
872 overscroll_window_->delegate());
873 delegate->stop_forwarding_events();
875 completed_overscroll_gesture_ = mode;
876 aura::Window* target = GetWindowToAnimateForOverscroll();
877 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
878 settings.SetPreemptionStrategy(
879 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
880 settings.SetTweenType(gfx::Tween::EASE_OUT);
881 settings.AddObserver(this);
882 gfx::Transform transform;
884 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
885 int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width;
886 transform.Translate(translate_x, 0);
887 target->SetTransform(transform);
888 UpdateOverscrollWindowBrightness(translate_x);
891 aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
892 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
895 return ShouldNavigateForward(web_contents_->GetController(),
896 current_overscroll_gesture_) ?
897 overscroll_window_.get() : GetContentNativeView();
900 gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
902 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
903 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
904 return gfx::Vector2d(0, delta_y);
906 // For horizontal overscroll, scroll freely if a navigation is possible. Do a
907 // resistive scroll otherwise.
908 const NavigationControllerImpl& controller = web_contents_->GetController();
909 const gfx::Rect& bounds = GetViewBounds();
910 if (ShouldNavigateForward(controller, current_overscroll_gesture_))
911 return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0);
912 else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
913 return gfx::Vector2d(std::min(bounds.width(), delta_x), 0);
914 return gfx::Vector2d();
917 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
918 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
919 overscroll_window_->delegate());
920 overscroll_window_->SchedulePaintInRect(
921 gfx::Rect(overscroll_window_->bounds().size()));
922 overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size()));
923 overscroll_window_->SetTransform(gfx::Transform());
924 navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
926 navigation_overlay_->StartObserving();
929 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
930 if (!overscroll_change_brightness_)
933 const float kBrightnessMin = -.1f;
934 const float kBrightnessMax = -.01f;
936 float ratio = fabs(delta_x) / GetViewBounds().width();
937 ratio = std::min(1.f, ratio);
938 if (base::i18n::IsRTL())
940 float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ?
941 kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) :
942 kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin);
943 brightness = std::max(kBrightnessMin, brightness);
944 brightness = std::min(kBrightnessMax, brightness);
945 aura::Window* window = GetWindowToAnimateForOverscroll();
946 window->layer()->SetLayerBrightness(brightness);
949 void WebContentsViewAura::AttachTouchEditableToRenderView() {
950 if (!touch_editable_)
952 RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
953 web_contents_->GetRenderWidgetHostView());
954 touch_editable_->AttachToView(rwhva);
957 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y) {
958 if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
959 web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
962 ////////////////////////////////////////////////////////////////////////////////
963 // WebContentsViewAura, WebContentsView implementation:
965 gfx::NativeView WebContentsViewAura::GetNativeView() const {
966 return window_.get();
969 gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
970 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
971 return rwhv ? rwhv->GetNativeView() : NULL;
974 gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
975 return window_->GetToplevelWindow();
978 void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
979 *out = window_->GetBoundsInScreen();
982 void WebContentsViewAura::SizeContents(const gfx::Size& size) {
983 gfx::Rect bounds = window_->bounds();
984 if (bounds.size() != size) {
985 bounds.set_size(size);
986 window_->SetBounds(bounds);
988 // Our size matches what we want but the renderers size may not match.
989 // Pretend we were resized so that the renderers size is updated too.
990 SizeChangedCommon(size);
994 void WebContentsViewAura::Focus() {
995 if (web_contents_->GetInterstitialPage()) {
996 web_contents_->GetInterstitialPage()->Focus();
1000 if (delegate_.get() && delegate_->Focus())
1003 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1008 void WebContentsViewAura::SetInitialFocus() {
1009 if (web_contents_->FocusLocationBarByDefault())
1010 web_contents_->SetFocusToLocationBar(false);
1015 void WebContentsViewAura::StoreFocus() {
1017 delegate_->StoreFocus();
1020 void WebContentsViewAura::RestoreFocus() {
1022 delegate_->RestoreFocus();
1025 DropData* WebContentsViewAura::GetDropData() const {
1026 return current_drop_data_.get();
1029 gfx::Rect WebContentsViewAura::GetViewBounds() const {
1030 return window_->GetBoundsInScreen();
1033 ////////////////////////////////////////////////////////////////////////////////
1034 // WebContentsViewAura, WebContentsView implementation:
1036 void WebContentsViewAura::CreateView(
1037 const gfx::Size& initial_size, gfx::NativeView context) {
1038 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1039 // if the bookmark bar is not shown and you create a new tab). The right
1040 // value is set shortly after this, so its safe to ignore.
1042 aura::Env::CreateInstance(true);
1043 window_.reset(new aura::Window(this));
1044 window_->set_owned_by_parent(false);
1045 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
1046 window_->SetTransparent(false);
1047 window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
1048 aura::Window* root_window = context ? context->GetRootWindow() : NULL;
1050 // There are places where there is no context currently because object
1051 // hierarchies are built before they're attached to a Widget. (See
1052 // views::WebView as an example; GetWidget() returns NULL at the point
1053 // where we are created.)
1055 // It should be OK to not set a default parent since such users will
1056 // explicitly add this WebContentsViewAura to their tree after they create
1059 aura::client::ParentWindowWithContext(
1060 window_.get(), root_window, root_window->GetBoundsInScreen());
1063 window_->layer()->SetMasksToBounds(true);
1064 window_->SetName("WebContentsViewAura");
1066 // WindowObserver is not interesting and is problematic for Browser Plugin
1068 // The use cases for WindowObserver do not apply to Browser Plugins:
1069 // 1) guests do not support NPAPI plugins.
1070 // 2) guests' window bounds are supposed to come from its embedder.
1071 if (!web_contents_->GetRenderProcessHost()->IsGuest())
1072 window_observer_.reset(new WindowObserver(this));
1074 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1075 // Hence, we save a reference to it locally. Similar model is used on other
1076 // platforms as well.
1078 drag_dest_delegate_ = delegate_->GetDragDestDelegate();
1081 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
1082 RenderWidgetHost* render_widget_host) {
1083 if (render_widget_host->GetView()) {
1084 // During testing, the view will already be set up in most cases to the
1085 // test view, so we don't want to clobber it with a real one. To verify that
1086 // this actually is happening (and somebody isn't accidentally creating the
1087 // view twice), we check for the RVH Factory, which will be set when we're
1088 // making special ones (which go along with the special views).
1089 DCHECK(RenderViewHostFactory::has_factory());
1090 return static_cast<RenderWidgetHostViewBase*>(
1091 render_widget_host->GetView());
1094 RenderWidgetHostViewBase* view = new RenderWidgetHostViewAura(
1095 render_widget_host);
1096 view->InitAsChild(NULL);
1097 GetNativeView()->AddChild(view->GetNativeView());
1099 if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1100 navigation_overlay_->StartObserving();
1103 RenderWidgetHostImpl* host_impl =
1104 RenderWidgetHostImpl::From(render_widget_host);
1106 if (!host_impl->is_hidden())
1109 // We listen to drag drop events in the newly created view's window.
1110 aura::client::SetDragDropDelegate(view->GetNativeView(), this);
1112 if (host_impl->overscroll_controller() &&
1113 (!web_contents_->GetDelegate() ||
1114 web_contents_->GetDelegate()->CanOverscrollContent())) {
1115 InstallOverscrollControllerDelegate(host_impl);
1118 AttachTouchEditableToRenderView();
1122 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
1123 RenderWidgetHost* render_widget_host) {
1124 return new RenderWidgetHostViewAura(render_widget_host);
1127 void WebContentsViewAura::SetPageTitle(const base::string16& title) {
1128 window_->set_title(title);
1131 void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
1134 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
1135 if (navigation_overlay_.get() && navigation_overlay_->has_window())
1136 navigation_overlay_->StartObserving();
1137 AttachTouchEditableToRenderView();
1140 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
1141 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
1142 web_contents_->GetRenderViewHost());
1144 host->SetOverscrollControllerEnabled(enabled);
1146 InstallOverscrollControllerDelegate(host);
1150 navigation_overlay_.reset();
1151 else if (!navigation_overlay_)
1152 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1155 ////////////////////////////////////////////////////////////////////////////////
1156 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1158 void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
1159 const ContextMenuParams& params) {
1160 if (touch_editable_) {
1161 touch_editable_->EndTouchEditing(false);
1164 delegate_->ShowContextMenu(render_frame_host, params);
1165 // WARNING: we may have been deleted during the call to ShowContextMenu().
1169 void WebContentsViewAura::StartDragging(
1170 const DropData& drop_data,
1171 blink::WebDragOperationsMask operations,
1172 const gfx::ImageSkia& image,
1173 const gfx::Vector2d& image_offset,
1174 const DragEventSourceInfo& event_info) {
1175 aura::Window* root_window = GetNativeView()->GetRootWindow();
1176 if (!aura::client::GetDragDropClient(root_window)) {
1177 web_contents_->SystemDragEnded();
1181 if (touch_editable_)
1182 touch_editable_->EndTouchEditing(false);
1184 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
1185 PrepareDragData(drop_data, provider, web_contents_);
1187 ui::OSExchangeData data(provider); // takes ownership of |provider|.
1189 if (!image.isNull()) {
1190 drag_utils::SetDragImageOnDataObject(image,
1191 gfx::Size(image.width(), image.height()), image_offset, &data);
1194 scoped_ptr<WebDragSourceAura> drag_source(
1195 new WebDragSourceAura(GetNativeView(), web_contents_));
1197 // We need to enable recursive tasks on the message loop so we can get
1198 // updates while in the system DoDragDrop loop.
1201 gfx::NativeView content_native_view = GetContentNativeView();
1202 base::MessageLoop::ScopedNestableTaskAllower allow(
1203 base::MessageLoop::current());
1204 result_op = aura::client::GetDragDropClient(root_window)
1205 ->StartDragAndDrop(data,
1207 content_native_view,
1208 event_info.event_location,
1209 ConvertFromWeb(operations),
1210 event_info.event_source);
1213 // Bail out immediately if the contents view window is gone. Note that it is
1214 // not safe to access any class members in this case since |this| may already
1215 // be destroyed. The local variable |drag_source| will still be valid though,
1216 // so we can use it to determine if the window is gone.
1217 if (!drag_source->window()) {
1218 // Note that in this case, we don't need to call SystemDragEnded() since the
1219 // renderer is going away.
1223 EndDrag(ConvertToWeb(result_op));
1224 web_contents_->SystemDragEnded();
1227 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
1228 current_drag_op_ = operation;
1231 void WebContentsViewAura::GotFocus() {
1232 if (web_contents_->GetDelegate())
1233 web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
1236 void WebContentsViewAura::TakeFocus(bool reverse) {
1237 if (web_contents_->GetDelegate() &&
1238 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1240 delegate_->TakeFocus(reverse);
1244 ////////////////////////////////////////////////////////////////////////////////
1245 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1247 gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
1248 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1249 if (!rwhv || !rwhv->IsShowing())
1252 return rwhv->GetViewBounds();
1255 void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1256 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1259 aura::Window* target = GetWindowToAnimateForOverscroll();
1260 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
1261 settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
1262 gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y);
1263 gfx::Transform transform;
1265 // Vertical overscrolls don't participate in the navigation gesture.
1266 if (current_overscroll_gesture_ != OVERSCROLL_NORTH &&
1267 current_overscroll_gesture_ != OVERSCROLL_SOUTH) {
1268 transform.Translate(translate.x(), translate.y());
1269 target->SetTransform(transform);
1270 UpdateOverscrollWindowBrightness(delta_x);
1273 OverscrollUpdateForWebContentsDelegate(translate.y());
1276 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1277 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
1278 OverscrollUpdateForWebContentsDelegate(0);
1279 NavigationControllerImpl& controller = web_contents_->GetController();
1280 if (ShouldNavigateForward(controller, mode) ||
1281 ShouldNavigateBack(controller, mode)) {
1282 CompleteOverscrollNavigation(mode);
1286 ResetOverscrollTransform();
1289 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1290 OverscrollMode new_mode) {
1291 // Reset any in-progress overscroll animation first.
1292 ResetOverscrollTransform();
1294 if (new_mode != OVERSCROLL_NONE && touch_editable_)
1295 touch_editable_->OverscrollStarted();
1297 if (new_mode == OVERSCROLL_NONE ||
1298 !GetContentNativeView() ||
1299 ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
1300 navigation_overlay_.get() && navigation_overlay_->has_window())) {
1301 current_overscroll_gesture_ = OVERSCROLL_NONE;
1302 OverscrollUpdateForWebContentsDelegate(0);
1304 aura::Window* target = GetWindowToAnimateForOverscroll();
1306 StopObservingImplicitAnimations();
1307 target->layer()->GetAnimator()->AbortAllAnimations();
1309 // Cleanup state of the content window first, because that can reset the
1310 // value of |current_overscroll_gesture_|.
1311 PrepareContentWindowForOverscroll();
1313 current_overscroll_gesture_ = new_mode;
1314 if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
1315 current_overscroll_gesture_ == OVERSCROLL_WEST)
1316 PrepareOverscrollWindow();
1318 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
1320 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1323 ////////////////////////////////////////////////////////////////////////////////
1324 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1326 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1327 overscroll_shadow_.reset();
1329 if (ShouldNavigateForward(web_contents_->GetController(),
1330 completed_overscroll_gesture_)) {
1331 web_contents_->GetController().GoForward();
1332 PrepareOverscrollNavigationOverlay();
1333 } else if (ShouldNavigateBack(web_contents_->GetController(),
1334 completed_overscroll_gesture_)) {
1335 web_contents_->GetController().GoBack();
1336 PrepareOverscrollNavigationOverlay();
1338 if (touch_editable_)
1339 touch_editable_->OverscrollCompleted();
1342 aura::Window* content = GetContentNativeView();
1344 content->SetTransform(gfx::Transform());
1345 content->layer()->SetLayerBrightness(0.f);
1347 current_overscroll_gesture_ = OVERSCROLL_NONE;
1348 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1349 overscroll_window_.reset();
1352 ////////////////////////////////////////////////////////////////////////////////
1353 // WebContentsViewAura, aura::WindowDelegate implementation:
1355 gfx::Size WebContentsViewAura::GetMinimumSize() const {
1359 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1363 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1364 const gfx::Rect& new_bounds) {
1365 SizeChangedCommon(new_bounds.size());
1367 delegate_->SizeChanged(new_bounds.size());
1369 // Constrained web dialogs, need to be kept centered over our content area.
1370 for (size_t i = 0; i < window_->children().size(); i++) {
1371 if (window_->children()[i]->GetProperty(
1372 aura::client::kConstrainedWindowKey)) {
1373 gfx::Rect bounds = window_->children()[i]->bounds();
1375 gfx::Point((new_bounds.width() - bounds.width()) / 2,
1376 (new_bounds.height() - bounds.height()) / 2));
1377 window_->children()[i]->SetBounds(bounds);
1382 gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1383 return gfx::kNullCursor;
1386 int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1390 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1391 aura::Window* child,
1392 const gfx::Point& location) {
1396 bool WebContentsViewAura::CanFocus() {
1397 // Do not take the focus if the render widget host view aura is gone or
1398 // is in the process of shutting down because neither the view window nor
1399 // this window can handle key events.
1400 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
1401 web_contents_->GetRenderWidgetHostView());
1402 if (view != NULL && !view->IsClosing())
1408 void WebContentsViewAura::OnCaptureLost() {
1411 void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
1414 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1415 float device_scale_factor) {
1418 void WebContentsViewAura::OnWindowDestroying(aura::Window* window) {
1419 // This means the destructor is going to be called soon. If there is an
1420 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1421 // then destroying it in the WebContentsViewAura destructor can trigger other
1422 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1423 // destroy the overscroll window here.
1424 navigation_overlay_.reset();
1425 overscroll_window_.reset();
1428 void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) {
1431 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1433 web_contents_->WasShown();
1435 web_contents_->WasHidden();
1438 bool WebContentsViewAura::HasHitTestMask() const {
1442 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1445 ////////////////////////////////////////////////////////////////////////////////
1446 // WebContentsViewAura, ui::EventHandler implementation:
1448 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1451 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1452 if (!web_contents_->GetDelegate())
1455 switch (event->type()) {
1456 case ui::ET_MOUSE_PRESSED:
1457 web_contents_->GetDelegate()->ActivateContents(web_contents_);
1459 case ui::ET_MOUSE_MOVED:
1460 case ui::ET_MOUSE_EXITED:
1461 web_contents_->GetDelegate()->ContentsMouseEvent(
1463 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1464 event->type() == ui::ET_MOUSE_MOVED);
1471 ////////////////////////////////////////////////////////////////////////////////
1472 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1474 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1475 if (drag_dest_delegate_)
1476 drag_dest_delegate_->DragInitialize(web_contents_);
1478 current_drop_data_.reset(new DropData());
1480 PrepareDropData(current_drop_data_.get(), event.data());
1481 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1483 gfx::Point screen_pt =
1484 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1485 current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1486 web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1487 *current_drop_data_.get(), event.location(), screen_pt, op,
1488 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1490 if (drag_dest_delegate_) {
1491 drag_dest_delegate_->OnReceiveDragData(event.data());
1492 drag_dest_delegate_->OnDragEnter();
1496 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1497 DCHECK(current_rvh_for_drag_);
1498 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1499 OnDragEntered(event);
1501 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1502 gfx::Point screen_pt =
1503 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1504 web_contents_->GetRenderViewHost()->DragTargetDragOver(
1505 event.location(), screen_pt, op,
1506 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1508 if (drag_dest_delegate_)
1509 drag_dest_delegate_->OnDragOver();
1511 return ConvertFromWeb(current_drag_op_);
1514 void WebContentsViewAura::OnDragExited() {
1515 DCHECK(current_rvh_for_drag_);
1516 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1519 web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1520 if (drag_dest_delegate_)
1521 drag_dest_delegate_->OnDragLeave();
1523 current_drop_data_.reset();
1526 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1527 DCHECK(current_rvh_for_drag_);
1528 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1529 OnDragEntered(event);
1531 web_contents_->GetRenderViewHost()->DragTargetDrop(
1533 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1534 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1535 if (drag_dest_delegate_)
1536 drag_dest_delegate_->OnDrop();
1537 current_drop_data_.reset();
1538 return ConvertFromWeb(current_drag_op_);
1541 } // namespace content