[Mac] Implement Ambient Light API
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_view_aura.cc
blob5b976ba1921edda335408986df99d93983e48370
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/web_contents/web_contents_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/files/file_util.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_guest.h"
13 #include "content/browser/download/drag_download_util.h"
14 #include "content/browser/frame_host/interstitial_page_impl.h"
15 #include "content/browser/frame_host/navigation_entry_impl.h"
16 #include "content/browser/renderer_host/dip_util.h"
17 #include "content/browser/renderer_host/overscroll_controller.h"
18 #include "content/browser/renderer_host/render_view_host_factory.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
22 #include "content/browser/renderer_host/web_input_event_aura.h"
23 #include "content/browser/web_contents/aura/gesture_nav_simple.h"
24 #include "content/browser/web_contents/aura/image_window_delegate.h"
25 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
26 #include "content/browser/web_contents/aura/shadow_layer_delegate.h"
27 #include "content/browser/web_contents/aura/window_slider.h"
28 #include "content/browser/web_contents/touch_editable_impl_aura.h"
29 #include "content/browser/web_contents/web_contents_impl.h"
30 #include "content/public/browser/content_browser_client.h"
31 #include "content/public/browser/notification_observer.h"
32 #include "content/public/browser/notification_registrar.h"
33 #include "content/public/browser/notification_source.h"
34 #include "content/public/browser/notification_types.h"
35 #include "content/public/browser/overscroll_configuration.h"
36 #include "content/public/browser/render_view_host.h"
37 #include "content/public/browser/render_widget_host.h"
38 #include "content/public/browser/render_widget_host_view.h"
39 #include "content/public/browser/web_contents_delegate.h"
40 #include "content/public/browser/web_contents_observer.h"
41 #include "content/public/browser/web_contents_view_delegate.h"
42 #include "content/public/browser/web_drag_dest_delegate.h"
43 #include "content/public/common/content_client.h"
44 #include "content/public/common/content_switches.h"
45 #include "content/public/common/drop_data.h"
46 #include "net/base/filename_util.h"
47 #include "third_party/WebKit/public/web/WebInputEvent.h"
48 #include "ui/aura/client/aura_constants.h"
49 #include "ui/aura/client/window_tree_client.h"
50 #include "ui/aura/env.h"
51 #include "ui/aura/window.h"
52 #include "ui/aura/window_observer.h"
53 #include "ui/aura/window_tree_host.h"
54 #include "ui/aura/window_tree_host_observer.h"
55 #include "ui/base/clipboard/clipboard.h"
56 #include "ui/base/clipboard/custom_data_helper.h"
57 #include "ui/base/dragdrop/drag_drop_types.h"
58 #include "ui/base/dragdrop/drag_utils.h"
59 #include "ui/base/dragdrop/drop_target_event.h"
60 #include "ui/base/dragdrop/os_exchange_data.h"
61 #include "ui/base/hit_test.h"
62 #include "ui/compositor/layer.h"
63 #include "ui/compositor/scoped_layer_animation_settings.h"
64 #include "ui/events/event.h"
65 #include "ui/events/event_utils.h"
66 #include "ui/gfx/canvas.h"
67 #include "ui/gfx/image/image.h"
68 #include "ui/gfx/image/image_png_rep.h"
69 #include "ui/gfx/image/image_skia.h"
70 #include "ui/gfx/screen.h"
71 #include "ui/wm/public/drag_drop_client.h"
72 #include "ui/wm/public/drag_drop_delegate.h"
74 namespace content {
75 WebContentsView* CreateWebContentsView(
76 WebContentsImpl* web_contents,
77 WebContentsViewDelegate* delegate,
78 RenderViewHostDelegateView** render_view_host_delegate_view) {
79 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
80 *render_view_host_delegate_view = rv;
81 return rv;
84 namespace {
86 bool IsScrollEndEffectEnabled() {
87 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
88 switches::kScrollEndEffect) == "1";
91 bool ShouldNavigateForward(const NavigationController& controller,
92 OverscrollMode mode) {
93 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
94 controller.CanGoForward();
97 bool ShouldNavigateBack(const NavigationController& controller,
98 OverscrollMode mode) {
99 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
100 controller.CanGoBack();
103 RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
104 RenderWidgetHostView* view) {
105 if (!view || RenderViewHostFactory::has_factory())
106 return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests.
108 RenderViewHost* rvh = RenderViewHost::From(view->GetRenderWidgetHost());
109 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
110 rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
111 if (BrowserPluginGuest::IsGuest(web_contents))
112 return NULL;
113 return static_cast<RenderWidgetHostViewAura*>(view);
116 // The window delegate for the overscroll window. This redirects trackpad events
117 // to the web-contents window. The delegate destroys itself when the window is
118 // destroyed.
119 class OverscrollWindowDelegate : public ImageWindowDelegate {
120 public:
121 OverscrollWindowDelegate(WebContentsImpl* web_contents,
122 OverscrollMode overscroll_mode)
123 : web_contents_(web_contents),
124 forward_events_(true) {
125 const NavigationControllerImpl& controller = web_contents->GetController();
126 const NavigationEntryImpl* entry = NULL;
127 if (ShouldNavigateForward(controller, overscroll_mode)) {
128 entry = NavigationEntryImpl::FromNavigationEntry(
129 controller.GetEntryAtOffset(1));
130 } else if (ShouldNavigateBack(controller, overscroll_mode)) {
131 entry = NavigationEntryImpl::FromNavigationEntry(
132 controller.GetEntryAtOffset(-1));
135 gfx::Image image;
136 if (entry && entry->screenshot().get()) {
137 std::vector<gfx::ImagePNGRep> image_reps;
138 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
139 image = gfx::Image(image_reps);
141 SetImage(image);
144 void stop_forwarding_events() { forward_events_ = false; }
146 private:
147 ~OverscrollWindowDelegate() override {}
149 aura::Window* web_contents_window() {
150 return web_contents_->GetView()->GetContentNativeView();
153 // Overridden from ui::EventHandler.
154 void OnScrollEvent(ui::ScrollEvent* event) override {
155 if (forward_events_ && web_contents_window())
156 web_contents_window()->delegate()->OnScrollEvent(event);
159 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 ~WebDragSourceAura() override {}
191 // NotificationObserver:
192 void Observe(int type,
193 const NotificationSource& source,
194 const NotificationDetails& details) override {
195 if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
196 return;
198 // Cancel the drag if it is still in progress.
199 aura::client::DragDropClient* dnd_client =
200 aura::client::GetDragDropClient(window_->GetRootWindow());
201 if (dnd_client && dnd_client->IsDragDropInProgress())
202 dnd_client->DragCancel();
204 window_ = NULL;
205 contents_ = NULL;
208 aura::Window* window() const { return window_; }
210 private:
211 aura::Window* window_;
212 WebContentsImpl* contents_;
213 NotificationRegistrar registrar_;
215 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
218 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
219 // Fill out the OSExchangeData with a file contents, synthesizing a name if
220 // necessary.
221 void PrepareDragForFileContents(const DropData& drop_data,
222 ui::OSExchangeData::Provider* provider) {
223 base::FilePath file_name =
224 base::FilePath::FromUTF16Unsafe(drop_data.file_description_filename);
225 // Images without ALT text will only have a file extension so we need to
226 // synthesize one from the provided extension and URL.
227 if (file_name.BaseName().RemoveExtension().empty()) {
228 const base::FilePath::StringType extension = file_name.Extension();
229 // Retrieve the name from the URL.
230 file_name = net::GenerateFileName(drop_data.url, "", "", "", "", "")
231 .ReplaceExtension(extension);
233 provider->SetFileContents(file_name, drop_data.file_contents);
235 #endif
237 #if defined(OS_WIN)
238 void PrepareDragForDownload(
239 const DropData& drop_data,
240 ui::OSExchangeData::Provider* provider,
241 WebContentsImpl* web_contents) {
242 const GURL& page_url = web_contents->GetLastCommittedURL();
243 const std::string& page_encoding = web_contents->GetEncoding();
245 // Parse the download metadata.
246 base::string16 mime_type;
247 base::FilePath file_name;
248 GURL download_url;
249 if (!ParseDownloadMetadata(drop_data.download_metadata,
250 &mime_type,
251 &file_name,
252 &download_url))
253 return;
255 // Generate the file name based on both mime type and proposed file name.
256 std::string default_name =
257 GetContentClient()->browser()->GetDefaultDownloadName();
258 base::FilePath generated_download_file_name =
259 net::GenerateFileName(download_url,
260 std::string(),
261 std::string(),
262 base::UTF16ToUTF8(file_name.value()),
263 base::UTF16ToUTF8(mime_type),
264 default_name);
266 // http://crbug.com/332579
267 base::ThreadRestrictions::ScopedAllowIO allow_file_operations;
269 base::FilePath temp_dir_path;
270 if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
271 &temp_dir_path))
272 return;
274 base::FilePath download_path =
275 temp_dir_path.Append(generated_download_file_name);
277 // We cannot know when the target application will be done using the temporary
278 // file, so schedule it to be deleted after rebooting.
279 base::DeleteFileAfterReboot(download_path);
280 base::DeleteFileAfterReboot(temp_dir_path);
282 // Provide the data as file (CF_HDROP). A temporary download file with the
283 // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
284 scoped_refptr<DragDownloadFile> download_file =
285 new DragDownloadFile(
286 download_path,
287 base::File(),
288 download_url,
289 Referrer(page_url, drop_data.referrer_policy),
290 page_encoding,
291 web_contents);
292 ui::OSExchangeData::DownloadFileInfo file_download(base::FilePath(),
293 download_file.get());
294 provider->SetDownloadFileInfo(file_download);
296 #endif // defined(OS_WIN)
298 // Returns the CustomFormat to store file system files.
299 const ui::OSExchangeData::CustomFormat& GetFileSystemFileCustomFormat() {
300 static const char kFormatString[] = "chromium/x-file-system-files";
301 CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat,
302 format,
303 (ui::Clipboard::GetFormatType(kFormatString)));
304 return format;
307 // Writes file system files to the pickle.
308 void WriteFileSystemFilesToPickle(
309 const std::vector<DropData::FileSystemFileInfo>& file_system_files,
310 Pickle* pickle) {
311 pickle->WriteSizeT(file_system_files.size());
312 for (size_t i = 0; i < file_system_files.size(); ++i) {
313 pickle->WriteString(file_system_files[i].url.spec());
314 pickle->WriteInt64(file_system_files[i].size);
318 // Reads file system files from the pickle.
319 bool ReadFileSystemFilesFromPickle(
320 const Pickle& pickle,
321 std::vector<DropData::FileSystemFileInfo>* file_system_files) {
322 PickleIterator iter(pickle);
324 size_t num_files = 0;
325 if (!iter.ReadSizeT(&num_files))
326 return false;
327 file_system_files->resize(num_files);
329 for (size_t i = 0; i < num_files; ++i) {
330 std::string url_string;
331 int64 size = 0;
332 if (!iter.ReadString(&url_string) || !iter.ReadInt64(&size))
333 return false;
335 GURL url(url_string);
336 if (!url.is_valid())
337 return false;
339 (*file_system_files)[i].url = url;
340 (*file_system_files)[i].size = size;
342 return true;
345 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
346 void PrepareDragData(const DropData& drop_data,
347 ui::OSExchangeData::Provider* provider,
348 WebContentsImpl* web_contents) {
349 provider->MarkOriginatedFromRenderer();
350 #if defined(OS_WIN)
351 // Put download before file contents to prefer the download of a image over
352 // its thumbnail link.
353 if (!drop_data.download_metadata.empty())
354 PrepareDragForDownload(drop_data, provider, web_contents);
355 #endif
356 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
357 // We set the file contents before the URL because the URL also sets file
358 // contents (to a .URL shortcut). We want to prefer file content data over
359 // a shortcut so we add it first.
360 if (!drop_data.file_contents.empty())
361 PrepareDragForFileContents(drop_data, provider);
362 #endif
363 // Call SetString() before SetURL() when we actually have a custom string.
364 // SetURL() will itself do SetString() when a string hasn't been set yet,
365 // but we want to prefer drop_data.text.string() over the URL string if it
366 // exists.
367 if (!drop_data.text.string().empty())
368 provider->SetString(drop_data.text.string());
369 if (drop_data.url.is_valid())
370 provider->SetURL(drop_data.url, drop_data.url_title);
371 if (!drop_data.html.string().empty())
372 provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
373 if (!drop_data.filenames.empty())
374 provider->SetFilenames(drop_data.filenames);
375 if (!drop_data.file_system_files.empty()) {
376 Pickle pickle;
377 WriteFileSystemFilesToPickle(drop_data.file_system_files, &pickle);
378 provider->SetPickledData(GetFileSystemFileCustomFormat(), pickle);
380 if (!drop_data.custom_data.empty()) {
381 Pickle pickle;
382 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
383 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
384 pickle);
388 // Utility to fill a DropData object from ui::OSExchangeData.
389 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
390 drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
392 base::string16 plain_text;
393 data.GetString(&plain_text);
394 if (!plain_text.empty())
395 drop_data->text = base::NullableString16(plain_text, false);
397 GURL url;
398 base::string16 url_title;
399 data.GetURLAndTitle(
400 ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES, &url, &url_title);
401 if (url.is_valid()) {
402 drop_data->url = url;
403 drop_data->url_title = url_title;
406 base::string16 html;
407 GURL html_base_url;
408 data.GetHtml(&html, &html_base_url);
409 if (!html.empty())
410 drop_data->html = base::NullableString16(html, false);
411 if (html_base_url.is_valid())
412 drop_data->html_base_url = html_base_url;
414 data.GetFilenames(&drop_data->filenames);
416 Pickle pickle;
417 std::vector<DropData::FileSystemFileInfo> file_system_files;
418 if (data.GetPickledData(GetFileSystemFileCustomFormat(), &pickle) &&
419 ReadFileSystemFilesFromPickle(pickle, &file_system_files))
420 drop_data->file_system_files = file_system_files;
422 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
423 ui::ReadCustomDataIntoMap(
424 pickle.data(), pickle.size(), &drop_data->custom_data);
427 // Utilities to convert between blink::WebDragOperationsMask and
428 // ui::DragDropTypes.
429 int ConvertFromWeb(blink::WebDragOperationsMask ops) {
430 int drag_op = ui::DragDropTypes::DRAG_NONE;
431 if (ops & blink::WebDragOperationCopy)
432 drag_op |= ui::DragDropTypes::DRAG_COPY;
433 if (ops & blink::WebDragOperationMove)
434 drag_op |= ui::DragDropTypes::DRAG_MOVE;
435 if (ops & blink::WebDragOperationLink)
436 drag_op |= ui::DragDropTypes::DRAG_LINK;
437 return drag_op;
440 blink::WebDragOperationsMask ConvertToWeb(int drag_op) {
441 int web_drag_op = blink::WebDragOperationNone;
442 if (drag_op & ui::DragDropTypes::DRAG_COPY)
443 web_drag_op |= blink::WebDragOperationCopy;
444 if (drag_op & ui::DragDropTypes::DRAG_MOVE)
445 web_drag_op |= blink::WebDragOperationMove;
446 if (drag_op & ui::DragDropTypes::DRAG_LINK)
447 web_drag_op |= blink::WebDragOperationLink;
448 return (blink::WebDragOperationsMask) web_drag_op;
451 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
452 int web_input_event_modifiers = 0;
453 if (aura_event_flags & ui::EF_SHIFT_DOWN)
454 web_input_event_modifiers |= blink::WebInputEvent::ShiftKey;
455 if (aura_event_flags & ui::EF_CONTROL_DOWN)
456 web_input_event_modifiers |= blink::WebInputEvent::ControlKey;
457 if (aura_event_flags & ui::EF_ALT_DOWN)
458 web_input_event_modifiers |= blink::WebInputEvent::AltKey;
459 if (aura_event_flags & ui::EF_COMMAND_DOWN)
460 web_input_event_modifiers |= blink::WebInputEvent::MetaKey;
461 return web_input_event_modifiers;
464 } // namespace
466 class WebContentsViewAura::WindowObserver
467 : public aura::WindowObserver, public aura::WindowTreeHostObserver {
468 public:
469 explicit WindowObserver(WebContentsViewAura* view)
470 : view_(view),
471 host_window_(NULL) {
472 view_->window_->AddObserver(this);
474 #if defined(OS_WIN)
475 if (view_->window_->GetRootWindow())
476 view_->window_->GetRootWindow()->AddObserver(this);
477 #endif
480 ~WindowObserver() override {
481 view_->window_->RemoveObserver(this);
482 if (view_->window_->GetHost())
483 view_->window_->GetHost()->RemoveObserver(this);
484 if (host_window_)
485 host_window_->RemoveObserver(this);
486 #if defined(OS_WIN)
487 if (host_window_) {
488 const aura::Window::Windows& children = host_window_->children();
489 for (size_t i = 0; i < children.size(); ++i)
490 children[i]->RemoveObserver(this);
493 aura::Window* root_window = view_->window_->GetRootWindow();
494 if (root_window) {
495 root_window->RemoveObserver(this);
496 const aura::Window::Windows& root_children = root_window->children();
497 for (size_t i = 0; i < root_children.size(); ++i)
498 root_children[i]->RemoveObserver(this);
500 #endif
503 // Overridden from aura::WindowObserver:
504 void OnWindowHierarchyChanged(
505 const aura::WindowObserver::HierarchyChangeParams& params) override {
506 if (params.receiver != view_->window_.get() ||
507 !params.target->Contains(view_->window_.get())) {
508 return;
511 // Use the new parent's root window for calculating HiDPI subpixel offset.
512 RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
513 view_->web_contents_->GetRenderWidgetHostView());
514 if (rwhv)
515 rwhv->SnapToPhysicalPixelBoundary();
518 #if defined(OS_WIN)
519 // Constrained windows are added as children of the parent's parent's view
520 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
521 // so that it can update the plugins' cutout rects accordingly.
522 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
523 // going to be deprecated in a year, this is ok for now. The test for this is
524 // PrintPreviewTest.WindowedNPAPIPluginHidden.
525 virtual void OnWindowAdded(aura::Window* new_window) override {
526 if (!new_window->Contains(view_->window_.get())) {
527 // Skip the case when the parent moves to the root window.
528 if (new_window != host_window_) {
529 // Observe sibling windows of the WebContents, or children of the root
530 // window.
531 if (new_window->parent() == host_window_ ||
532 new_window->parent() == view_->window_->GetRootWindow()) {
533 new_window->AddObserver(this);
538 if (new_window->parent() == host_window_) {
539 UpdateConstrainedWindows(NULL);
543 virtual void OnWillRemoveWindow(aura::Window* window) override {
544 if (window == view_->window_)
545 return;
547 window->RemoveObserver(this);
548 UpdateConstrainedWindows(window);
551 virtual void OnWindowVisibilityChanged(aura::Window* window,
552 bool visible) override {
553 if (window == view_->window_ ||
554 window->parent() == host_window_ ||
555 window->parent() == view_->window_->GetRootWindow()) {
556 UpdateConstrainedWindows(NULL);
559 #endif
561 void OnWindowParentChanged(aura::Window* window,
562 aura::Window* parent) override {
563 if (window != view_->window_)
564 return;
566 aura::Window* host_window =
567 window->GetProperty(aura::client::kHostWindowKey);
568 if (!host_window)
569 host_window = parent;
571 if (host_window_)
572 host_window_->RemoveObserver(this);
574 #if defined(OS_WIN)
575 if (host_window_) {
576 const aura::Window::Windows& children = host_window_->children();
577 for (size_t i = 0; i < children.size(); ++i)
578 children[i]->RemoveObserver(this);
579 RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
580 view_->web_contents_->GetRenderWidgetHostView());
581 if (rwhv)
582 rwhv->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
585 // When we get parented to the root window, the code below will watch the
586 // host window, aka root window. Since we already watch the root window on
587 // Windows, unregister first so that the debug check doesn't fire.
588 if (host_window && host_window == window->GetRootWindow())
589 host_window->RemoveObserver(this);
591 // We need to undo the above if we were parented to the root window and then
592 // got parented to another window. At that point, the code before the ifdef
593 // would have stopped watching the root window.
594 if (window->GetRootWindow() &&
595 host_window != window->GetRootWindow() &&
596 !window->GetRootWindow()->HasObserver(this)) {
597 window->GetRootWindow()->AddObserver(this);
599 #endif
601 host_window_ = host_window;
602 if (host_window) {
603 host_window->AddObserver(this);
604 #if defined(OS_WIN)
605 if (host_window != window->GetRootWindow()) {
606 const aura::Window::Windows& children = host_window->children();
607 for (size_t i = 0; i < children.size(); ++i) {
608 if (!children[i]->Contains(view_->window_.get()))
609 children[i]->AddObserver(this);
612 #endif
616 void OnWindowBoundsChanged(aura::Window* window,
617 const gfx::Rect& old_bounds,
618 const gfx::Rect& new_bounds) override {
619 if (window == host_window_ || window == view_->window_) {
620 SendScreenRects();
621 if (view_->touch_editable_)
622 view_->touch_editable_->UpdateEditingController();
623 #if defined(OS_WIN)
624 } else {
625 UpdateConstrainedWindows(NULL);
626 #endif
630 void OnWindowDestroying(aura::Window* window) override {
631 if (window == host_window_) {
632 host_window_->RemoveObserver(this);
633 host_window_ = NULL;
637 void OnWindowAddedToRootWindow(aura::Window* window) override {
638 if (window == view_->window_) {
639 window->GetHost()->AddObserver(this);
640 #if defined(OS_WIN)
641 if (!window->GetRootWindow()->HasObserver(this))
642 window->GetRootWindow()->AddObserver(this);
643 #endif
647 void OnWindowRemovingFromRootWindow(aura::Window* window,
648 aura::Window* new_root) override {
649 if (window == view_->window_) {
650 window->GetHost()->RemoveObserver(this);
651 #if defined(OS_WIN)
652 window->GetRootWindow()->RemoveObserver(this);
654 const aura::Window::Windows& root_children =
655 window->GetRootWindow()->children();
656 for (size_t i = 0; i < root_children.size(); ++i) {
657 if (root_children[i] != view_->window_ &&
658 root_children[i] != host_window_) {
659 root_children[i]->RemoveObserver(this);
662 #endif
666 // Overridden WindowTreeHostObserver:
667 void OnHostMoved(const aura::WindowTreeHost* host,
668 const gfx::Point& new_origin) override {
669 TRACE_EVENT1("ui",
670 "WebContentsViewAura::WindowObserver::OnHostMoved",
671 "new_origin", new_origin.ToString());
673 // This is for the desktop case (i.e. Aura desktop).
674 SendScreenRects();
677 private:
678 void SendScreenRects() {
679 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
680 SendScreenRects();
683 #if defined(OS_WIN)
684 void UpdateConstrainedWindows(aura::Window* exclude) {
685 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
686 view_->web_contents_->GetRenderWidgetHostView());
687 if (!view)
688 return;
690 std::vector<gfx::Rect> constrained_windows;
691 if (host_window_) {
692 const aura::Window::Windows& children = host_window_->children();
693 for (size_t i = 0; i < children.size(); ++i) {
694 if (!children[i]->Contains(view_->window_.get()) &&
695 children[i] != exclude &&
696 children[i]->IsVisible()) {
697 constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
702 aura::Window* root_window = view_->window_->GetRootWindow();
703 const aura::Window::Windows& root_children = root_window->children();
704 if (root_window) {
705 for (size_t i = 0; i < root_children.size(); ++i) {
706 if (root_children[i]->IsVisible() &&
707 !root_children[i]->Contains(view_->window_.get())) {
708 constrained_windows.push_back(
709 root_children[i]->GetBoundsInRootWindow());
714 view->UpdateConstrainedWindowRects(constrained_windows);
716 #endif
718 WebContentsViewAura* view_;
720 // The parent window that hosts the constrained windows. We cache the old host
721 // view so that we can unregister when it's not the parent anymore.
722 aura::Window* host_window_;
724 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
727 ////////////////////////////////////////////////////////////////////////////////
728 // WebContentsViewAura, public:
730 WebContentsViewAura::WebContentsViewAura(
731 WebContentsImpl* web_contents,
732 WebContentsViewDelegate* delegate)
733 : web_contents_(web_contents),
734 delegate_(delegate),
735 current_drag_op_(blink::WebDragOperationNone),
736 drag_dest_delegate_(NULL),
737 current_rvh_for_drag_(NULL),
738 overscroll_change_brightness_(false),
739 current_overscroll_gesture_(OVERSCROLL_NONE),
740 completed_overscroll_gesture_(OVERSCROLL_NONE),
741 touch_editable_(TouchEditableImplAura::Create()),
742 is_or_was_visible_(false) {
745 ////////////////////////////////////////////////////////////////////////////////
746 // WebContentsViewAura, private:
748 WebContentsViewAura::~WebContentsViewAura() {
749 if (!window_)
750 return;
752 window_observer_.reset();
753 window_->RemoveObserver(this);
755 // Window needs a valid delegate during its destructor, so we explicitly
756 // delete it here.
757 window_.reset();
760 void WebContentsViewAura::SetTouchEditableForTest(
761 TouchEditableImplAura* touch_editable) {
762 touch_editable_.reset(touch_editable);
763 AttachTouchEditableToRenderView();
766 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
767 if (web_contents_->GetInterstitialPage())
768 web_contents_->GetInterstitialPage()->SetSize(size);
769 RenderWidgetHostView* rwhv =
770 web_contents_->GetRenderWidgetHostView();
771 if (rwhv)
772 rwhv->SetSize(size);
775 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
776 aura::Window* root_window = GetNativeView()->GetRootWindow();
777 gfx::Point screen_loc =
778 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
779 gfx::Point client_loc = screen_loc;
780 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
781 aura::Window* window = rvh->GetView()->GetNativeView();
782 aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
783 if (!web_contents_)
784 return;
785 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
786 screen_loc.x(), screen_loc.y(), ops);
789 void WebContentsViewAura::InstallOverscrollControllerDelegate(
790 RenderWidgetHostViewAura* view) {
791 const std::string value = base::CommandLine::ForCurrentProcess()->
792 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation);
793 if (value == "0") {
794 navigation_overlay_.reset();
795 return;
797 if (value == "2") {
798 navigation_overlay_.reset();
799 if (!gesture_nav_simple_)
800 gesture_nav_simple_.reset(new GestureNavSimple(web_contents_));
801 view->overscroll_controller()->set_delegate(gesture_nav_simple_.get());
802 return;
804 view->overscroll_controller()->set_delegate(this);
805 if (!navigation_overlay_)
806 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
809 void WebContentsViewAura::PrepareOverscrollWindow() {
810 // If there is an existing |overscroll_window_| which is in the middle of an
811 // animation, then destroying the window here causes the animation to be
812 // completed immediately, which triggers |OnImplicitAnimationsCompleted()|
813 // callback, and that tries to reset |overscroll_window_| again, causing a
814 // double-free. So use a temporary variable here.
815 if (overscroll_window_) {
816 base::AutoReset<OverscrollMode> reset_state(&current_overscroll_gesture_,
817 current_overscroll_gesture_);
818 scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
821 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
822 web_contents_,
823 current_overscroll_gesture_);
824 overscroll_window_.reset(new aura::Window(overscroll_delegate));
825 overscroll_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
826 overscroll_window_->SetTransparent(true);
827 overscroll_window_->Init(aura::WINDOW_LAYER_TEXTURED);
828 overscroll_window_->layer()->SetMasksToBounds(false);
829 overscroll_window_->SetName("OverscrollOverlay");
831 overscroll_change_brightness_ = overscroll_delegate->has_image();
832 window_->AddChild(overscroll_window_.get());
834 gfx::Rect bounds = gfx::Rect(window_->bounds().size());
835 if (ShouldNavigateForward(web_contents_->GetController(),
836 current_overscroll_gesture_)) {
837 // The overlay will be sliding in from the right edge towards the left in
838 // non-RTL, or sliding in from the left edge towards the right in RTL.
839 // So position the overlay window accordingly.
840 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
843 aura::Window* animate_window = GetWindowToAnimateForOverscroll();
844 if (animate_window == overscroll_window_)
845 window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
846 else
847 window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
849 UpdateOverscrollWindowBrightness(0.f);
851 overscroll_window_->SetBounds(bounds);
852 overscroll_window_->Show();
854 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
857 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
858 StopObservingImplicitAnimations();
859 aura::Window* content = GetContentNativeView();
860 content->layer()->GetAnimator()->AbortAllAnimations();
861 content->SetTransform(gfx::Transform());
862 content->layer()->SetLayerBrightness(0.f);
865 void WebContentsViewAura::ResetOverscrollTransform() {
866 if (!web_contents_->GetRenderWidgetHostView())
867 return;
868 aura::Window* target = GetWindowToAnimateForOverscroll();
869 if (!target)
870 return;
872 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
873 settings.SetPreemptionStrategy(
874 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
875 settings.SetTweenType(gfx::Tween::EASE_OUT);
876 settings.AddObserver(this);
877 target->SetTransform(gfx::Transform());
880 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
881 settings.SetPreemptionStrategy(
882 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
883 settings.SetTweenType(gfx::Tween::EASE_OUT);
884 UpdateOverscrollWindowBrightness(0.f);
888 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
889 if (!web_contents_->GetRenderWidgetHostView())
890 return;
892 // Animate out the current view first. Navigate to the requested history at
893 // the end of the animation.
894 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
895 return;
897 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
898 current_overscroll_gesture_, OVERSCROLL_COUNT);
899 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
900 overscroll_window_->delegate());
901 delegate->stop_forwarding_events();
903 completed_overscroll_gesture_ = mode;
904 aura::Window* target = GetWindowToAnimateForOverscroll();
905 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
906 settings.SetPreemptionStrategy(
907 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
908 settings.SetTweenType(gfx::Tween::EASE_OUT);
909 settings.AddObserver(this);
910 gfx::Transform transform;
911 int content_width =
912 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
913 float translate_x = static_cast<float>(mode == OVERSCROLL_WEST ?
914 -content_width : content_width);
915 transform.Translate(translate_x, 0);
916 target->SetTransform(transform);
917 UpdateOverscrollWindowBrightness(translate_x);
920 aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
921 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
922 return NULL;
924 return ShouldNavigateForward(web_contents_->GetController(),
925 current_overscroll_gesture_) ?
926 overscroll_window_.get() : GetContentNativeView();
929 gfx::Vector2dF WebContentsViewAura::GetTranslationForOverscroll(float delta_x,
930 float delta_y) {
931 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
932 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
933 return gfx::Vector2dF(0, delta_y);
935 // For horizontal overscroll, scroll freely if a navigation is possible. Do a
936 // resistive scroll otherwise.
937 const NavigationControllerImpl& controller = web_contents_->GetController();
938 const gfx::Rect& bounds = GetViewBounds();
939 const float bounds_width = static_cast<float>(bounds.width());
940 if (ShouldNavigateForward(controller, current_overscroll_gesture_))
941 return gfx::Vector2dF(std::max(-bounds_width, delta_x), 0);
942 else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
943 return gfx::Vector2dF(std::min(bounds_width, delta_x), 0);
944 return gfx::Vector2dF();
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(
988 float delta_y) {
989 if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
990 web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
993 ////////////////////////////////////////////////////////////////////////////////
994 // WebContentsViewAura, WebContentsView implementation:
996 gfx::NativeView WebContentsViewAura::GetNativeView() const {
997 return window_.get();
1000 gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
1001 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1002 return rwhv ? rwhv->GetNativeView() : NULL;
1005 gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
1006 gfx::NativeWindow window = window_->GetToplevelWindow();
1007 return window ? window : delegate_->GetNativeWindow();
1010 void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
1011 *out = window_->GetBoundsInScreen();
1014 void WebContentsViewAura::SizeContents(const gfx::Size& size) {
1015 gfx::Rect bounds = window_->bounds();
1016 if (bounds.size() != size) {
1017 bounds.set_size(size);
1018 window_->SetBounds(bounds);
1019 } else {
1020 // Our size matches what we want but the renderers size may not match.
1021 // Pretend we were resized so that the renderers size is updated too.
1022 SizeChangedCommon(size);
1026 void WebContentsViewAura::Focus() {
1027 if (web_contents_->GetInterstitialPage()) {
1028 web_contents_->GetInterstitialPage()->Focus();
1029 return;
1032 if (delegate_.get() && delegate_->Focus())
1033 return;
1035 RenderWidgetHostView* rwhv =
1036 web_contents_->GetFullscreenRenderWidgetHostView();
1037 if (!rwhv)
1038 rwhv = web_contents_->GetRenderWidgetHostView();
1039 if (rwhv)
1040 rwhv->Focus();
1043 void WebContentsViewAura::SetInitialFocus() {
1044 if (web_contents_->FocusLocationBarByDefault())
1045 web_contents_->SetFocusToLocationBar(false);
1046 else
1047 Focus();
1050 void WebContentsViewAura::StoreFocus() {
1051 if (delegate_)
1052 delegate_->StoreFocus();
1055 void WebContentsViewAura::RestoreFocus() {
1056 if (delegate_)
1057 delegate_->RestoreFocus();
1060 DropData* WebContentsViewAura::GetDropData() const {
1061 return current_drop_data_.get();
1064 gfx::Rect WebContentsViewAura::GetViewBounds() const {
1065 return window_->GetBoundsInScreen();
1068 ////////////////////////////////////////////////////////////////////////////////
1069 // WebContentsViewAura, WebContentsView implementation:
1071 void WebContentsViewAura::CreateView(
1072 const gfx::Size& initial_size, gfx::NativeView context) {
1073 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1074 // if the bookmark bar is not shown and you create a new tab). The right
1075 // value is set shortly after this, so its safe to ignore.
1077 aura::Env::CreateInstance(true);
1078 window_.reset(new aura::Window(this));
1079 window_->set_owned_by_parent(false);
1080 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
1081 window_->SetTransparent(false);
1082 window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
1083 window_->AddObserver(this);
1084 aura::Window* root_window = context ? context->GetRootWindow() : NULL;
1085 if (root_window) {
1086 // There are places where there is no context currently because object
1087 // hierarchies are built before they're attached to a Widget. (See
1088 // views::WebView as an example; GetWidget() returns NULL at the point
1089 // where we are created.)
1091 // It should be OK to not set a default parent since such users will
1092 // explicitly add this WebContentsViewAura to their tree after they create
1093 // us.
1094 if (root_window) {
1095 aura::client::ParentWindowWithContext(
1096 window_.get(), root_window, root_window->GetBoundsInScreen());
1099 window_->layer()->SetMasksToBounds(true);
1100 window_->SetName("WebContentsViewAura");
1102 // WindowObserver is not interesting and is problematic for Browser Plugin
1103 // guests.
1104 // The use cases for WindowObserver do not apply to Browser Plugins:
1105 // 1) guests do not support NPAPI plugins.
1106 // 2) guests' window bounds are supposed to come from its embedder.
1107 if (!BrowserPluginGuest::IsGuest(web_contents_))
1108 window_observer_.reset(new WindowObserver(this));
1110 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1111 // Hence, we save a reference to it locally. Similar model is used on other
1112 // platforms as well.
1113 if (delegate_)
1114 drag_dest_delegate_ = delegate_->GetDragDestDelegate();
1117 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
1118 RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
1119 if (render_widget_host->GetView()) {
1120 // During testing, the view will already be set up in most cases to the
1121 // test view, so we don't want to clobber it with a real one. To verify that
1122 // this actually is happening (and somebody isn't accidentally creating the
1123 // view twice), we check for the RVH Factory, which will be set when we're
1124 // making special ones (which go along with the special views).
1125 DCHECK(RenderViewHostFactory::has_factory());
1126 return static_cast<RenderWidgetHostViewBase*>(
1127 render_widget_host->GetView());
1130 RenderWidgetHostViewAura* view =
1131 new RenderWidgetHostViewAura(render_widget_host, is_guest_view_hack);
1132 view->InitAsChild(NULL);
1133 GetNativeView()->AddChild(view->GetNativeView());
1135 if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1136 navigation_overlay_->StartObserving();
1139 RenderWidgetHostImpl* host_impl =
1140 RenderWidgetHostImpl::From(render_widget_host);
1142 if (!host_impl->is_hidden())
1143 view->Show();
1145 // We listen to drag drop events in the newly created view's window.
1146 aura::client::SetDragDropDelegate(view->GetNativeView(), this);
1148 if (view->overscroll_controller() &&
1149 (!web_contents_->GetDelegate() ||
1150 web_contents_->GetDelegate()->CanOverscrollContent())) {
1151 InstallOverscrollControllerDelegate(view);
1154 AttachTouchEditableToRenderView();
1155 return view;
1158 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
1159 RenderWidgetHost* render_widget_host) {
1160 return new RenderWidgetHostViewAura(render_widget_host, false);
1163 void WebContentsViewAura::SetPageTitle(const base::string16& title) {
1164 window_->SetTitle(title);
1167 void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
1170 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
1171 if (navigation_overlay_.get() && navigation_overlay_->has_window())
1172 navigation_overlay_->StartObserving();
1173 AttachTouchEditableToRenderView();
1176 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
1177 RenderWidgetHostViewAura* view =
1178 ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
1179 if (view) {
1180 view->SetOverscrollControllerEnabled(enabled);
1181 if (enabled)
1182 InstallOverscrollControllerDelegate(view);
1185 if (!enabled)
1186 navigation_overlay_.reset();
1187 else if (!navigation_overlay_)
1188 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1191 ////////////////////////////////////////////////////////////////////////////////
1192 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1194 void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
1195 const ContextMenuParams& params) {
1196 if (touch_editable_) {
1197 touch_editable_->EndTouchEditing(false);
1199 if (delegate_) {
1200 delegate_->ShowContextMenu(render_frame_host, params);
1201 // WARNING: we may have been deleted during the call to ShowContextMenu().
1205 void WebContentsViewAura::StartDragging(
1206 const DropData& drop_data,
1207 blink::WebDragOperationsMask operations,
1208 const gfx::ImageSkia& image,
1209 const gfx::Vector2d& image_offset,
1210 const DragEventSourceInfo& event_info) {
1211 aura::Window* root_window = GetNativeView()->GetRootWindow();
1212 if (!aura::client::GetDragDropClient(root_window)) {
1213 web_contents_->SystemDragEnded();
1214 return;
1217 if (touch_editable_)
1218 touch_editable_->EndTouchEditing(false);
1220 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
1221 PrepareDragData(drop_data, provider, web_contents_);
1223 ui::OSExchangeData data(provider); // takes ownership of |provider|.
1225 if (!image.isNull())
1226 drag_utils::SetDragImageOnDataObject(image, image_offset, &data);
1228 scoped_ptr<WebDragSourceAura> drag_source(
1229 new WebDragSourceAura(GetNativeView(), web_contents_));
1231 // We need to enable recursive tasks on the message loop so we can get
1232 // updates while in the system DoDragDrop loop.
1233 int result_op = 0;
1235 gfx::NativeView content_native_view = GetContentNativeView();
1236 base::MessageLoop::ScopedNestableTaskAllower allow(
1237 base::MessageLoop::current());
1238 result_op = aura::client::GetDragDropClient(root_window)
1239 ->StartDragAndDrop(data,
1240 root_window,
1241 content_native_view,
1242 event_info.event_location,
1243 ConvertFromWeb(operations),
1244 event_info.event_source);
1247 // Bail out immediately if the contents view window is gone. Note that it is
1248 // not safe to access any class members in this case since |this| may already
1249 // be destroyed. The local variable |drag_source| will still be valid though,
1250 // so we can use it to determine if the window is gone.
1251 if (!drag_source->window()) {
1252 // Note that in this case, we don't need to call SystemDragEnded() since the
1253 // renderer is going away.
1254 return;
1257 EndDrag(ConvertToWeb(result_op));
1258 web_contents_->SystemDragEnded();
1261 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
1262 current_drag_op_ = operation;
1265 void WebContentsViewAura::GotFocus() {
1266 if (web_contents_->GetDelegate())
1267 web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
1270 void WebContentsViewAura::TakeFocus(bool reverse) {
1271 if (web_contents_->GetDelegate() &&
1272 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1273 delegate_.get()) {
1274 delegate_->TakeFocus(reverse);
1278 void WebContentsViewAura::ShowDisambiguationPopup(
1279 const gfx::Rect& target_rect,
1280 const SkBitmap& zoomed_bitmap,
1281 const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
1282 const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
1283 if (delegate_) {
1284 delegate_->ShowDisambiguationPopup(target_rect, zoomed_bitmap,
1285 window_.get(), gesture_cb, mouse_cb);
1289 void WebContentsViewAura::HideDisambiguationPopup() {
1290 if (delegate_)
1291 delegate_->HideDisambiguationPopup();
1294 ////////////////////////////////////////////////////////////////////////////////
1295 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1297 gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
1298 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1299 if (!rwhv || !rwhv->IsShowing())
1300 return gfx::Rect();
1302 return rwhv->GetViewBounds();
1305 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1306 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1307 return false;
1309 aura::Window* target = GetWindowToAnimateForOverscroll();
1310 gfx::Vector2dF translate = GetTranslationForOverscroll(delta_x, delta_y);
1311 gfx::Transform transform;
1313 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
1314 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
1315 OverscrollUpdateForWebContentsDelegate(translate.y());
1316 } else {
1317 // Only horizontal overscrolls participate in the navigation gesture.
1318 transform.Translate(translate.x(), translate.y());
1319 target->SetTransform(transform);
1320 UpdateOverscrollWindowBrightness(delta_x);
1323 return !translate.IsZero();
1326 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1327 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
1328 if (web_contents_->GetDelegate() &&
1329 IsScrollEndEffectEnabled() &&
1330 (mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
1331 web_contents_->GetDelegate()->OverscrollComplete();
1333 NavigationControllerImpl& controller = web_contents_->GetController();
1334 if (ShouldNavigateForward(controller, mode) ||
1335 ShouldNavigateBack(controller, mode)) {
1336 CompleteOverscrollNavigation(mode);
1337 return;
1340 ResetOverscrollTransform();
1343 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1344 OverscrollMode new_mode) {
1345 // Reset any in-progress overscroll animation first.
1346 ResetOverscrollTransform();
1348 if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
1349 OverscrollUpdateForWebContentsDelegate(0);
1351 if (new_mode != OVERSCROLL_NONE && touch_editable_)
1352 touch_editable_->OverscrollStarted();
1354 if (new_mode == OVERSCROLL_NONE ||
1355 !GetContentNativeView() ||
1356 ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
1357 navigation_overlay_.get() && navigation_overlay_->has_window())) {
1358 current_overscroll_gesture_ = OVERSCROLL_NONE;
1359 } else {
1360 aura::Window* target = GetWindowToAnimateForOverscroll();
1361 if (target) {
1362 StopObservingImplicitAnimations();
1363 target->layer()->GetAnimator()->AbortAllAnimations();
1365 // Cleanup state of the content window first, because that can reset the
1366 // value of |current_overscroll_gesture_|.
1367 PrepareContentWindowForOverscroll();
1369 current_overscroll_gesture_ = new_mode;
1370 if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
1371 current_overscroll_gesture_ == OVERSCROLL_WEST)
1372 PrepareOverscrollWindow();
1374 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
1376 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1379 ////////////////////////////////////////////////////////////////////////////////
1380 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1382 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1383 overscroll_shadow_.reset();
1385 if (ShouldNavigateForward(web_contents_->GetController(),
1386 completed_overscroll_gesture_)) {
1387 web_contents_->GetController().GoForward();
1388 PrepareOverscrollNavigationOverlay();
1389 } else if (ShouldNavigateBack(web_contents_->GetController(),
1390 completed_overscroll_gesture_)) {
1391 web_contents_->GetController().GoBack();
1392 PrepareOverscrollNavigationOverlay();
1393 } else {
1394 if (touch_editable_)
1395 touch_editable_->OverscrollCompleted();
1398 aura::Window* content = GetContentNativeView();
1399 if (content) {
1400 content->SetTransform(gfx::Transform());
1401 content->layer()->SetLayerBrightness(0.f);
1403 current_overscroll_gesture_ = OVERSCROLL_NONE;
1404 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1405 overscroll_window_.reset();
1408 ////////////////////////////////////////////////////////////////////////////////
1409 // WebContentsViewAura, aura::WindowDelegate implementation:
1411 gfx::Size WebContentsViewAura::GetMinimumSize() const {
1412 return gfx::Size();
1415 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1416 return gfx::Size();
1419 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1420 const gfx::Rect& new_bounds) {
1421 SizeChangedCommon(new_bounds.size());
1422 if (delegate_)
1423 delegate_->SizeChanged(new_bounds.size());
1425 // Constrained web dialogs, need to be kept centered over our content area.
1426 for (size_t i = 0; i < window_->children().size(); i++) {
1427 if (window_->children()[i]->GetProperty(
1428 aura::client::kConstrainedWindowKey)) {
1429 gfx::Rect bounds = window_->children()[i]->bounds();
1430 bounds.set_origin(
1431 gfx::Point((new_bounds.width() - bounds.width()) / 2,
1432 (new_bounds.height() - bounds.height()) / 2));
1433 window_->children()[i]->SetBounds(bounds);
1438 gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1439 return gfx::kNullCursor;
1442 int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1443 return HTCLIENT;
1446 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1447 aura::Window* child,
1448 const gfx::Point& location) {
1449 return true;
1452 bool WebContentsViewAura::CanFocus() {
1453 // Do not take the focus if the render widget host view aura is gone or
1454 // is in the process of shutting down because neither the view window nor
1455 // this window can handle key events.
1456 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
1457 web_contents_->GetRenderWidgetHostView());
1458 if (view != NULL && !view->IsClosing())
1459 return true;
1461 return false;
1464 void WebContentsViewAura::OnCaptureLost() {
1467 void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
1470 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1471 float device_scale_factor) {
1474 void WebContentsViewAura::OnWindowDestroying(aura::Window* window) {
1475 // This means the destructor is going to be called soon. If there is an
1476 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1477 // then destroying it in the WebContentsViewAura destructor can trigger other
1478 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1479 // destroy the overscroll window here.
1480 navigation_overlay_.reset();
1481 overscroll_window_.reset();
1484 void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) {
1487 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1490 bool WebContentsViewAura::HasHitTestMask() const {
1491 return false;
1494 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1497 ////////////////////////////////////////////////////////////////////////////////
1498 // WebContentsViewAura, ui::EventHandler implementation:
1500 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1503 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1504 if (!web_contents_->GetDelegate())
1505 return;
1507 switch (event->type()) {
1508 case ui::ET_MOUSE_PRESSED:
1509 web_contents_->GetDelegate()->ActivateContents(web_contents_);
1510 break;
1511 case ui::ET_MOUSE_MOVED:
1512 case ui::ET_MOUSE_EXITED:
1513 web_contents_->GetDelegate()->ContentsMouseEvent(
1514 web_contents_,
1515 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1516 event->type() == ui::ET_MOUSE_MOVED);
1517 break;
1518 default:
1519 break;
1523 ////////////////////////////////////////////////////////////////////////////////
1524 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1526 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1527 current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1528 current_drop_data_.reset(new DropData());
1530 PrepareDropData(current_drop_data_.get(), event.data());
1531 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1533 // Give the delegate an opportunity to cancel the drag.
1534 if (web_contents_->GetDelegate() &&
1535 !web_contents_->GetDelegate()->CanDragEnter(
1536 web_contents_, *current_drop_data_.get(), op)) {
1537 current_drop_data_.reset(NULL);
1538 return;
1541 if (drag_dest_delegate_)
1542 drag_dest_delegate_->DragInitialize(web_contents_);
1544 gfx::Point screen_pt =
1545 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1546 web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1547 *current_drop_data_.get(), event.location(), screen_pt, op,
1548 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1550 if (drag_dest_delegate_) {
1551 drag_dest_delegate_->OnReceiveDragData(event.data());
1552 drag_dest_delegate_->OnDragEnter();
1556 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1557 DCHECK(current_rvh_for_drag_);
1558 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1559 OnDragEntered(event);
1561 if (!current_drop_data_)
1562 return ui::DragDropTypes::DRAG_NONE;
1564 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1565 gfx::Point screen_pt =
1566 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1567 web_contents_->GetRenderViewHost()->DragTargetDragOver(
1568 event.location(), screen_pt, op,
1569 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1571 if (drag_dest_delegate_)
1572 drag_dest_delegate_->OnDragOver();
1574 return ConvertFromWeb(current_drag_op_);
1577 void WebContentsViewAura::OnDragExited() {
1578 DCHECK(current_rvh_for_drag_);
1579 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1580 return;
1582 if (!current_drop_data_)
1583 return;
1585 web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1586 if (drag_dest_delegate_)
1587 drag_dest_delegate_->OnDragLeave();
1589 current_drop_data_.reset();
1592 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1593 DCHECK(current_rvh_for_drag_);
1594 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1595 OnDragEntered(event);
1597 if (!current_drop_data_)
1598 return ui::DragDropTypes::DRAG_NONE;
1600 web_contents_->GetRenderViewHost()->DragTargetDrop(
1601 event.location(),
1602 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1603 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1604 if (drag_dest_delegate_)
1605 drag_dest_delegate_->OnDrop();
1606 current_drop_data_.reset();
1607 return ConvertFromWeb(current_drag_op_);
1610 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
1611 bool visible) {
1612 // Ignore any visibility changes in the hierarchy below.
1613 if (window != window_.get() && window_->Contains(window))
1614 return;
1616 UpdateWebContentsVisibility(visible);
1619 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible) {
1620 if (!is_or_was_visible_) {
1621 // We should not hide the web contents before it was shown the first time,
1622 // since resources would immediately be destroyed and only re-created after
1623 // content got loaded. In this state the window content is undefined and can
1624 // show garbage.
1625 // However - the page load mechanism requires an activation call through a
1626 // visibility call to (re)load.
1627 if (visible) {
1628 is_or_was_visible_ = true;
1629 web_contents_->WasShown();
1631 return;
1633 if (visible) {
1634 if (!web_contents_->should_normally_be_visible())
1635 web_contents_->WasShown();
1636 } else {
1637 if (web_contents_->should_normally_be_visible())
1638 web_contents_->WasHidden();
1642 } // namespace content