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 base::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:
506 virtual void OnWindowHierarchyChanged(
507 const aura::WindowObserver::HierarchyChangeParams
& params
) OVERRIDE
{
508 if (params
.receiver
!= view_
->window_
.get() ||
509 !params
.target
->Contains(view_
->window_
.get())) {
513 // Use the new parent's root window for calculating HiDPI subpixel offset.
514 RenderWidgetHostViewAura
* rwhv
= ToRenderWidgetHostViewAura(
515 view_
->web_contents_
->GetRenderWidgetHostView());
517 rwhv
->SnapToPhysicalPixelBoundary();
521 // Constrained windows are added as children of the parent's parent's view
522 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
523 // so that it can update the plugins' cutout rects accordingly.
524 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
525 // going to be deprecated in a year, this is ok for now. The test for this is
526 // PrintPreviewTest.WindowedNPAPIPluginHidden.
527 virtual void OnWindowAdded(aura::Window
* new_window
) OVERRIDE
{
528 if (!new_window
->Contains(view_
->window_
.get())) {
529 // Skip the case when the parent moves to the root window.
530 if (new_window
!= host_window_
) {
531 // Observe sibling windows of the WebContents, or children of the root
533 if (new_window
->parent() == host_window_
||
534 new_window
->parent() == view_
->window_
->GetRootWindow()) {
535 new_window
->AddObserver(this);
540 if (new_window
->parent() == host_window_
) {
541 UpdateConstrainedWindows(NULL
);
545 virtual void OnWillRemoveWindow(aura::Window
* window
) OVERRIDE
{
546 if (window
== view_
->window_
)
549 window
->RemoveObserver(this);
550 UpdateConstrainedWindows(window
);
553 virtual void OnWindowVisibilityChanged(aura::Window
* window
,
554 bool visible
) OVERRIDE
{
555 if (window
== view_
->window_
||
556 window
->parent() == host_window_
||
557 window
->parent() == view_
->window_
->GetRootWindow()) {
558 UpdateConstrainedWindows(NULL
);
563 virtual void OnWindowParentChanged(aura::Window
* window
,
564 aura::Window
* parent
) OVERRIDE
{
565 if (window
!= view_
->window_
)
568 aura::Window
* host_window
=
569 window
->GetProperty(aura::client::kHostWindowKey
);
571 host_window
= parent
;
574 host_window_
->RemoveObserver(this);
578 const aura::Window::Windows
& children
= host_window_
->children();
579 for (size_t i
= 0; i
< children
.size(); ++i
)
580 children
[i
]->RemoveObserver(this);
581 RenderWidgetHostViewAura
* rwhv
= ToRenderWidgetHostViewAura(
582 view_
->web_contents_
->GetRenderWidgetHostView());
584 rwhv
->UpdateConstrainedWindowRects(std::vector
<gfx::Rect
>());
587 // When we get parented to the root window, the code below will watch the
588 // host window, aka root window. Since we already watch the root window on
589 // Windows, unregister first so that the debug check doesn't fire.
590 if (host_window
&& host_window
== window
->GetRootWindow())
591 host_window
->RemoveObserver(this);
593 // We need to undo the above if we were parented to the root window and then
594 // got parented to another window. At that point, the code before the ifdef
595 // would have stopped watching the root window.
596 if (window
->GetRootWindow() &&
597 host_window
!= window
->GetRootWindow() &&
598 !window
->GetRootWindow()->HasObserver(this)) {
599 window
->GetRootWindow()->AddObserver(this);
603 host_window_
= host_window
;
605 host_window
->AddObserver(this);
607 if (host_window
!= window
->GetRootWindow()) {
608 const aura::Window::Windows
& children
= host_window
->children();
609 for (size_t i
= 0; i
< children
.size(); ++i
) {
610 if (!children
[i
]->Contains(view_
->window_
.get()))
611 children
[i
]->AddObserver(this);
618 virtual void OnWindowBoundsChanged(aura::Window
* window
,
619 const gfx::Rect
& old_bounds
,
620 const gfx::Rect
& new_bounds
) OVERRIDE
{
621 if (window
== host_window_
|| window
== view_
->window_
) {
623 if (view_
->touch_editable_
)
624 view_
->touch_editable_
->UpdateEditingController();
627 UpdateConstrainedWindows(NULL
);
632 virtual void OnWindowDestroying(aura::Window
* window
) OVERRIDE
{
633 if (window
== host_window_
) {
634 host_window_
->RemoveObserver(this);
639 virtual void OnWindowAddedToRootWindow(aura::Window
* window
) OVERRIDE
{
640 if (window
== view_
->window_
) {
641 window
->GetHost()->AddObserver(this);
643 if (!window
->GetRootWindow()->HasObserver(this))
644 window
->GetRootWindow()->AddObserver(this);
649 virtual void OnWindowRemovingFromRootWindow(aura::Window
* window
,
650 aura::Window
* new_root
) OVERRIDE
{
651 if (window
== view_
->window_
) {
652 window
->GetHost()->RemoveObserver(this);
654 window
->GetRootWindow()->RemoveObserver(this);
656 const aura::Window::Windows
& root_children
=
657 window
->GetRootWindow()->children();
658 for (size_t i
= 0; i
< root_children
.size(); ++i
) {
659 if (root_children
[i
] != view_
->window_
&&
660 root_children
[i
] != host_window_
) {
661 root_children
[i
]->RemoveObserver(this);
668 // Overridden WindowTreeHostObserver:
669 virtual void OnHostMoved(const aura::WindowTreeHost
* host
,
670 const gfx::Point
& new_origin
) OVERRIDE
{
672 "WebContentsViewAura::WindowObserver::OnHostMoved",
673 "new_origin", new_origin
.ToString());
675 // This is for the desktop case (i.e. Aura desktop).
680 void SendScreenRects() {
681 RenderWidgetHostImpl::From(view_
->web_contents_
->GetRenderViewHost())->
686 void UpdateConstrainedWindows(aura::Window
* exclude
) {
687 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
688 view_
->web_contents_
->GetRenderWidgetHostView());
692 std::vector
<gfx::Rect
> constrained_windows
;
694 const aura::Window::Windows
& children
= host_window_
->children();
695 for (size_t i
= 0; i
< children
.size(); ++i
) {
696 if (!children
[i
]->Contains(view_
->window_
.get()) &&
697 children
[i
] != exclude
&&
698 children
[i
]->IsVisible()) {
699 constrained_windows
.push_back(children
[i
]->GetBoundsInRootWindow());
704 aura::Window
* root_window
= view_
->window_
->GetRootWindow();
705 const aura::Window::Windows
& root_children
= root_window
->children();
707 for (size_t i
= 0; i
< root_children
.size(); ++i
) {
708 if (root_children
[i
]->IsVisible() &&
709 !root_children
[i
]->Contains(view_
->window_
.get())) {
710 constrained_windows
.push_back(
711 root_children
[i
]->GetBoundsInRootWindow());
716 view
->UpdateConstrainedWindowRects(constrained_windows
);
720 WebContentsViewAura
* view_
;
722 // The parent window that hosts the constrained windows. We cache the old host
723 // view so that we can unregister when it's not the parent anymore.
724 aura::Window
* host_window_
;
726 DISALLOW_COPY_AND_ASSIGN(WindowObserver
);
729 ////////////////////////////////////////////////////////////////////////////////
730 // WebContentsViewAura, public:
732 WebContentsViewAura::WebContentsViewAura(
733 WebContentsImpl
* web_contents
,
734 WebContentsViewDelegate
* delegate
)
735 : web_contents_(web_contents
),
737 current_drag_op_(blink::WebDragOperationNone
),
738 drag_dest_delegate_(NULL
),
739 current_rvh_for_drag_(NULL
),
740 overscroll_change_brightness_(false),
741 current_overscroll_gesture_(OVERSCROLL_NONE
),
742 completed_overscroll_gesture_(OVERSCROLL_NONE
),
743 touch_editable_(TouchEditableImplAura::Create()),
744 is_or_was_visible_(false) {
747 ////////////////////////////////////////////////////////////////////////////////
748 // WebContentsViewAura, private:
750 WebContentsViewAura::~WebContentsViewAura() {
754 window_observer_
.reset();
755 window_
->RemoveObserver(this);
757 // Window needs a valid delegate during its destructor, so we explicitly
762 void WebContentsViewAura::SetTouchEditableForTest(
763 TouchEditableImplAura
* touch_editable
) {
764 touch_editable_
.reset(touch_editable
);
765 AttachTouchEditableToRenderView();
768 void WebContentsViewAura::SizeChangedCommon(const gfx::Size
& size
) {
769 if (web_contents_
->GetInterstitialPage())
770 web_contents_
->GetInterstitialPage()->SetSize(size
);
771 RenderWidgetHostView
* rwhv
=
772 web_contents_
->GetRenderWidgetHostView();
777 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops
) {
778 aura::Window
* root_window
= GetNativeView()->GetRootWindow();
779 gfx::Point screen_loc
=
780 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
781 gfx::Point client_loc
= screen_loc
;
782 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
783 aura::Window
* window
= rvh
->GetView()->GetNativeView();
784 aura::Window::ConvertPointToTarget(root_window
, window
, &client_loc
);
787 web_contents_
->DragSourceEndedAt(client_loc
.x(), client_loc
.y(),
788 screen_loc
.x(), screen_loc
.y(), ops
);
791 void WebContentsViewAura::InstallOverscrollControllerDelegate(
792 RenderWidgetHostViewAura
* view
) {
793 const std::string value
= base::CommandLine::ForCurrentProcess()->
794 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation
);
796 navigation_overlay_
.reset();
800 navigation_overlay_
.reset();
801 if (!gesture_nav_simple_
)
802 gesture_nav_simple_
.reset(new GestureNavSimple(web_contents_
));
803 view
->overscroll_controller()->set_delegate(gesture_nav_simple_
.get());
806 view
->overscroll_controller()->set_delegate(this);
807 if (!navigation_overlay_
)
808 navigation_overlay_
.reset(new OverscrollNavigationOverlay(web_contents_
));
811 void WebContentsViewAura::PrepareOverscrollWindow() {
812 // If there is an existing |overscroll_window_| which is in the middle of an
813 // animation, then destroying the window here causes the animation to be
814 // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
815 // callback, and that tries to reset |overscroll_window_| again, causing a
816 // double-free. So use a temporary variable here.
817 if (overscroll_window_
) {
818 base::AutoReset
<OverscrollMode
> reset_state(¤t_overscroll_gesture_
,
819 current_overscroll_gesture_
);
820 scoped_ptr
<aura::Window
> reset_window(overscroll_window_
.release());
823 OverscrollWindowDelegate
* overscroll_delegate
= new OverscrollWindowDelegate(
825 current_overscroll_gesture_
);
826 overscroll_window_
.reset(new aura::Window(overscroll_delegate
));
827 overscroll_window_
->SetType(ui::wm::WINDOW_TYPE_CONTROL
);
828 overscroll_window_
->SetTransparent(true);
829 overscroll_window_
->Init(aura::WINDOW_LAYER_TEXTURED
);
830 overscroll_window_
->layer()->SetMasksToBounds(false);
831 overscroll_window_
->SetName("OverscrollOverlay");
833 overscroll_change_brightness_
= overscroll_delegate
->has_image();
834 window_
->AddChild(overscroll_window_
.get());
836 gfx::Rect bounds
= gfx::Rect(window_
->bounds().size());
837 if (ShouldNavigateForward(web_contents_
->GetController(),
838 current_overscroll_gesture_
)) {
839 // The overlay will be sliding in from the right edge towards the left in
840 // non-RTL, or sliding in from the left edge towards the right in RTL.
841 // So position the overlay window accordingly.
842 bounds
.Offset(base::i18n::IsRTL() ? -bounds
.width() : bounds
.width(), 0);
845 aura::Window
* animate_window
= GetWindowToAnimateForOverscroll();
846 if (animate_window
== overscroll_window_
)
847 window_
->StackChildAbove(overscroll_window_
.get(), GetContentNativeView());
849 window_
->StackChildBelow(overscroll_window_
.get(), GetContentNativeView());
851 UpdateOverscrollWindowBrightness(0.f
);
853 overscroll_window_
->SetBounds(bounds
);
854 overscroll_window_
->Show();
856 overscroll_shadow_
.reset(new ShadowLayerDelegate(animate_window
->layer()));
859 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
860 StopObservingImplicitAnimations();
861 aura::Window
* content
= GetContentNativeView();
862 content
->layer()->GetAnimator()->AbortAllAnimations();
863 content
->SetTransform(gfx::Transform());
864 content
->layer()->SetLayerBrightness(0.f
);
867 void WebContentsViewAura::ResetOverscrollTransform() {
868 if (!web_contents_
->GetRenderWidgetHostView())
870 aura::Window
* target
= GetWindowToAnimateForOverscroll();
874 ui::ScopedLayerAnimationSettings
settings(target
->layer()->GetAnimator());
875 settings
.SetPreemptionStrategy(
876 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET
);
877 settings
.SetTweenType(gfx::Tween::EASE_OUT
);
878 settings
.AddObserver(this);
879 target
->SetTransform(gfx::Transform());
882 ui::ScopedLayerAnimationSettings
settings(target
->layer()->GetAnimator());
883 settings
.SetPreemptionStrategy(
884 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET
);
885 settings
.SetTweenType(gfx::Tween::EASE_OUT
);
886 UpdateOverscrollWindowBrightness(0.f
);
890 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode
) {
891 if (!web_contents_
->GetRenderWidgetHostView())
894 // Animate out the current view first. Navigate to the requested history at
895 // the end of the animation.
896 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
899 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
900 current_overscroll_gesture_
, OVERSCROLL_COUNT
);
901 OverscrollWindowDelegate
* delegate
= static_cast<OverscrollWindowDelegate
*>(
902 overscroll_window_
->delegate());
903 delegate
->stop_forwarding_events();
905 completed_overscroll_gesture_
= mode
;
906 aura::Window
* target
= GetWindowToAnimateForOverscroll();
907 ui::ScopedLayerAnimationSettings
settings(target
->layer()->GetAnimator());
908 settings
.SetPreemptionStrategy(
909 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET
);
910 settings
.SetTweenType(gfx::Tween::EASE_OUT
);
911 settings
.AddObserver(this);
912 gfx::Transform transform
;
914 web_contents_
->GetRenderWidgetHostView()->GetViewBounds().width();
915 int translate_x
= mode
== OVERSCROLL_WEST
? -content_width
: content_width
;
916 transform
.Translate(translate_x
, 0);
917 target
->SetTransform(transform
);
918 UpdateOverscrollWindowBrightness(translate_x
);
921 aura::Window
* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
922 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
925 return ShouldNavigateForward(web_contents_
->GetController(),
926 current_overscroll_gesture_
) ?
927 overscroll_window_
.get() : GetContentNativeView();
930 gfx::Vector2d
WebContentsViewAura::GetTranslationForOverscroll(int delta_x
,
932 if (current_overscroll_gesture_
== OVERSCROLL_NORTH
||
933 current_overscroll_gesture_
== OVERSCROLL_SOUTH
) {
934 return gfx::Vector2d(0, delta_y
);
936 // For horizontal overscroll, scroll freely if a navigation is possible. Do a
937 // resistive scroll otherwise.
938 const NavigationControllerImpl
& controller
= web_contents_
->GetController();
939 const gfx::Rect
& bounds
= GetViewBounds();
940 if (ShouldNavigateForward(controller
, current_overscroll_gesture_
))
941 return gfx::Vector2d(std::max(-bounds
.width(), delta_x
), 0);
942 else if (ShouldNavigateBack(controller
, current_overscroll_gesture_
))
943 return gfx::Vector2d(std::min(bounds
.width(), delta_x
), 0);
944 return gfx::Vector2d();
947 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
948 OverscrollWindowDelegate
* delegate
= static_cast<OverscrollWindowDelegate
*>(
949 overscroll_window_
->delegate());
950 overscroll_window_
->SchedulePaintInRect(
951 gfx::Rect(overscroll_window_
->bounds().size()));
952 overscroll_window_
->SetBounds(gfx::Rect(window_
->bounds().size()));
953 overscroll_window_
->SetTransform(gfx::Transform());
954 navigation_overlay_
->SetOverlayWindow(overscroll_window_
.Pass(),
956 navigation_overlay_
->StartObserving();
959 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x
) {
960 if (!overscroll_change_brightness_
)
963 const float kBrightnessMin
= -.1f
;
964 const float kBrightnessMax
= -.01f
;
966 float ratio
= fabs(delta_x
) / GetViewBounds().width();
967 ratio
= std::min(1.f
, ratio
);
968 if (base::i18n::IsRTL())
970 float brightness
= current_overscroll_gesture_
== OVERSCROLL_WEST
?
971 kBrightnessMin
+ ratio
* (kBrightnessMax
- kBrightnessMin
) :
972 kBrightnessMax
- ratio
* (kBrightnessMax
- kBrightnessMin
);
973 brightness
= std::max(kBrightnessMin
, brightness
);
974 brightness
= std::min(kBrightnessMax
, brightness
);
975 aura::Window
* window
= GetWindowToAnimateForOverscroll();
976 window
->layer()->SetLayerBrightness(brightness
);
979 void WebContentsViewAura::AttachTouchEditableToRenderView() {
980 if (!touch_editable_
)
982 RenderWidgetHostViewAura
* rwhva
= ToRenderWidgetHostViewAura(
983 web_contents_
->GetRenderWidgetHostView());
984 touch_editable_
->AttachToView(rwhva
);
987 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y
) {
988 if (web_contents_
->GetDelegate() && IsScrollEndEffectEnabled())
989 web_contents_
->GetDelegate()->OverscrollUpdate(delta_y
);
992 ////////////////////////////////////////////////////////////////////////////////
993 // WebContentsViewAura, WebContentsView implementation:
995 gfx::NativeView
WebContentsViewAura::GetNativeView() const {
996 return window_
.get();
999 gfx::NativeView
WebContentsViewAura::GetContentNativeView() const {
1000 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
1001 return rwhv
? rwhv
->GetNativeView() : NULL
;
1004 gfx::NativeWindow
WebContentsViewAura::GetTopLevelNativeWindow() const {
1005 return window_
->GetToplevelWindow();
1008 void WebContentsViewAura::GetContainerBounds(gfx::Rect
*out
) const {
1009 *out
= window_
->GetBoundsInScreen();
1012 void WebContentsViewAura::SizeContents(const gfx::Size
& size
) {
1013 gfx::Rect bounds
= window_
->bounds();
1014 if (bounds
.size() != size
) {
1015 bounds
.set_size(size
);
1016 window_
->SetBounds(bounds
);
1018 // Our size matches what we want but the renderers size may not match.
1019 // Pretend we were resized so that the renderers size is updated too.
1020 SizeChangedCommon(size
);
1024 void WebContentsViewAura::Focus() {
1025 if (web_contents_
->GetInterstitialPage()) {
1026 web_contents_
->GetInterstitialPage()->Focus();
1030 if (delegate_
.get() && delegate_
->Focus())
1033 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
1038 void WebContentsViewAura::SetInitialFocus() {
1039 if (web_contents_
->FocusLocationBarByDefault())
1040 web_contents_
->SetFocusToLocationBar(false);
1045 void WebContentsViewAura::StoreFocus() {
1047 delegate_
->StoreFocus();
1050 void WebContentsViewAura::RestoreFocus() {
1052 delegate_
->RestoreFocus();
1055 DropData
* WebContentsViewAura::GetDropData() const {
1056 return current_drop_data_
.get();
1059 gfx::Rect
WebContentsViewAura::GetViewBounds() const {
1060 return window_
->GetBoundsInScreen();
1063 ////////////////////////////////////////////////////////////////////////////////
1064 // WebContentsViewAura, WebContentsView implementation:
1066 void WebContentsViewAura::CreateView(
1067 const gfx::Size
& initial_size
, gfx::NativeView context
) {
1068 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1069 // if the bookmark bar is not shown and you create a new tab). The right
1070 // value is set shortly after this, so its safe to ignore.
1072 aura::Env::CreateInstance(true);
1073 window_
.reset(new aura::Window(this));
1074 window_
->set_owned_by_parent(false);
1075 window_
->SetType(ui::wm::WINDOW_TYPE_CONTROL
);
1076 window_
->SetTransparent(false);
1077 window_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
1078 window_
->AddObserver(this);
1079 aura::Window
* root_window
= context
? context
->GetRootWindow() : NULL
;
1081 // There are places where there is no context currently because object
1082 // hierarchies are built before they're attached to a Widget. (See
1083 // views::WebView as an example; GetWidget() returns NULL at the point
1084 // where we are created.)
1086 // It should be OK to not set a default parent since such users will
1087 // explicitly add this WebContentsViewAura to their tree after they create
1090 aura::client::ParentWindowWithContext(
1091 window_
.get(), root_window
, root_window
->GetBoundsInScreen());
1094 window_
->layer()->SetMasksToBounds(true);
1095 window_
->SetName("WebContentsViewAura");
1097 // WindowObserver is not interesting and is problematic for Browser Plugin
1099 // The use cases for WindowObserver do not apply to Browser Plugins:
1100 // 1) guests do not support NPAPI plugins.
1101 // 2) guests' window bounds are supposed to come from its embedder.
1102 if (!BrowserPluginGuest::IsGuest(web_contents_
))
1103 window_observer_
.reset(new WindowObserver(this));
1105 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1106 // Hence, we save a reference to it locally. Similar model is used on other
1107 // platforms as well.
1109 drag_dest_delegate_
= delegate_
->GetDragDestDelegate();
1112 RenderWidgetHostViewBase
* WebContentsViewAura::CreateViewForWidget(
1113 RenderWidgetHost
* render_widget_host
) {
1114 if (render_widget_host
->GetView()) {
1115 // During testing, the view will already be set up in most cases to the
1116 // test view, so we don't want to clobber it with a real one. To verify that
1117 // this actually is happening (and somebody isn't accidentally creating the
1118 // view twice), we check for the RVH Factory, which will be set when we're
1119 // making special ones (which go along with the special views).
1120 DCHECK(RenderViewHostFactory::has_factory());
1121 return static_cast<RenderWidgetHostViewBase
*>(
1122 render_widget_host
->GetView());
1125 RenderWidgetHostViewAura
* view
=
1126 new RenderWidgetHostViewAura(render_widget_host
);
1127 view
->InitAsChild(NULL
);
1128 GetNativeView()->AddChild(view
->GetNativeView());
1130 if (navigation_overlay_
.get() && navigation_overlay_
->has_window()) {
1131 navigation_overlay_
->StartObserving();
1134 RenderWidgetHostImpl
* host_impl
=
1135 RenderWidgetHostImpl::From(render_widget_host
);
1137 if (!host_impl
->is_hidden())
1140 // We listen to drag drop events in the newly created view's window.
1141 aura::client::SetDragDropDelegate(view
->GetNativeView(), this);
1143 if (view
->overscroll_controller() &&
1144 (!web_contents_
->GetDelegate() ||
1145 web_contents_
->GetDelegate()->CanOverscrollContent())) {
1146 InstallOverscrollControllerDelegate(view
);
1149 AttachTouchEditableToRenderView();
1153 RenderWidgetHostViewBase
* WebContentsViewAura::CreateViewForPopupWidget(
1154 RenderWidgetHost
* render_widget_host
) {
1155 return new RenderWidgetHostViewAura(render_widget_host
);
1158 void WebContentsViewAura::SetPageTitle(const base::string16
& title
) {
1159 window_
->SetTitle(title
);
1162 void WebContentsViewAura::RenderViewCreated(RenderViewHost
* host
) {
1165 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost
* host
) {
1166 if (navigation_overlay_
.get() && navigation_overlay_
->has_window())
1167 navigation_overlay_
->StartObserving();
1168 AttachTouchEditableToRenderView();
1171 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled
) {
1172 RenderWidgetHostViewAura
* view
=
1173 ToRenderWidgetHostViewAura(web_contents_
->GetRenderWidgetHostView());
1175 view
->SetOverscrollControllerEnabled(enabled
);
1177 InstallOverscrollControllerDelegate(view
);
1181 navigation_overlay_
.reset();
1182 else if (!navigation_overlay_
)
1183 navigation_overlay_
.reset(new OverscrollNavigationOverlay(web_contents_
));
1186 ////////////////////////////////////////////////////////////////////////////////
1187 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1189 void WebContentsViewAura::ShowContextMenu(RenderFrameHost
* render_frame_host
,
1190 const ContextMenuParams
& params
) {
1191 if (touch_editable_
) {
1192 touch_editable_
->EndTouchEditing(false);
1195 delegate_
->ShowContextMenu(render_frame_host
, params
);
1196 // WARNING: we may have been deleted during the call to ShowContextMenu().
1200 void WebContentsViewAura::StartDragging(
1201 const DropData
& drop_data
,
1202 blink::WebDragOperationsMask operations
,
1203 const gfx::ImageSkia
& image
,
1204 const gfx::Vector2d
& image_offset
,
1205 const DragEventSourceInfo
& event_info
) {
1206 aura::Window
* root_window
= GetNativeView()->GetRootWindow();
1207 if (!aura::client::GetDragDropClient(root_window
)) {
1208 web_contents_
->SystemDragEnded();
1212 if (touch_editable_
)
1213 touch_editable_
->EndTouchEditing(false);
1215 ui::OSExchangeData::Provider
* provider
= ui::OSExchangeData::CreateProvider();
1216 PrepareDragData(drop_data
, provider
, web_contents_
);
1218 ui::OSExchangeData
data(provider
); // takes ownership of |provider|.
1220 if (!image
.isNull())
1221 drag_utils::SetDragImageOnDataObject(image
, image_offset
, &data
);
1223 scoped_ptr
<WebDragSourceAura
> drag_source(
1224 new WebDragSourceAura(GetNativeView(), web_contents_
));
1226 // We need to enable recursive tasks on the message loop so we can get
1227 // updates while in the system DoDragDrop loop.
1230 gfx::NativeView content_native_view
= GetContentNativeView();
1231 base::MessageLoop::ScopedNestableTaskAllower
allow(
1232 base::MessageLoop::current());
1233 result_op
= aura::client::GetDragDropClient(root_window
)
1234 ->StartDragAndDrop(data
,
1236 content_native_view
,
1237 event_info
.event_location
,
1238 ConvertFromWeb(operations
),
1239 event_info
.event_source
);
1242 // Bail out immediately if the contents view window is gone. Note that it is
1243 // not safe to access any class members in this case since |this| may already
1244 // be destroyed. The local variable |drag_source| will still be valid though,
1245 // so we can use it to determine if the window is gone.
1246 if (!drag_source
->window()) {
1247 // Note that in this case, we don't need to call SystemDragEnded() since the
1248 // renderer is going away.
1252 EndDrag(ConvertToWeb(result_op
));
1253 web_contents_
->SystemDragEnded();
1256 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation
) {
1257 current_drag_op_
= operation
;
1260 void WebContentsViewAura::GotFocus() {
1261 if (web_contents_
->GetDelegate())
1262 web_contents_
->GetDelegate()->WebContentsFocused(web_contents_
);
1265 void WebContentsViewAura::TakeFocus(bool reverse
) {
1266 if (web_contents_
->GetDelegate() &&
1267 !web_contents_
->GetDelegate()->TakeFocus(web_contents_
, reverse
) &&
1269 delegate_
->TakeFocus(reverse
);
1273 ////////////////////////////////////////////////////////////////////////////////
1274 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1276 gfx::Rect
WebContentsViewAura::GetVisibleBounds() const {
1277 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
1278 if (!rwhv
|| !rwhv
->IsShowing())
1281 return rwhv
->GetViewBounds();
1284 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x
, float delta_y
) {
1285 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
1288 aura::Window
* target
= GetWindowToAnimateForOverscroll();
1289 gfx::Vector2d translate
= GetTranslationForOverscroll(delta_x
, delta_y
);
1290 gfx::Transform transform
;
1292 // Vertical overscrolls don't participate in the navigation gesture.
1293 if (current_overscroll_gesture_
!= OVERSCROLL_NORTH
&&
1294 current_overscroll_gesture_
!= OVERSCROLL_SOUTH
) {
1295 transform
.Translate(translate
.x(), translate
.y());
1296 target
->SetTransform(transform
);
1297 UpdateOverscrollWindowBrightness(delta_x
);
1300 OverscrollUpdateForWebContentsDelegate(translate
.y());
1301 return !translate
.IsZero();
1304 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode
) {
1305 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode
, OVERSCROLL_COUNT
);
1306 OverscrollUpdateForWebContentsDelegate(0);
1307 NavigationControllerImpl
& controller
= web_contents_
->GetController();
1308 if (ShouldNavigateForward(controller
, mode
) ||
1309 ShouldNavigateBack(controller
, mode
)) {
1310 CompleteOverscrollNavigation(mode
);
1314 ResetOverscrollTransform();
1317 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode
,
1318 OverscrollMode new_mode
) {
1319 // Reset any in-progress overscroll animation first.
1320 ResetOverscrollTransform();
1322 if (new_mode
!= OVERSCROLL_NONE
&& touch_editable_
)
1323 touch_editable_
->OverscrollStarted();
1325 if (new_mode
== OVERSCROLL_NONE
||
1326 !GetContentNativeView() ||
1327 ((new_mode
== OVERSCROLL_EAST
|| new_mode
== OVERSCROLL_WEST
) &&
1328 navigation_overlay_
.get() && navigation_overlay_
->has_window())) {
1329 current_overscroll_gesture_
= OVERSCROLL_NONE
;
1330 OverscrollUpdateForWebContentsDelegate(0);
1332 aura::Window
* target
= GetWindowToAnimateForOverscroll();
1334 StopObservingImplicitAnimations();
1335 target
->layer()->GetAnimator()->AbortAllAnimations();
1337 // Cleanup state of the content window first, because that can reset the
1338 // value of |current_overscroll_gesture_|.
1339 PrepareContentWindowForOverscroll();
1341 current_overscroll_gesture_
= new_mode
;
1342 if (current_overscroll_gesture_
== OVERSCROLL_EAST
||
1343 current_overscroll_gesture_
== OVERSCROLL_WEST
)
1344 PrepareOverscrollWindow();
1346 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode
, OVERSCROLL_COUNT
);
1348 completed_overscroll_gesture_
= OVERSCROLL_NONE
;
1351 ////////////////////////////////////////////////////////////////////////////////
1352 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1354 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1355 overscroll_shadow_
.reset();
1357 if (ShouldNavigateForward(web_contents_
->GetController(),
1358 completed_overscroll_gesture_
)) {
1359 web_contents_
->GetController().GoForward();
1360 PrepareOverscrollNavigationOverlay();
1361 } else if (ShouldNavigateBack(web_contents_
->GetController(),
1362 completed_overscroll_gesture_
)) {
1363 web_contents_
->GetController().GoBack();
1364 PrepareOverscrollNavigationOverlay();
1366 if (touch_editable_
)
1367 touch_editable_
->OverscrollCompleted();
1370 aura::Window
* content
= GetContentNativeView();
1372 content
->SetTransform(gfx::Transform());
1373 content
->layer()->SetLayerBrightness(0.f
);
1375 current_overscroll_gesture_
= OVERSCROLL_NONE
;
1376 completed_overscroll_gesture_
= OVERSCROLL_NONE
;
1377 overscroll_window_
.reset();
1380 ////////////////////////////////////////////////////////////////////////////////
1381 // WebContentsViewAura, aura::WindowDelegate implementation:
1383 gfx::Size
WebContentsViewAura::GetMinimumSize() const {
1387 gfx::Size
WebContentsViewAura::GetMaximumSize() const {
1391 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect
& old_bounds
,
1392 const gfx::Rect
& new_bounds
) {
1393 SizeChangedCommon(new_bounds
.size());
1395 delegate_
->SizeChanged(new_bounds
.size());
1397 // Constrained web dialogs, need to be kept centered over our content area.
1398 for (size_t i
= 0; i
< window_
->children().size(); i
++) {
1399 if (window_
->children()[i
]->GetProperty(
1400 aura::client::kConstrainedWindowKey
)) {
1401 gfx::Rect bounds
= window_
->children()[i
]->bounds();
1403 gfx::Point((new_bounds
.width() - bounds
.width()) / 2,
1404 (new_bounds
.height() - bounds
.height()) / 2));
1405 window_
->children()[i
]->SetBounds(bounds
);
1410 gfx::NativeCursor
WebContentsViewAura::GetCursor(const gfx::Point
& point
) {
1411 return gfx::kNullCursor
;
1414 int WebContentsViewAura::GetNonClientComponent(const gfx::Point
& point
) const {
1418 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1419 aura::Window
* child
,
1420 const gfx::Point
& location
) {
1424 bool WebContentsViewAura::CanFocus() {
1425 // Do not take the focus if the render widget host view aura is gone or
1426 // is in the process of shutting down because neither the view window nor
1427 // this window can handle key events.
1428 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
1429 web_contents_
->GetRenderWidgetHostView());
1430 if (view
!= NULL
&& !view
->IsClosing())
1436 void WebContentsViewAura::OnCaptureLost() {
1439 void WebContentsViewAura::OnPaint(gfx::Canvas
* canvas
) {
1442 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1443 float device_scale_factor
) {
1446 void WebContentsViewAura::OnWindowDestroying(aura::Window
* window
) {
1447 // This means the destructor is going to be called soon. If there is an
1448 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1449 // then destroying it in the WebContentsViewAura destructor can trigger other
1450 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1451 // destroy the overscroll window here.
1452 navigation_overlay_
.reset();
1453 overscroll_window_
.reset();
1456 void WebContentsViewAura::OnWindowDestroyed(aura::Window
* window
) {
1459 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible
) {
1462 bool WebContentsViewAura::HasHitTestMask() const {
1466 void WebContentsViewAura::GetHitTestMask(gfx::Path
* mask
) const {
1469 ////////////////////////////////////////////////////////////////////////////////
1470 // WebContentsViewAura, ui::EventHandler implementation:
1472 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent
* event
) {
1475 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent
* event
) {
1476 if (!web_contents_
->GetDelegate())
1479 switch (event
->type()) {
1480 case ui::ET_MOUSE_PRESSED
:
1481 web_contents_
->GetDelegate()->ActivateContents(web_contents_
);
1483 case ui::ET_MOUSE_MOVED
:
1484 case ui::ET_MOUSE_EXITED
:
1485 web_contents_
->GetDelegate()->ContentsMouseEvent(
1487 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1488 event
->type() == ui::ET_MOUSE_MOVED
);
1495 ////////////////////////////////////////////////////////////////////////////////
1496 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1498 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent
& event
) {
1499 current_rvh_for_drag_
= web_contents_
->GetRenderViewHost();
1500 current_drop_data_
.reset(new DropData());
1502 PrepareDropData(current_drop_data_
.get(), event
.data());
1503 blink::WebDragOperationsMask op
= ConvertToWeb(event
.source_operations());
1505 // Give the delegate an opportunity to cancel the drag.
1506 if (web_contents_
->GetDelegate() &&
1507 !web_contents_
->GetDelegate()->CanDragEnter(
1508 web_contents_
, *current_drop_data_
.get(), op
)) {
1509 current_drop_data_
.reset(NULL
);
1513 if (drag_dest_delegate_
)
1514 drag_dest_delegate_
->DragInitialize(web_contents_
);
1516 gfx::Point screen_pt
=
1517 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1518 web_contents_
->GetRenderViewHost()->DragTargetDragEnter(
1519 *current_drop_data_
.get(), event
.location(), screen_pt
, op
,
1520 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1522 if (drag_dest_delegate_
) {
1523 drag_dest_delegate_
->OnReceiveDragData(event
.data());
1524 drag_dest_delegate_
->OnDragEnter();
1528 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent
& event
) {
1529 DCHECK(current_rvh_for_drag_
);
1530 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1531 OnDragEntered(event
);
1533 if (!current_drop_data_
)
1534 return ui::DragDropTypes::DRAG_NONE
;
1536 blink::WebDragOperationsMask op
= ConvertToWeb(event
.source_operations());
1537 gfx::Point screen_pt
=
1538 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1539 web_contents_
->GetRenderViewHost()->DragTargetDragOver(
1540 event
.location(), screen_pt
, op
,
1541 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1543 if (drag_dest_delegate_
)
1544 drag_dest_delegate_
->OnDragOver();
1546 return ConvertFromWeb(current_drag_op_
);
1549 void WebContentsViewAura::OnDragExited() {
1550 DCHECK(current_rvh_for_drag_
);
1551 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1554 if (!current_drop_data_
)
1557 web_contents_
->GetRenderViewHost()->DragTargetDragLeave();
1558 if (drag_dest_delegate_
)
1559 drag_dest_delegate_
->OnDragLeave();
1561 current_drop_data_
.reset();
1564 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent
& event
) {
1565 DCHECK(current_rvh_for_drag_
);
1566 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1567 OnDragEntered(event
);
1569 if (!current_drop_data_
)
1570 return ui::DragDropTypes::DRAG_NONE
;
1572 web_contents_
->GetRenderViewHost()->DragTargetDrop(
1574 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1575 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1576 if (drag_dest_delegate_
)
1577 drag_dest_delegate_
->OnDrop();
1578 current_drop_data_
.reset();
1579 return ConvertFromWeb(current_drag_op_
);
1582 void WebContentsViewAura::OnWindowParentChanged(aura::Window
* window
,
1583 aura::Window
* parent
) {
1584 // Ignore any visibility changes in the hierarchy below.
1585 if (window
!= window_
.get() && window_
->Contains(window
))
1588 // On Windows we will get called with a parent of NULL as part of the shut
1589 // down process. As such we do only change the visibility when a parent gets
1592 UpdateWebContentsVisibility(window
->IsVisible());
1595 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window
* window
,
1597 // Ignore any visibility changes in the hierarchy below.
1598 if (window
!= window_
.get() && window_
->Contains(window
))
1601 UpdateWebContentsVisibility(visible
);
1604 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible
) {
1605 if (!is_or_was_visible_
) {
1606 // We should not hide the web contents before it was shown the first time,
1607 // since resources would immediately be destroyed and only re-created after
1608 // content got loaded. In this state the window content is undefined and can
1610 // However - the page load mechanism requires an activation call through a
1611 // visibility call to (re)load.
1613 is_or_was_visible_
= true;
1614 web_contents_
->WasShown();
1619 if (!web_contents_
->should_normally_be_visible())
1620 web_contents_
->WasShown();
1622 if (web_contents_
->should_normally_be_visible())
1623 web_contents_
->WasHidden();
1627 } // namespace content