Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_view_aura.cc
blob1a61244b2e6649e21ada602f135267833f85b83f
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"
73 namespace content {
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;
80 return rv;
83 namespace {
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))
111 return NULL;
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
117 // destroyed.
118 class OverscrollWindowDelegate : public ImageWindowDelegate {
119 public:
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));
134 gfx::Image image;
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);
141 SetImage(image);
144 void stop_forwarding_events() { forward_events_ = false; }
146 private:
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
178 // the renderer.
179 class WebDragSourceAura : public NotificationObserver {
180 public:
181 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
182 : window_(window),
183 contents_(contents) {
184 registrar_.Add(this,
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)
197 return;
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();
205 window_ = NULL;
206 contents_ = NULL;
209 aura::Window* window() const { return window_; }
211 private:
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
221 // necessary.
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);
236 #endif
238 #if defined(OS_WIN)
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;
249 GURL download_url;
250 if (!ParseDownloadMetadata(drop_data.download_metadata,
251 &mime_type,
252 &file_name,
253 &download_url))
254 return;
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,
261 std::string(),
262 std::string(),
263 base::UTF16ToUTF8(file_name.value()),
264 base::UTF16ToUTF8(mime_type),
265 default_name);
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"),
272 &temp_dir_path))
273 return;
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(
287 download_path,
288 base::File(),
289 download_url,
290 Referrer(page_url, drop_data.referrer_policy),
291 page_encoding,
292 web_contents);
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,
303 format,
304 (ui::Clipboard::GetFormatType(kFormatString)));
305 return format;
308 // Writes file system files to the pickle.
309 void WriteFileSystemFilesToPickle(
310 const std::vector<DropData::FileSystemFileInfo>& file_system_files,
311 Pickle* pickle) {
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))
327 return false;
328 file_system_files->resize(num_files);
330 for (uint64 i = 0; i < num_files; ++i) {
331 std::string url_string;
332 int64 size = 0;
333 if (!pickle.ReadString(&iter, &url_string) ||
334 !pickle.ReadInt64(&iter, &size))
335 return false;
337 GURL url(url_string);
338 if (!url.is_valid())
339 return false;
341 (*file_system_files)[i].url = url;
342 (*file_system_files)[i].size = size;
344 return true;
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();
352 #if defined(OS_WIN)
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);
357 #endif
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);
364 #endif
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
368 // exists.
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()) {
378 Pickle pickle;
379 WriteFileSystemFilesToPickle(drop_data.file_system_files, &pickle);
380 provider->SetPickledData(GetFileSystemFileCustomFormat(), pickle);
382 if (!drop_data.custom_data.empty()) {
383 Pickle pickle;
384 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
385 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
386 pickle);
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);
399 GURL url;
400 base::string16 url_title;
401 data.GetURLAndTitle(
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;
408 base::string16 html;
409 GURL html_base_url;
410 data.GetHtml(&html, &html_base_url);
411 if (!html.empty())
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);
418 Pickle pickle;
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;
439 return drag_op;
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;
466 } // namespace
468 class WebContentsViewAura::WindowObserver
469 : public aura::WindowObserver, public aura::WindowTreeHostObserver {
470 public:
471 explicit WindowObserver(WebContentsViewAura* view)
472 : view_(view),
473 host_window_(NULL) {
474 view_->window_->AddObserver(this);
476 #if defined(OS_WIN)
477 if (view_->window_->GetRootWindow())
478 view_->window_->GetRootWindow()->AddObserver(this);
479 #endif
482 virtual ~WindowObserver() {
483 view_->window_->RemoveObserver(this);
484 if (view_->window_->GetHost())
485 view_->window_->GetHost()->RemoveObserver(this);
486 if (host_window_)
487 host_window_->RemoveObserver(this);
488 #if defined(OS_WIN)
489 if (host_window_) {
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();
496 if (root_window) {
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);
502 #endif
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())) {
510 return;
513 // Use the new parent's root window for calculating HiDPI subpixel offset.
514 RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
515 view_->web_contents_->GetRenderWidgetHostView());
516 if (rwhv)
517 rwhv->SnapToPhysicalPixelBoundary();
520 #if defined(OS_WIN)
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
532 // window.
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_)
547 return;
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);
561 #endif
563 virtual void OnWindowParentChanged(aura::Window* window,
564 aura::Window* parent) OVERRIDE {
565 if (window != view_->window_)
566 return;
568 aura::Window* host_window =
569 window->GetProperty(aura::client::kHostWindowKey);
570 if (!host_window)
571 host_window = parent;
573 if (host_window_)
574 host_window_->RemoveObserver(this);
576 #if defined(OS_WIN)
577 if (host_window_) {
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());
583 if (rwhv)
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);
601 #endif
603 host_window_ = host_window;
604 if (host_window) {
605 host_window->AddObserver(this);
606 #if defined(OS_WIN)
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);
614 #endif
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_) {
622 SendScreenRects();
623 if (view_->touch_editable_)
624 view_->touch_editable_->UpdateEditingController();
625 #if defined(OS_WIN)
626 } else {
627 UpdateConstrainedWindows(NULL);
628 #endif
632 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
633 if (window == host_window_) {
634 host_window_->RemoveObserver(this);
635 host_window_ = NULL;
639 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
640 if (window == view_->window_) {
641 window->GetHost()->AddObserver(this);
642 #if defined(OS_WIN)
643 if (!window->GetRootWindow()->HasObserver(this))
644 window->GetRootWindow()->AddObserver(this);
645 #endif
649 virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
650 aura::Window* new_root) OVERRIDE {
651 if (window == view_->window_) {
652 window->GetHost()->RemoveObserver(this);
653 #if defined(OS_WIN)
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);
664 #endif
668 // Overridden WindowTreeHostObserver:
669 virtual void OnHostMoved(const aura::WindowTreeHost* host,
670 const gfx::Point& new_origin) OVERRIDE {
671 TRACE_EVENT1("ui",
672 "WebContentsViewAura::WindowObserver::OnHostMoved",
673 "new_origin", new_origin.ToString());
675 // This is for the desktop case (i.e. Aura desktop).
676 SendScreenRects();
679 private:
680 void SendScreenRects() {
681 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
682 SendScreenRects();
685 #if defined(OS_WIN)
686 void UpdateConstrainedWindows(aura::Window* exclude) {
687 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
688 view_->web_contents_->GetRenderWidgetHostView());
689 if (!view)
690 return;
692 std::vector<gfx::Rect> constrained_windows;
693 if (host_window_) {
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();
706 if (root_window) {
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);
718 #endif
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),
736 delegate_(delegate),
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() {
751 if (!window_)
752 return;
754 window_observer_.reset();
755 window_->RemoveObserver(this);
757 // Window needs a valid delegate during its destructor, so we explicitly
758 // delete it here.
759 window_.reset();
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();
773 if (rwhv)
774 rwhv->SetSize(size);
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);
785 if (!web_contents_)
786 return;
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);
795 if (value == "0") {
796 navigation_overlay_.reset();
797 return;
799 if (value == "2") {
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());
804 return;
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(&current_overscroll_gesture_,
819 current_overscroll_gesture_);
820 scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
823 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
824 web_contents_,
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());
848 else
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())
869 return;
870 aura::Window* target = GetWindowToAnimateForOverscroll();
871 if (!target)
872 return;
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())
892 return;
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)
897 return;
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;
913 int content_width =
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)
923 return NULL;
925 return ShouldNavigateForward(web_contents_->GetController(),
926 current_overscroll_gesture_) ?
927 overscroll_window_.get() : GetContentNativeView();
930 gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
931 int delta_y) {
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(),
955 delegate);
956 navigation_overlay_->StartObserving();
959 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
960 if (!overscroll_change_brightness_)
961 return;
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())
969 ratio = 1.f - ratio;
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_)
981 return;
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);
1017 } else {
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();
1027 return;
1030 if (delegate_.get() && delegate_->Focus())
1031 return;
1033 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1034 if (rwhv)
1035 rwhv->Focus();
1038 void WebContentsViewAura::SetInitialFocus() {
1039 if (web_contents_->FocusLocationBarByDefault())
1040 web_contents_->SetFocusToLocationBar(false);
1041 else
1042 Focus();
1045 void WebContentsViewAura::StoreFocus() {
1046 if (delegate_)
1047 delegate_->StoreFocus();
1050 void WebContentsViewAura::RestoreFocus() {
1051 if (delegate_)
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;
1080 if (root_window) {
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
1088 // us.
1089 if (root_window) {
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
1098 // guests.
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.
1108 if (delegate_)
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())
1138 view->Show();
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();
1150 return view;
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());
1174 if (view) {
1175 view->SetOverscrollControllerEnabled(enabled);
1176 if (enabled)
1177 InstallOverscrollControllerDelegate(view);
1180 if (!enabled)
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);
1194 if (delegate_) {
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();
1209 return;
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.
1228 int result_op = 0;
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,
1235 root_window,
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.
1249 return;
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) &&
1268 delegate_.get()) {
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())
1279 return gfx::Rect();
1281 return rwhv->GetViewBounds();
1284 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1285 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1286 return false;
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);
1311 return;
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);
1331 } else {
1332 aura::Window* target = GetWindowToAnimateForOverscroll();
1333 if (target) {
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();
1365 } else {
1366 if (touch_editable_)
1367 touch_editable_->OverscrollCompleted();
1370 aura::Window* content = GetContentNativeView();
1371 if (content) {
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 {
1384 return gfx::Size();
1387 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1388 return gfx::Size();
1391 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1392 const gfx::Rect& new_bounds) {
1393 SizeChangedCommon(new_bounds.size());
1394 if (delegate_)
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();
1402 bounds.set_origin(
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 {
1415 return HTCLIENT;
1418 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1419 aura::Window* child,
1420 const gfx::Point& location) {
1421 return true;
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())
1431 return true;
1433 return false;
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 {
1463 return false;
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())
1477 return;
1479 switch (event->type()) {
1480 case ui::ET_MOUSE_PRESSED:
1481 web_contents_->GetDelegate()->ActivateContents(web_contents_);
1482 break;
1483 case ui::ET_MOUSE_MOVED:
1484 case ui::ET_MOUSE_EXITED:
1485 web_contents_->GetDelegate()->ContentsMouseEvent(
1486 web_contents_,
1487 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1488 event->type() == ui::ET_MOUSE_MOVED);
1489 break;
1490 default:
1491 break;
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);
1510 return;
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())
1552 return;
1554 if (!current_drop_data_)
1555 return;
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(
1573 event.location(),
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))
1586 return;
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
1590 // set.
1591 if (parent)
1592 UpdateWebContentsVisibility(window->IsVisible());
1595 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
1596 bool visible) {
1597 // Ignore any visibility changes in the hierarchy below.
1598 if (window != window_.get() && window_->Contains(window))
1599 return;
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
1609 // show garbage.
1610 // However - the page load mechanism requires an activation call through a
1611 // visibility call to (re)load.
1612 if (visible) {
1613 is_or_was_visible_ = true;
1614 web_contents_->WasShown();
1616 return;
1618 if (visible) {
1619 if (!web_contents_->should_normally_be_visible())
1620 web_contents_->WasShown();
1621 } else {
1622 if (web_contents_->should_normally_be_visible())
1623 web_contents_->WasHidden();
1627 } // namespace content