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/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/web_contents/aura/gesture_nav_simple.h"
23 #include "content/browser/web_contents/aura/image_window_delegate.h"
24 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
25 #include "content/browser/web_contents/aura/shadow_layer_delegate.h"
26 #include "content/browser/web_contents/aura/window_slider.h"
27 #include "content/browser/web_contents/touch_editable_impl_aura.h"
28 #include "content/browser/web_contents/web_contents_impl.h"
29 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/notification_observer.h"
31 #include "content/public/browser/notification_registrar.h"
32 #include "content/public/browser/notification_source.h"
33 #include "content/public/browser/notification_types.h"
34 #include "content/public/browser/overscroll_configuration.h"
35 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/render_widget_host.h"
37 #include "content/public/browser/render_widget_host_view.h"
38 #include "content/public/browser/web_contents_delegate.h"
39 #include "content/public/browser/web_contents_observer.h"
40 #include "content/public/browser/web_contents_view_delegate.h"
41 #include "content/public/browser/web_drag_dest_delegate.h"
42 #include "content/public/common/content_client.h"
43 #include "content/public/common/content_switches.h"
44 #include "content/public/common/drop_data.h"
45 #include "net/base/filename_util.h"
46 #include "third_party/WebKit/public/web/WebInputEvent.h"
47 #include "ui/aura/client/aura_constants.h"
48 #include "ui/aura/client/window_tree_client.h"
49 #include "ui/aura/env.h"
50 #include "ui/aura/window.h"
51 #include "ui/aura/window_observer.h"
52 #include "ui/aura/window_tree_host.h"
53 #include "ui/aura/window_tree_host_observer.h"
54 #include "ui/base/clipboard/clipboard.h"
55 #include "ui/base/clipboard/custom_data_helper.h"
56 #include "ui/base/dragdrop/drag_drop_types.h"
57 #include "ui/base/dragdrop/drag_utils.h"
58 #include "ui/base/dragdrop/drop_target_event.h"
59 #include "ui/base/dragdrop/os_exchange_data.h"
60 #include "ui/base/hit_test.h"
61 #include "ui/compositor/layer.h"
62 #include "ui/compositor/scoped_layer_animation_settings.h"
63 #include "ui/events/event.h"
64 #include "ui/events/event_utils.h"
65 #include "ui/gfx/canvas.h"
66 #include "ui/gfx/image/image.h"
67 #include "ui/gfx/image/image_png_rep.h"
68 #include "ui/gfx/image/image_skia.h"
69 #include "ui/gfx/screen.h"
70 #include "ui/wm/public/drag_drop_client.h"
71 #include "ui/wm/public/drag_drop_delegate.h"
74 WebContentsView
* CreateWebContentsView(
75 WebContentsImpl
* web_contents
,
76 WebContentsViewDelegate
* delegate
,
77 RenderViewHostDelegateView
** render_view_host_delegate_view
) {
78 WebContentsViewAura
* rv
= new WebContentsViewAura(web_contents
, delegate
);
79 *render_view_host_delegate_view
= rv
;
85 bool IsScrollEndEffectEnabled() {
86 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
87 switches::kScrollEndEffect
) == "1";
90 bool ShouldNavigateForward(const NavigationController
& controller
,
91 OverscrollMode mode
) {
92 return mode
== (base::i18n::IsRTL() ? OVERSCROLL_EAST
: OVERSCROLL_WEST
) &&
93 controller
.CanGoForward();
96 bool ShouldNavigateBack(const NavigationController
& controller
,
97 OverscrollMode mode
) {
98 return mode
== (base::i18n::IsRTL() ? OVERSCROLL_WEST
: OVERSCROLL_EAST
) &&
99 controller
.CanGoBack();
102 RenderWidgetHostViewAura
* ToRenderWidgetHostViewAura(
103 RenderWidgetHostView
* view
) {
104 if (!view
|| RenderViewHostFactory::has_factory())
105 return NULL
; // Can't cast to RenderWidgetHostViewAura in unit tests.
107 RenderViewHost
* rvh
= RenderViewHost::From(view
->GetRenderWidgetHost());
108 WebContentsImpl
* web_contents
= static_cast<WebContentsImpl
*>(
109 rvh
? WebContents::FromRenderViewHost(rvh
) : NULL
);
110 if (BrowserPluginGuest::IsGuest(web_contents
))
112 return static_cast<RenderWidgetHostViewAura
*>(view
);
115 // The window delegate for the overscroll window. This redirects trackpad events
116 // to the web-contents window. The delegate destroys itself when the window is
118 class OverscrollWindowDelegate
: public ImageWindowDelegate
{
120 OverscrollWindowDelegate(WebContentsImpl
* web_contents
,
121 OverscrollMode overscroll_mode
)
122 : web_contents_(web_contents
),
123 forward_events_(true) {
124 const NavigationControllerImpl
& controller
= web_contents
->GetController();
125 const NavigationEntryImpl
* entry
= NULL
;
126 if (ShouldNavigateForward(controller
, overscroll_mode
)) {
127 entry
= NavigationEntryImpl::FromNavigationEntry(
128 controller
.GetEntryAtOffset(1));
129 } else if (ShouldNavigateBack(controller
, overscroll_mode
)) {
130 entry
= NavigationEntryImpl::FromNavigationEntry(
131 controller
.GetEntryAtOffset(-1));
135 if (entry
&& entry
->screenshot().get()) {
136 std::vector
<gfx::ImagePNGRep
> image_reps
;
137 image_reps
.push_back(gfx::ImagePNGRep(entry
->screenshot(),
138 ui::GetScaleFactorForNativeView(web_contents_window())));
139 image
= gfx::Image(image_reps
);
144 void stop_forwarding_events() { forward_events_
= false; }
147 virtual ~OverscrollWindowDelegate() {}
149 aura::Window
* web_contents_window() {
150 return web_contents_
->GetView()->GetContentNativeView();
153 // Overridden from ui::EventHandler.
154 virtual void OnScrollEvent(ui::ScrollEvent
* event
) OVERRIDE
{
155 if (forward_events_
&& web_contents_window())
156 web_contents_window()->delegate()->OnScrollEvent(event
);
159 virtual void OnGestureEvent(ui::GestureEvent
* event
) OVERRIDE
{
160 if (forward_events_
&& web_contents_window())
161 web_contents_window()->delegate()->OnGestureEvent(event
);
164 WebContentsImpl
* web_contents_
;
166 // The window is displayed both during the gesture, and after the gesture
167 // while the navigation is in progress. During the gesture, it is necessary to
168 // forward input events to the content page (e.g. when the overscroll window
169 // slides under the cursor and starts receiving scroll events). However, once
170 // the gesture is complete, and the window is being displayed as an overlay
171 // window during navigation, events should not be forwarded anymore.
172 bool forward_events_
;
174 DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate
);
177 // Listens to all mouse drag events during a drag and drop and sends them to
179 class WebDragSourceAura
: public NotificationObserver
{
181 WebDragSourceAura(aura::Window
* window
, WebContentsImpl
* contents
)
183 contents_(contents
) {
185 NOTIFICATION_WEB_CONTENTS_DISCONNECTED
,
186 Source
<WebContents
>(contents
));
189 virtual ~WebDragSourceAura() {
192 // NotificationObserver:
193 virtual void Observe(int type
,
194 const NotificationSource
& source
,
195 const NotificationDetails
& details
) OVERRIDE
{
196 if (type
!= NOTIFICATION_WEB_CONTENTS_DISCONNECTED
)
199 // Cancel the drag if it is still in progress.
200 aura::client::DragDropClient
* dnd_client
=
201 aura::client::GetDragDropClient(window_
->GetRootWindow());
202 if (dnd_client
&& dnd_client
->IsDragDropInProgress())
203 dnd_client
->DragCancel();
209 aura::Window
* window() const { return window_
; }
212 aura::Window
* window_
;
213 WebContentsImpl
* contents_
;
214 NotificationRegistrar registrar_
;
216 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura
);
219 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
220 // Fill out the OSExchangeData with a file contents, synthesizing a name if
222 void PrepareDragForFileContents(const DropData
& drop_data
,
223 ui::OSExchangeData::Provider
* provider
) {
224 base::FilePath file_name
=
225 base::FilePath::FromUTF16Unsafe(drop_data
.file_description_filename
);
226 // Images without ALT text will only have a file extension so we need to
227 // synthesize one from the provided extension and URL.
228 if (file_name
.BaseName().RemoveExtension().empty()) {
229 const base::FilePath::StringType extension
= file_name
.Extension();
230 // Retrieve the name from the URL.
231 file_name
= net::GenerateFileName(drop_data
.url
, "", "", "", "", "")
232 .ReplaceExtension(extension
);
234 provider
->SetFileContents(file_name
, drop_data
.file_contents
);
239 void PrepareDragForDownload(
240 const DropData
& drop_data
,
241 ui::OSExchangeData::Provider
* provider
,
242 WebContentsImpl
* web_contents
) {
243 const GURL
& page_url
= web_contents
->GetLastCommittedURL();
244 const std::string
& page_encoding
= web_contents
->GetEncoding();
246 // Parse the download metadata.
247 base::string16 mime_type
;
248 base::FilePath file_name
;
250 if (!ParseDownloadMetadata(drop_data
.download_metadata
,
256 // Generate the file name based on both mime type and proposed file name.
257 std::string default_name
=
258 GetContentClient()->browser()->GetDefaultDownloadName();
259 base::FilePath generated_download_file_name
=
260 net::GenerateFileName(download_url
,
263 base::UTF16ToUTF8(file_name
.value()),
264 base::UTF16ToUTF8(mime_type
),
267 // http://crbug.com/332579
268 base::ThreadRestrictions::ScopedAllowIO allow_file_operations
;
270 base::FilePath temp_dir_path
;
271 if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
275 base::FilePath download_path
=
276 temp_dir_path
.Append(generated_download_file_name
);
278 // We cannot know when the target application will be done using the temporary
279 // file, so schedule it to be deleted after rebooting.
280 base::DeleteFileAfterReboot(download_path
);
281 base::DeleteFileAfterReboot(temp_dir_path
);
283 // Provide the data as file (CF_HDROP). A temporary download file with the
284 // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
285 scoped_refptr
<DragDownloadFile
> download_file
=
286 new DragDownloadFile(
290 Referrer(page_url
, drop_data
.referrer_policy
),
293 ui::OSExchangeData::DownloadFileInfo
file_download(base::FilePath(),
294 download_file
.get());
295 provider
->SetDownloadFileInfo(file_download
);
297 #endif // defined(OS_WIN)
299 // Returns the CustomFormat to store file system files.
300 const ui::OSExchangeData::CustomFormat
& GetFileSystemFileCustomFormat() {
301 static const char kFormatString
[] = "chromium/x-file-system-files";
302 CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat
,
304 (ui::Clipboard::GetFormatType(kFormatString
)));
308 // Writes file system files to the pickle.
309 void WriteFileSystemFilesToPickle(
310 const std::vector
<DropData::FileSystemFileInfo
>& file_system_files
,
312 pickle
->WriteUInt64(file_system_files
.size());
313 for (size_t i
= 0; i
< file_system_files
.size(); ++i
) {
314 pickle
->WriteString(file_system_files
[i
].url
.spec());
315 pickle
->WriteInt64(file_system_files
[i
].size
);
319 // Reads file system files from the pickle.
320 bool ReadFileSystemFilesFromPickle(
321 const Pickle
& pickle
,
322 std::vector
<DropData::FileSystemFileInfo
>* file_system_files
) {
323 PickleIterator
iter(pickle
);
325 uint64 num_files
= 0;
326 if (!pickle
.ReadUInt64(&iter
, &num_files
))
328 file_system_files
->resize(num_files
);
330 for (uint64 i
= 0; i
< num_files
; ++i
) {
331 std::string url_string
;
333 if (!pickle
.ReadString(&iter
, &url_string
) ||
334 !pickle
.ReadInt64(&iter
, &size
))
337 GURL
url(url_string
);
341 (*file_system_files
)[i
].url
= url
;
342 (*file_system_files
)[i
].size
= size
;
347 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
348 void PrepareDragData(const DropData
& drop_data
,
349 ui::OSExchangeData::Provider
* provider
,
350 WebContentsImpl
* web_contents
) {
351 provider
->MarkOriginatedFromRenderer();
353 // Put download before file contents to prefer the download of a image over
354 // its thumbnail link.
355 if (!drop_data
.download_metadata
.empty())
356 PrepareDragForDownload(drop_data
, provider
, web_contents
);
358 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
359 // We set the file contents before the URL because the URL also sets file
360 // contents (to a .URL shortcut). We want to prefer file content data over
361 // a shortcut so we add it first.
362 if (!drop_data
.file_contents
.empty())
363 PrepareDragForFileContents(drop_data
, provider
);
365 // Call SetString() before SetURL() when we actually have a custom string.
366 // SetURL() will itself do SetString() when a string hasn't been set yet,
367 // but we want to prefer drop_data.text.string() over the URL string if it
369 if (!drop_data
.text
.string().empty())
370 provider
->SetString(drop_data
.text
.string());
371 if (drop_data
.url
.is_valid())
372 provider
->SetURL(drop_data
.url
, drop_data
.url_title
);
373 if (!drop_data
.html
.string().empty())
374 provider
->SetHtml(drop_data
.html
.string(), drop_data
.html_base_url
);
375 if (!drop_data
.filenames
.empty())
376 provider
->SetFilenames(drop_data
.filenames
);
377 if (!drop_data
.file_system_files
.empty()) {
379 WriteFileSystemFilesToPickle(drop_data
.file_system_files
, &pickle
);
380 provider
->SetPickledData(GetFileSystemFileCustomFormat(), pickle
);
382 if (!drop_data
.custom_data
.empty()) {
384 ui::WriteCustomDataToPickle(drop_data
.custom_data
, &pickle
);
385 provider
->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
390 // Utility to fill a DropData object from ui::OSExchangeData.
391 void PrepareDropData(DropData
* drop_data
, const ui::OSExchangeData
& data
) {
392 drop_data
->did_originate_from_renderer
= data
.DidOriginateFromRenderer();
394 base::string16 plain_text
;
395 data
.GetString(&plain_text
);
396 if (!plain_text
.empty())
397 drop_data
->text
= base::NullableString16(plain_text
, false);
400 base::string16 url_title
;
402 ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES
, &url
, &url_title
);
403 if (url
.is_valid()) {
404 drop_data
->url
= url
;
405 drop_data
->url_title
= url_title
;
410 data
.GetHtml(&html
, &html_base_url
);
412 drop_data
->html
= base::NullableString16(html
, false);
413 if (html_base_url
.is_valid())
414 drop_data
->html_base_url
= html_base_url
;
416 data
.GetFilenames(&drop_data
->filenames
);
419 std::vector
<DropData::FileSystemFileInfo
> file_system_files
;
420 if (data
.GetPickledData(GetFileSystemFileCustomFormat(), &pickle
) &&
421 ReadFileSystemFilesFromPickle(pickle
, &file_system_files
))
422 drop_data
->file_system_files
= file_system_files
;
424 if (data
.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle
))
425 ui::ReadCustomDataIntoMap(
426 pickle
.data(), pickle
.size(), &drop_data
->custom_data
);
429 // Utilities to convert between blink::WebDragOperationsMask and
430 // ui::DragDropTypes.
431 int ConvertFromWeb(blink::WebDragOperationsMask ops
) {
432 int drag_op
= ui::DragDropTypes::DRAG_NONE
;
433 if (ops
& blink::WebDragOperationCopy
)
434 drag_op
|= ui::DragDropTypes::DRAG_COPY
;
435 if (ops
& blink::WebDragOperationMove
)
436 drag_op
|= ui::DragDropTypes::DRAG_MOVE
;
437 if (ops
& blink::WebDragOperationLink
)
438 drag_op
|= ui::DragDropTypes::DRAG_LINK
;
442 blink::WebDragOperationsMask
ConvertToWeb(int drag_op
) {
443 int web_drag_op
= blink::WebDragOperationNone
;
444 if (drag_op
& ui::DragDropTypes::DRAG_COPY
)
445 web_drag_op
|= blink::WebDragOperationCopy
;
446 if (drag_op
& ui::DragDropTypes::DRAG_MOVE
)
447 web_drag_op
|= blink::WebDragOperationMove
;
448 if (drag_op
& ui::DragDropTypes::DRAG_LINK
)
449 web_drag_op
|= blink::WebDragOperationLink
;
450 return (blink::WebDragOperationsMask
) web_drag_op
;
453 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags
) {
454 int web_input_event_modifiers
= 0;
455 if (aura_event_flags
& ui::EF_SHIFT_DOWN
)
456 web_input_event_modifiers
|= blink::WebInputEvent::ShiftKey
;
457 if (aura_event_flags
& ui::EF_CONTROL_DOWN
)
458 web_input_event_modifiers
|= blink::WebInputEvent::ControlKey
;
459 if (aura_event_flags
& ui::EF_ALT_DOWN
)
460 web_input_event_modifiers
|= blink::WebInputEvent::AltKey
;
461 if (aura_event_flags
& ui::EF_COMMAND_DOWN
)
462 web_input_event_modifiers
|= blink::WebInputEvent::MetaKey
;
463 return web_input_event_modifiers
;
468 class WebContentsViewAura::WindowObserver
469 : public aura::WindowObserver
, public aura::WindowTreeHostObserver
{
471 explicit WindowObserver(WebContentsViewAura
* view
)
474 view_
->window_
->AddObserver(this);
477 if (view_
->window_
->GetRootWindow())
478 view_
->window_
->GetRootWindow()->AddObserver(this);
482 virtual ~WindowObserver() {
483 view_
->window_
->RemoveObserver(this);
484 if (view_
->window_
->GetHost())
485 view_
->window_
->GetHost()->RemoveObserver(this);
487 host_window_
->RemoveObserver(this);
490 const aura::Window::Windows
& children
= host_window_
->children();
491 for (size_t i
= 0; i
< children
.size(); ++i
)
492 children
[i
]->RemoveObserver(this);
495 aura::Window
* root_window
= view_
->window_
->GetRootWindow();
497 root_window
->RemoveObserver(this);
498 const aura::Window::Windows
& root_children
= root_window
->children();
499 for (size_t i
= 0; i
< root_children
.size(); ++i
)
500 root_children
[i
]->RemoveObserver(this);
505 // Overridden from aura::WindowObserver:
507 // Constrained windows are added as children of the parent's parent's view
508 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
509 // so that it can update the plugins' cutout rects accordingly.
510 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
511 // going to be deprecated in a year, this is ok for now. The test for this is
512 // PrintPreviewTest.WindowedNPAPIPluginHidden.
513 virtual void OnWindowAdded(aura::Window
* new_window
) OVERRIDE
{
514 if (!new_window
->Contains(view_
->window_
.get())) {
515 // Skip the case when the parent moves to the root window.
516 if (new_window
!= host_window_
) {
517 // Observe sibling windows of the WebContents, or children of the root
519 if (new_window
->parent() == host_window_
||
520 new_window
->parent() == view_
->window_
->GetRootWindow()) {
521 new_window
->AddObserver(this);
526 if (new_window
->parent() == host_window_
) {
527 UpdateConstrainedWindows(NULL
);
531 virtual void OnWillRemoveWindow(aura::Window
* window
) OVERRIDE
{
532 if (window
== view_
->window_
)
535 window
->RemoveObserver(this);
536 UpdateConstrainedWindows(window
);
539 virtual void OnWindowVisibilityChanged(aura::Window
* window
,
540 bool visible
) OVERRIDE
{
541 if (window
== view_
->window_
||
542 window
->parent() == host_window_
||
543 window
->parent() == view_
->window_
->GetRootWindow()) {
544 UpdateConstrainedWindows(NULL
);
549 virtual void OnWindowParentChanged(aura::Window
* window
,
550 aura::Window
* parent
) OVERRIDE
{
551 if (window
!= view_
->window_
)
554 // Use the new parent's root window for calculating HiDPI subpixel offset.
555 RenderWidgetHostViewAura
* rwhv
= ToRenderWidgetHostViewAura(
556 view_
->web_contents_
->GetRenderWidgetHostView());
558 rwhv
->SnapToPhysicalPixelBoundary();
560 aura::Window
* host_window
=
561 window
->GetProperty(aura::client::kHostWindowKey
);
563 host_window
= parent
;
566 host_window_
->RemoveObserver(this);
570 const aura::Window::Windows
& children
= host_window_
->children();
571 for (size_t i
= 0; i
< children
.size(); ++i
)
572 children
[i
]->RemoveObserver(this);
575 rwhv
->UpdateConstrainedWindowRects(std::vector
<gfx::Rect
>());
578 // When we get parented to the root window, the code below will watch the
579 // host window, aka root window. Since we already watch the root window on
580 // Windows, unregister first so that the debug check doesn't fire.
581 if (host_window
&& host_window
== window
->GetRootWindow())
582 host_window
->RemoveObserver(this);
584 // We need to undo the above if we were parented to the root window and then
585 // got parented to another window. At that point, the code before the ifdef
586 // would have stopped watching the root window.
587 if (window
->GetRootWindow() &&
588 host_window
!= window
->GetRootWindow() &&
589 !window
->GetRootWindow()->HasObserver(this)) {
590 window
->GetRootWindow()->AddObserver(this);
594 host_window_
= host_window
;
596 host_window
->AddObserver(this);
598 if (host_window
!= window
->GetRootWindow()) {
599 const aura::Window::Windows
& children
= host_window
->children();
600 for (size_t i
= 0; i
< children
.size(); ++i
) {
601 if (!children
[i
]->Contains(view_
->window_
.get()))
602 children
[i
]->AddObserver(this);
609 virtual void OnWindowBoundsChanged(aura::Window
* window
,
610 const gfx::Rect
& old_bounds
,
611 const gfx::Rect
& new_bounds
) OVERRIDE
{
612 if (window
== host_window_
|| window
== view_
->window_
) {
614 if (view_
->touch_editable_
)
615 view_
->touch_editable_
->UpdateEditingController();
618 UpdateConstrainedWindows(NULL
);
623 virtual void OnWindowDestroying(aura::Window
* window
) OVERRIDE
{
624 if (window
== host_window_
) {
625 host_window_
->RemoveObserver(this);
630 virtual void OnWindowAddedToRootWindow(aura::Window
* window
) OVERRIDE
{
631 if (window
== view_
->window_
) {
632 window
->GetHost()->AddObserver(this);
634 if (!window
->GetRootWindow()->HasObserver(this))
635 window
->GetRootWindow()->AddObserver(this);
640 virtual void OnWindowRemovingFromRootWindow(aura::Window
* window
,
641 aura::Window
* new_root
) OVERRIDE
{
642 if (window
== view_
->window_
) {
643 window
->GetHost()->RemoveObserver(this);
645 window
->GetRootWindow()->RemoveObserver(this);
647 const aura::Window::Windows
& root_children
=
648 window
->GetRootWindow()->children();
649 for (size_t i
= 0; i
< root_children
.size(); ++i
) {
650 if (root_children
[i
] != view_
->window_
&&
651 root_children
[i
] != host_window_
) {
652 root_children
[i
]->RemoveObserver(this);
659 // Overridden WindowTreeHostObserver:
660 virtual void OnHostMoved(const aura::WindowTreeHost
* host
,
661 const gfx::Point
& new_origin
) OVERRIDE
{
663 "WebContentsViewAura::WindowObserver::OnHostMoved",
664 "new_origin", new_origin
.ToString());
666 // This is for the desktop case (i.e. Aura desktop).
671 void SendScreenRects() {
672 RenderWidgetHostImpl::From(view_
->web_contents_
->GetRenderViewHost())->
677 void UpdateConstrainedWindows(aura::Window
* exclude
) {
678 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
679 view_
->web_contents_
->GetRenderWidgetHostView());
683 std::vector
<gfx::Rect
> constrained_windows
;
685 const aura::Window::Windows
& children
= host_window_
->children();
686 for (size_t i
= 0; i
< children
.size(); ++i
) {
687 if (!children
[i
]->Contains(view_
->window_
.get()) &&
688 children
[i
] != exclude
&&
689 children
[i
]->IsVisible()) {
690 constrained_windows
.push_back(children
[i
]->GetBoundsInRootWindow());
695 aura::Window
* root_window
= view_
->window_
->GetRootWindow();
696 const aura::Window::Windows
& root_children
= root_window
->children();
698 for (size_t i
= 0; i
< root_children
.size(); ++i
) {
699 if (root_children
[i
]->IsVisible() &&
700 !root_children
[i
]->Contains(view_
->window_
.get())) {
701 constrained_windows
.push_back(
702 root_children
[i
]->GetBoundsInRootWindow());
707 view
->UpdateConstrainedWindowRects(constrained_windows
);
711 WebContentsViewAura
* view_
;
713 // The parent window that hosts the constrained windows. We cache the old host
714 // view so that we can unregister when it's not the parent anymore.
715 aura::Window
* host_window_
;
717 DISALLOW_COPY_AND_ASSIGN(WindowObserver
);
720 ////////////////////////////////////////////////////////////////////////////////
721 // WebContentsViewAura, public:
723 WebContentsViewAura::WebContentsViewAura(
724 WebContentsImpl
* web_contents
,
725 WebContentsViewDelegate
* delegate
)
726 : web_contents_(web_contents
),
728 current_drag_op_(blink::WebDragOperationNone
),
729 drag_dest_delegate_(NULL
),
730 current_rvh_for_drag_(NULL
),
731 overscroll_change_brightness_(false),
732 current_overscroll_gesture_(OVERSCROLL_NONE
),
733 completed_overscroll_gesture_(OVERSCROLL_NONE
),
734 touch_editable_(TouchEditableImplAura::Create()),
735 is_or_was_visible_(false) {
738 ////////////////////////////////////////////////////////////////////////////////
739 // WebContentsViewAura, private:
741 WebContentsViewAura::~WebContentsViewAura() {
745 window_observer_
.reset();
746 window_
->RemoveObserver(this);
748 // Window needs a valid delegate during its destructor, so we explicitly
753 void WebContentsViewAura::SetTouchEditableForTest(
754 TouchEditableImplAura
* touch_editable
) {
755 touch_editable_
.reset(touch_editable
);
756 AttachTouchEditableToRenderView();
759 void WebContentsViewAura::SizeChangedCommon(const gfx::Size
& size
) {
760 if (web_contents_
->GetInterstitialPage())
761 web_contents_
->GetInterstitialPage()->SetSize(size
);
762 RenderWidgetHostView
* rwhv
=
763 web_contents_
->GetRenderWidgetHostView();
768 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops
) {
769 aura::Window
* root_window
= GetNativeView()->GetRootWindow();
770 gfx::Point screen_loc
=
771 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
772 gfx::Point client_loc
= screen_loc
;
773 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
774 aura::Window
* window
= rvh
->GetView()->GetNativeView();
775 aura::Window::ConvertPointToTarget(root_window
, window
, &client_loc
);
778 web_contents_
->DragSourceEndedAt(client_loc
.x(), client_loc
.y(),
779 screen_loc
.x(), screen_loc
.y(), ops
);
782 void WebContentsViewAura::InstallOverscrollControllerDelegate(
783 RenderWidgetHostViewAura
* view
) {
784 const std::string value
= CommandLine::ForCurrentProcess()->
785 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation
);
787 navigation_overlay_
.reset();
791 navigation_overlay_
.reset();
792 if (!gesture_nav_simple_
)
793 gesture_nav_simple_
.reset(new GestureNavSimple(web_contents_
));
794 view
->overscroll_controller()->set_delegate(gesture_nav_simple_
.get());
797 view
->overscroll_controller()->set_delegate(this);
798 if (!navigation_overlay_
)
799 navigation_overlay_
.reset(new OverscrollNavigationOverlay(web_contents_
));
802 void WebContentsViewAura::PrepareOverscrollWindow() {
803 // If there is an existing |overscroll_window_| which is in the middle of an
804 // animation, then destroying the window here causes the animation to be
805 // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
806 // callback, and that tries to reset |overscroll_window_| again, causing a
807 // double-free. So use a temporary variable here.
808 if (overscroll_window_
) {
809 base::AutoReset
<OverscrollMode
> reset_state(¤t_overscroll_gesture_
,
810 current_overscroll_gesture_
);
811 scoped_ptr
<aura::Window
> reset_window(overscroll_window_
.release());
814 OverscrollWindowDelegate
* overscroll_delegate
= new OverscrollWindowDelegate(
816 current_overscroll_gesture_
);
817 overscroll_window_
.reset(new aura::Window(overscroll_delegate
));
818 overscroll_window_
->SetType(ui::wm::WINDOW_TYPE_CONTROL
);
819 overscroll_window_
->SetTransparent(true);
820 overscroll_window_
->Init(aura::WINDOW_LAYER_TEXTURED
);
821 overscroll_window_
->layer()->SetMasksToBounds(false);
822 overscroll_window_
->SetName("OverscrollOverlay");
824 overscroll_change_brightness_
= overscroll_delegate
->has_image();
825 window_
->AddChild(overscroll_window_
.get());
827 gfx::Rect bounds
= gfx::Rect(window_
->bounds().size());
828 if (ShouldNavigateForward(web_contents_
->GetController(),
829 current_overscroll_gesture_
)) {
830 // The overlay will be sliding in from the right edge towards the left in
831 // non-RTL, or sliding in from the left edge towards the right in RTL.
832 // So position the overlay window accordingly.
833 bounds
.Offset(base::i18n::IsRTL() ? -bounds
.width() : bounds
.width(), 0);
836 aura::Window
* animate_window
= GetWindowToAnimateForOverscroll();
837 if (animate_window
== overscroll_window_
)
838 window_
->StackChildAbove(overscroll_window_
.get(), GetContentNativeView());
840 window_
->StackChildBelow(overscroll_window_
.get(), GetContentNativeView());
842 UpdateOverscrollWindowBrightness(0.f
);
844 overscroll_window_
->SetBounds(bounds
);
845 overscroll_window_
->Show();
847 overscroll_shadow_
.reset(new ShadowLayerDelegate(animate_window
->layer()));
850 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
851 StopObservingImplicitAnimations();
852 aura::Window
* content
= GetContentNativeView();
853 content
->layer()->GetAnimator()->AbortAllAnimations();
854 content
->SetTransform(gfx::Transform());
855 content
->layer()->SetLayerBrightness(0.f
);
858 void WebContentsViewAura::ResetOverscrollTransform() {
859 if (!web_contents_
->GetRenderWidgetHostView())
861 aura::Window
* target
= GetWindowToAnimateForOverscroll();
865 ui::ScopedLayerAnimationSettings
settings(target
->layer()->GetAnimator());
866 settings
.SetPreemptionStrategy(
867 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET
);
868 settings
.SetTweenType(gfx::Tween::EASE_OUT
);
869 settings
.AddObserver(this);
870 target
->SetTransform(gfx::Transform());
873 ui::ScopedLayerAnimationSettings
settings(target
->layer()->GetAnimator());
874 settings
.SetPreemptionStrategy(
875 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET
);
876 settings
.SetTweenType(gfx::Tween::EASE_OUT
);
877 UpdateOverscrollWindowBrightness(0.f
);
881 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode
) {
882 if (!web_contents_
->GetRenderWidgetHostView())
885 // Animate out the current view first. Navigate to the requested history at
886 // the end of the animation.
887 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
890 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
891 current_overscroll_gesture_
, OVERSCROLL_COUNT
);
892 OverscrollWindowDelegate
* delegate
= static_cast<OverscrollWindowDelegate
*>(
893 overscroll_window_
->delegate());
894 delegate
->stop_forwarding_events();
896 completed_overscroll_gesture_
= mode
;
897 aura::Window
* target
= GetWindowToAnimateForOverscroll();
898 ui::ScopedLayerAnimationSettings
settings(target
->layer()->GetAnimator());
899 settings
.SetPreemptionStrategy(
900 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET
);
901 settings
.SetTweenType(gfx::Tween::EASE_OUT
);
902 settings
.AddObserver(this);
903 gfx::Transform transform
;
905 web_contents_
->GetRenderWidgetHostView()->GetViewBounds().width();
906 int translate_x
= mode
== OVERSCROLL_WEST
? -content_width
: content_width
;
907 transform
.Translate(translate_x
, 0);
908 target
->SetTransform(transform
);
909 UpdateOverscrollWindowBrightness(translate_x
);
912 aura::Window
* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
913 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
916 return ShouldNavigateForward(web_contents_
->GetController(),
917 current_overscroll_gesture_
) ?
918 overscroll_window_
.get() : GetContentNativeView();
921 gfx::Vector2d
WebContentsViewAura::GetTranslationForOverscroll(int delta_x
,
923 if (current_overscroll_gesture_
== OVERSCROLL_NORTH
||
924 current_overscroll_gesture_
== OVERSCROLL_SOUTH
) {
925 return gfx::Vector2d(0, delta_y
);
927 // For horizontal overscroll, scroll freely if a navigation is possible. Do a
928 // resistive scroll otherwise.
929 const NavigationControllerImpl
& controller
= web_contents_
->GetController();
930 const gfx::Rect
& bounds
= GetViewBounds();
931 if (ShouldNavigateForward(controller
, current_overscroll_gesture_
))
932 return gfx::Vector2d(std::max(-bounds
.width(), delta_x
), 0);
933 else if (ShouldNavigateBack(controller
, current_overscroll_gesture_
))
934 return gfx::Vector2d(std::min(bounds
.width(), delta_x
), 0);
935 return gfx::Vector2d();
938 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
939 OverscrollWindowDelegate
* delegate
= static_cast<OverscrollWindowDelegate
*>(
940 overscroll_window_
->delegate());
941 overscroll_window_
->SchedulePaintInRect(
942 gfx::Rect(overscroll_window_
->bounds().size()));
943 overscroll_window_
->SetBounds(gfx::Rect(window_
->bounds().size()));
944 overscroll_window_
->SetTransform(gfx::Transform());
945 navigation_overlay_
->SetOverlayWindow(overscroll_window_
.Pass(),
947 navigation_overlay_
->StartObserving();
950 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x
) {
951 if (!overscroll_change_brightness_
)
954 const float kBrightnessMin
= -.1f
;
955 const float kBrightnessMax
= -.01f
;
957 float ratio
= fabs(delta_x
) / GetViewBounds().width();
958 ratio
= std::min(1.f
, ratio
);
959 if (base::i18n::IsRTL())
961 float brightness
= current_overscroll_gesture_
== OVERSCROLL_WEST
?
962 kBrightnessMin
+ ratio
* (kBrightnessMax
- kBrightnessMin
) :
963 kBrightnessMax
- ratio
* (kBrightnessMax
- kBrightnessMin
);
964 brightness
= std::max(kBrightnessMin
, brightness
);
965 brightness
= std::min(kBrightnessMax
, brightness
);
966 aura::Window
* window
= GetWindowToAnimateForOverscroll();
967 window
->layer()->SetLayerBrightness(brightness
);
970 void WebContentsViewAura::AttachTouchEditableToRenderView() {
971 if (!touch_editable_
)
973 RenderWidgetHostViewAura
* rwhva
= ToRenderWidgetHostViewAura(
974 web_contents_
->GetRenderWidgetHostView());
975 touch_editable_
->AttachToView(rwhva
);
978 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y
) {
979 if (web_contents_
->GetDelegate() && IsScrollEndEffectEnabled())
980 web_contents_
->GetDelegate()->OverscrollUpdate(delta_y
);
983 ////////////////////////////////////////////////////////////////////////////////
984 // WebContentsViewAura, WebContentsView implementation:
986 gfx::NativeView
WebContentsViewAura::GetNativeView() const {
987 return window_
.get();
990 gfx::NativeView
WebContentsViewAura::GetContentNativeView() const {
991 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
992 return rwhv
? rwhv
->GetNativeView() : NULL
;
995 gfx::NativeWindow
WebContentsViewAura::GetTopLevelNativeWindow() const {
996 return window_
->GetToplevelWindow();
999 void WebContentsViewAura::GetContainerBounds(gfx::Rect
*out
) const {
1000 *out
= window_
->GetBoundsInScreen();
1003 void WebContentsViewAura::SizeContents(const gfx::Size
& size
) {
1004 gfx::Rect bounds
= window_
->bounds();
1005 if (bounds
.size() != size
) {
1006 bounds
.set_size(size
);
1007 window_
->SetBounds(bounds
);
1009 // Our size matches what we want but the renderers size may not match.
1010 // Pretend we were resized so that the renderers size is updated too.
1011 SizeChangedCommon(size
);
1015 void WebContentsViewAura::Focus() {
1016 if (web_contents_
->GetInterstitialPage()) {
1017 web_contents_
->GetInterstitialPage()->Focus();
1021 if (delegate_
.get() && delegate_
->Focus())
1024 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
1029 void WebContentsViewAura::SetInitialFocus() {
1030 if (web_contents_
->FocusLocationBarByDefault())
1031 web_contents_
->SetFocusToLocationBar(false);
1036 void WebContentsViewAura::StoreFocus() {
1038 delegate_
->StoreFocus();
1041 void WebContentsViewAura::RestoreFocus() {
1043 delegate_
->RestoreFocus();
1046 DropData
* WebContentsViewAura::GetDropData() const {
1047 return current_drop_data_
.get();
1050 gfx::Rect
WebContentsViewAura::GetViewBounds() const {
1051 return window_
->GetBoundsInScreen();
1054 ////////////////////////////////////////////////////////////////////////////////
1055 // WebContentsViewAura, WebContentsView implementation:
1057 void WebContentsViewAura::CreateView(
1058 const gfx::Size
& initial_size
, gfx::NativeView context
) {
1059 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1060 // if the bookmark bar is not shown and you create a new tab). The right
1061 // value is set shortly after this, so its safe to ignore.
1063 aura::Env::CreateInstance(true);
1064 window_
.reset(new aura::Window(this));
1065 window_
->set_owned_by_parent(false);
1066 window_
->SetType(ui::wm::WINDOW_TYPE_CONTROL
);
1067 window_
->SetTransparent(false);
1068 window_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
1069 window_
->AddObserver(this);
1070 aura::Window
* root_window
= context
? context
->GetRootWindow() : NULL
;
1072 // There are places where there is no context currently because object
1073 // hierarchies are built before they're attached to a Widget. (See
1074 // views::WebView as an example; GetWidget() returns NULL at the point
1075 // where we are created.)
1077 // It should be OK to not set a default parent since such users will
1078 // explicitly add this WebContentsViewAura to their tree after they create
1081 aura::client::ParentWindowWithContext(
1082 window_
.get(), root_window
, root_window
->GetBoundsInScreen());
1085 window_
->layer()->SetMasksToBounds(true);
1086 window_
->SetName("WebContentsViewAura");
1088 // WindowObserver is not interesting and is problematic for Browser Plugin
1090 // The use cases for WindowObserver do not apply to Browser Plugins:
1091 // 1) guests do not support NPAPI plugins.
1092 // 2) guests' window bounds are supposed to come from its embedder.
1093 if (!BrowserPluginGuest::IsGuest(web_contents_
))
1094 window_observer_
.reset(new WindowObserver(this));
1096 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1097 // Hence, we save a reference to it locally. Similar model is used on other
1098 // platforms as well.
1100 drag_dest_delegate_
= delegate_
->GetDragDestDelegate();
1103 RenderWidgetHostViewBase
* WebContentsViewAura::CreateViewForWidget(
1104 RenderWidgetHost
* render_widget_host
) {
1105 if (render_widget_host
->GetView()) {
1106 // During testing, the view will already be set up in most cases to the
1107 // test view, so we don't want to clobber it with a real one. To verify that
1108 // this actually is happening (and somebody isn't accidentally creating the
1109 // view twice), we check for the RVH Factory, which will be set when we're
1110 // making special ones (which go along with the special views).
1111 DCHECK(RenderViewHostFactory::has_factory());
1112 return static_cast<RenderWidgetHostViewBase
*>(
1113 render_widget_host
->GetView());
1116 RenderWidgetHostViewAura
* view
=
1117 new RenderWidgetHostViewAura(render_widget_host
);
1118 view
->InitAsChild(NULL
);
1119 GetNativeView()->AddChild(view
->GetNativeView());
1121 if (navigation_overlay_
.get() && navigation_overlay_
->has_window()) {
1122 navigation_overlay_
->StartObserving();
1125 RenderWidgetHostImpl
* host_impl
=
1126 RenderWidgetHostImpl::From(render_widget_host
);
1128 if (!host_impl
->is_hidden())
1131 // We listen to drag drop events in the newly created view's window.
1132 aura::client::SetDragDropDelegate(view
->GetNativeView(), this);
1134 if (view
->overscroll_controller() &&
1135 (!web_contents_
->GetDelegate() ||
1136 web_contents_
->GetDelegate()->CanOverscrollContent())) {
1137 InstallOverscrollControllerDelegate(view
);
1140 AttachTouchEditableToRenderView();
1144 RenderWidgetHostViewBase
* WebContentsViewAura::CreateViewForPopupWidget(
1145 RenderWidgetHost
* render_widget_host
) {
1146 return new RenderWidgetHostViewAura(render_widget_host
);
1149 void WebContentsViewAura::SetPageTitle(const base::string16
& title
) {
1150 window_
->SetTitle(title
);
1153 void WebContentsViewAura::RenderViewCreated(RenderViewHost
* host
) {
1156 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost
* host
) {
1157 if (navigation_overlay_
.get() && navigation_overlay_
->has_window())
1158 navigation_overlay_
->StartObserving();
1159 AttachTouchEditableToRenderView();
1162 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled
) {
1163 RenderWidgetHostViewAura
* view
=
1164 ToRenderWidgetHostViewAura(web_contents_
->GetRenderWidgetHostView());
1166 view
->SetOverscrollControllerEnabled(enabled
);
1168 InstallOverscrollControllerDelegate(view
);
1172 navigation_overlay_
.reset();
1173 else if (!navigation_overlay_
)
1174 navigation_overlay_
.reset(new OverscrollNavigationOverlay(web_contents_
));
1177 ////////////////////////////////////////////////////////////////////////////////
1178 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1180 void WebContentsViewAura::ShowContextMenu(RenderFrameHost
* render_frame_host
,
1181 const ContextMenuParams
& params
) {
1182 if (touch_editable_
) {
1183 touch_editable_
->EndTouchEditing(false);
1186 delegate_
->ShowContextMenu(render_frame_host
, params
);
1187 // WARNING: we may have been deleted during the call to ShowContextMenu().
1191 void WebContentsViewAura::StartDragging(
1192 const DropData
& drop_data
,
1193 blink::WebDragOperationsMask operations
,
1194 const gfx::ImageSkia
& image
,
1195 const gfx::Vector2d
& image_offset
,
1196 const DragEventSourceInfo
& event_info
) {
1197 aura::Window
* root_window
= GetNativeView()->GetRootWindow();
1198 if (!aura::client::GetDragDropClient(root_window
)) {
1199 web_contents_
->SystemDragEnded();
1203 if (touch_editable_
)
1204 touch_editable_
->EndTouchEditing(false);
1206 ui::OSExchangeData::Provider
* provider
= ui::OSExchangeData::CreateProvider();
1207 PrepareDragData(drop_data
, provider
, web_contents_
);
1209 ui::OSExchangeData
data(provider
); // takes ownership of |provider|.
1211 if (!image
.isNull())
1212 drag_utils::SetDragImageOnDataObject(image
, image_offset
, &data
);
1214 scoped_ptr
<WebDragSourceAura
> drag_source(
1215 new WebDragSourceAura(GetNativeView(), web_contents_
));
1217 // We need to enable recursive tasks on the message loop so we can get
1218 // updates while in the system DoDragDrop loop.
1221 gfx::NativeView content_native_view
= GetContentNativeView();
1222 base::MessageLoop::ScopedNestableTaskAllower
allow(
1223 base::MessageLoop::current());
1224 result_op
= aura::client::GetDragDropClient(root_window
)
1225 ->StartDragAndDrop(data
,
1227 content_native_view
,
1228 event_info
.event_location
,
1229 ConvertFromWeb(operations
),
1230 event_info
.event_source
);
1233 // Bail out immediately if the contents view window is gone. Note that it is
1234 // not safe to access any class members in this case since |this| may already
1235 // be destroyed. The local variable |drag_source| will still be valid though,
1236 // so we can use it to determine if the window is gone.
1237 if (!drag_source
->window()) {
1238 // Note that in this case, we don't need to call SystemDragEnded() since the
1239 // renderer is going away.
1243 EndDrag(ConvertToWeb(result_op
));
1244 web_contents_
->SystemDragEnded();
1247 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation
) {
1248 current_drag_op_
= operation
;
1251 void WebContentsViewAura::GotFocus() {
1252 if (web_contents_
->GetDelegate())
1253 web_contents_
->GetDelegate()->WebContentsFocused(web_contents_
);
1256 void WebContentsViewAura::TakeFocus(bool reverse
) {
1257 if (web_contents_
->GetDelegate() &&
1258 !web_contents_
->GetDelegate()->TakeFocus(web_contents_
, reverse
) &&
1260 delegate_
->TakeFocus(reverse
);
1264 ////////////////////////////////////////////////////////////////////////////////
1265 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1267 gfx::Rect
WebContentsViewAura::GetVisibleBounds() const {
1268 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
1269 if (!rwhv
|| !rwhv
->IsShowing())
1272 return rwhv
->GetViewBounds();
1275 void WebContentsViewAura::OnOverscrollUpdate(float delta_x
, float delta_y
) {
1276 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
1279 aura::Window
* target
= GetWindowToAnimateForOverscroll();
1280 gfx::Vector2d translate
= GetTranslationForOverscroll(delta_x
, delta_y
);
1281 gfx::Transform transform
;
1283 // Vertical overscrolls don't participate in the navigation gesture.
1284 if (current_overscroll_gesture_
!= OVERSCROLL_NORTH
&&
1285 current_overscroll_gesture_
!= OVERSCROLL_SOUTH
) {
1286 transform
.Translate(translate
.x(), translate
.y());
1287 target
->SetTransform(transform
);
1288 UpdateOverscrollWindowBrightness(delta_x
);
1291 OverscrollUpdateForWebContentsDelegate(translate
.y());
1294 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode
) {
1295 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode
, OVERSCROLL_COUNT
);
1296 OverscrollUpdateForWebContentsDelegate(0);
1297 NavigationControllerImpl
& controller
= web_contents_
->GetController();
1298 if (ShouldNavigateForward(controller
, mode
) ||
1299 ShouldNavigateBack(controller
, mode
)) {
1300 CompleteOverscrollNavigation(mode
);
1304 ResetOverscrollTransform();
1307 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode
,
1308 OverscrollMode new_mode
) {
1309 // Reset any in-progress overscroll animation first.
1310 ResetOverscrollTransform();
1312 if (new_mode
!= OVERSCROLL_NONE
&& touch_editable_
)
1313 touch_editable_
->OverscrollStarted();
1315 if (new_mode
== OVERSCROLL_NONE
||
1316 !GetContentNativeView() ||
1317 ((new_mode
== OVERSCROLL_EAST
|| new_mode
== OVERSCROLL_WEST
) &&
1318 navigation_overlay_
.get() && navigation_overlay_
->has_window())) {
1319 current_overscroll_gesture_
= OVERSCROLL_NONE
;
1320 OverscrollUpdateForWebContentsDelegate(0);
1322 aura::Window
* target
= GetWindowToAnimateForOverscroll();
1324 StopObservingImplicitAnimations();
1325 target
->layer()->GetAnimator()->AbortAllAnimations();
1327 // Cleanup state of the content window first, because that can reset the
1328 // value of |current_overscroll_gesture_|.
1329 PrepareContentWindowForOverscroll();
1331 current_overscroll_gesture_
= new_mode
;
1332 if (current_overscroll_gesture_
== OVERSCROLL_EAST
||
1333 current_overscroll_gesture_
== OVERSCROLL_WEST
)
1334 PrepareOverscrollWindow();
1336 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode
, OVERSCROLL_COUNT
);
1338 completed_overscroll_gesture_
= OVERSCROLL_NONE
;
1341 ////////////////////////////////////////////////////////////////////////////////
1342 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1344 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1345 overscroll_shadow_
.reset();
1347 if (ShouldNavigateForward(web_contents_
->GetController(),
1348 completed_overscroll_gesture_
)) {
1349 web_contents_
->GetController().GoForward();
1350 PrepareOverscrollNavigationOverlay();
1351 } else if (ShouldNavigateBack(web_contents_
->GetController(),
1352 completed_overscroll_gesture_
)) {
1353 web_contents_
->GetController().GoBack();
1354 PrepareOverscrollNavigationOverlay();
1356 if (touch_editable_
)
1357 touch_editable_
->OverscrollCompleted();
1360 aura::Window
* content
= GetContentNativeView();
1362 content
->SetTransform(gfx::Transform());
1363 content
->layer()->SetLayerBrightness(0.f
);
1365 current_overscroll_gesture_
= OVERSCROLL_NONE
;
1366 completed_overscroll_gesture_
= OVERSCROLL_NONE
;
1367 overscroll_window_
.reset();
1370 ////////////////////////////////////////////////////////////////////////////////
1371 // WebContentsViewAura, aura::WindowDelegate implementation:
1373 gfx::Size
WebContentsViewAura::GetMinimumSize() const {
1377 gfx::Size
WebContentsViewAura::GetMaximumSize() const {
1381 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect
& old_bounds
,
1382 const gfx::Rect
& new_bounds
) {
1383 SizeChangedCommon(new_bounds
.size());
1385 delegate_
->SizeChanged(new_bounds
.size());
1387 // Constrained web dialogs, need to be kept centered over our content area.
1388 for (size_t i
= 0; i
< window_
->children().size(); i
++) {
1389 if (window_
->children()[i
]->GetProperty(
1390 aura::client::kConstrainedWindowKey
)) {
1391 gfx::Rect bounds
= window_
->children()[i
]->bounds();
1393 gfx::Point((new_bounds
.width() - bounds
.width()) / 2,
1394 (new_bounds
.height() - bounds
.height()) / 2));
1395 window_
->children()[i
]->SetBounds(bounds
);
1400 gfx::NativeCursor
WebContentsViewAura::GetCursor(const gfx::Point
& point
) {
1401 return gfx::kNullCursor
;
1404 int WebContentsViewAura::GetNonClientComponent(const gfx::Point
& point
) const {
1408 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1409 aura::Window
* child
,
1410 const gfx::Point
& location
) {
1414 bool WebContentsViewAura::CanFocus() {
1415 // Do not take the focus if the render widget host view aura is gone or
1416 // is in the process of shutting down because neither the view window nor
1417 // this window can handle key events.
1418 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
1419 web_contents_
->GetRenderWidgetHostView());
1420 if (view
!= NULL
&& !view
->IsClosing())
1426 void WebContentsViewAura::OnCaptureLost() {
1429 void WebContentsViewAura::OnPaint(gfx::Canvas
* canvas
) {
1432 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1433 float device_scale_factor
) {
1436 void WebContentsViewAura::OnWindowDestroying(aura::Window
* window
) {
1437 // This means the destructor is going to be called soon. If there is an
1438 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1439 // then destroying it in the WebContentsViewAura destructor can trigger other
1440 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1441 // destroy the overscroll window here.
1442 navigation_overlay_
.reset();
1443 overscroll_window_
.reset();
1446 void WebContentsViewAura::OnWindowDestroyed(aura::Window
* window
) {
1449 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible
) {
1452 bool WebContentsViewAura::HasHitTestMask() const {
1456 void WebContentsViewAura::GetHitTestMask(gfx::Path
* mask
) const {
1459 ////////////////////////////////////////////////////////////////////////////////
1460 // WebContentsViewAura, ui::EventHandler implementation:
1462 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent
* event
) {
1465 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent
* event
) {
1466 if (!web_contents_
->GetDelegate())
1469 switch (event
->type()) {
1470 case ui::ET_MOUSE_PRESSED
:
1471 web_contents_
->GetDelegate()->ActivateContents(web_contents_
);
1473 case ui::ET_MOUSE_MOVED
:
1474 case ui::ET_MOUSE_EXITED
:
1475 web_contents_
->GetDelegate()->ContentsMouseEvent(
1477 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1478 event
->type() == ui::ET_MOUSE_MOVED
);
1485 ////////////////////////////////////////////////////////////////////////////////
1486 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1488 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent
& event
) {
1489 current_rvh_for_drag_
= web_contents_
->GetRenderViewHost();
1490 current_drop_data_
.reset(new DropData());
1492 PrepareDropData(current_drop_data_
.get(), event
.data());
1493 blink::WebDragOperationsMask op
= ConvertToWeb(event
.source_operations());
1495 // Give the delegate an opportunity to cancel the drag.
1496 if (!web_contents_
->GetDelegate()->CanDragEnter(web_contents_
,
1497 *current_drop_data_
.get(),
1499 current_drop_data_
.reset(NULL
);
1503 if (drag_dest_delegate_
)
1504 drag_dest_delegate_
->DragInitialize(web_contents_
);
1506 gfx::Point screen_pt
=
1507 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1508 web_contents_
->GetRenderViewHost()->DragTargetDragEnter(
1509 *current_drop_data_
.get(), event
.location(), screen_pt
, op
,
1510 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1512 if (drag_dest_delegate_
) {
1513 drag_dest_delegate_
->OnReceiveDragData(event
.data());
1514 drag_dest_delegate_
->OnDragEnter();
1518 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent
& event
) {
1519 DCHECK(current_rvh_for_drag_
);
1520 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1521 OnDragEntered(event
);
1523 if (!current_drop_data_
)
1524 return ui::DragDropTypes::DRAG_NONE
;
1526 blink::WebDragOperationsMask op
= ConvertToWeb(event
.source_operations());
1527 gfx::Point screen_pt
=
1528 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1529 web_contents_
->GetRenderViewHost()->DragTargetDragOver(
1530 event
.location(), screen_pt
, op
,
1531 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1533 if (drag_dest_delegate_
)
1534 drag_dest_delegate_
->OnDragOver();
1536 return ConvertFromWeb(current_drag_op_
);
1539 void WebContentsViewAura::OnDragExited() {
1540 DCHECK(current_rvh_for_drag_
);
1541 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1544 if (!current_drop_data_
)
1547 web_contents_
->GetRenderViewHost()->DragTargetDragLeave();
1548 if (drag_dest_delegate_
)
1549 drag_dest_delegate_
->OnDragLeave();
1551 current_drop_data_
.reset();
1554 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent
& event
) {
1555 DCHECK(current_rvh_for_drag_
);
1556 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1557 OnDragEntered(event
);
1559 if (!current_drop_data_
)
1560 return ui::DragDropTypes::DRAG_NONE
;
1562 web_contents_
->GetRenderViewHost()->DragTargetDrop(
1564 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1565 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1566 if (drag_dest_delegate_
)
1567 drag_dest_delegate_
->OnDrop();
1568 current_drop_data_
.reset();
1569 return ConvertFromWeb(current_drag_op_
);
1572 void WebContentsViewAura::OnWindowParentChanged(aura::Window
* window
,
1573 aura::Window
* parent
) {
1574 // Ignore any visibility changes in the hierarchy below.
1575 if (window
!= window_
.get() && window_
->Contains(window
))
1578 // On Windows we will get called with a parent of NULL as part of the shut
1579 // down process. As such we do only change the visibility when a parent gets
1582 UpdateWebContentsVisibility(window
->IsVisible());
1585 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window
* window
,
1587 // Ignore any visibility changes in the hierarchy below.
1588 if (window
!= window_
.get() && window_
->Contains(window
))
1591 UpdateWebContentsVisibility(visible
);
1594 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible
) {
1595 if (!is_or_was_visible_
) {
1596 // We should not hide the web contents before it was shown the first time,
1597 // since resources would immediately be destroyed and only re-created after
1598 // content got loaded. In this state the window content is undefined and can
1600 // However - the page load mechanism requires an activation call through a
1601 // visibility call to (re)load.
1603 is_or_was_visible_
= true;
1604 web_contents_
->WasShown();
1609 if (!web_contents_
->should_normally_be_visible())
1610 web_contents_
->WasShown();
1612 if (web_contents_
->should_normally_be_visible())
1613 web_contents_
->WasHidden();
1617 } // namespace content