Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_view_aura.cc
blobe6c144b50a4f5cb193a6f45f7af24802a87df97b
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/strings/utf_string_conversions.h"
11 #include "content/browser/browser_plugin/browser_plugin_guest.h"
12 #include "content/browser/download/drag_download_util.h"
13 #include "content/browser/frame_host/interstitial_page_impl.h"
14 #include "content/browser/frame_host/navigation_entry_impl.h"
15 #include "content/browser/renderer_host/dip_util.h"
16 #include "content/browser/renderer_host/input/touch_selection_controller_client_aura.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/overscroll_navigation_overlay.h"
25 #include "content/browser/web_contents/web_contents_impl.h"
26 #include "content/public/browser/content_browser_client.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "content/public/browser/notification_source.h"
30 #include "content/public/browser/notification_types.h"
31 #include "content/public/browser/overscroll_configuration.h"
32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/render_widget_host.h"
34 #include "content/public/browser/render_widget_host_view.h"
35 #include "content/public/browser/web_contents_delegate.h"
36 #include "content/public/browser/web_contents_observer.h"
37 #include "content/public/browser/web_contents_view_delegate.h"
38 #include "content/public/browser/web_drag_dest_delegate.h"
39 #include "content/public/common/content_client.h"
40 #include "content/public/common/content_switches.h"
41 #include "content/public/common/drop_data.h"
42 #include "net/base/filename_util.h"
43 #include "third_party/WebKit/public/web/WebInputEvent.h"
44 #include "ui/aura/client/aura_constants.h"
45 #include "ui/aura/client/window_tree_client.h"
46 #include "ui/aura/env.h"
47 #include "ui/aura/window.h"
48 #include "ui/aura/window_observer.h"
49 #include "ui/aura/window_tree_host.h"
50 #include "ui/aura/window_tree_host_observer.h"
51 #include "ui/base/clipboard/clipboard.h"
52 #include "ui/base/clipboard/custom_data_helper.h"
53 #include "ui/base/dragdrop/drag_drop_types.h"
54 #include "ui/base/dragdrop/drag_utils.h"
55 #include "ui/base/dragdrop/drop_target_event.h"
56 #include "ui/base/dragdrop/os_exchange_data.h"
57 #include "ui/base/hit_test.h"
58 #include "ui/compositor/layer.h"
59 #include "ui/events/event.h"
60 #include "ui/events/event_utils.h"
61 #include "ui/gfx/canvas.h"
62 #include "ui/gfx/image/image.h"
63 #include "ui/gfx/image/image_png_rep.h"
64 #include "ui/gfx/image/image_skia.h"
65 #include "ui/gfx/screen.h"
66 #include "ui/touch_selection/touch_selection_controller.h"
67 #include "ui/wm/public/drag_drop_client.h"
68 #include "ui/wm/public/drag_drop_delegate.h"
70 namespace content {
71 WebContentsView* CreateWebContentsView(
72 WebContentsImpl* web_contents,
73 WebContentsViewDelegate* delegate,
74 RenderViewHostDelegateView** render_view_host_delegate_view) {
75 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
76 *render_view_host_delegate_view = rv;
77 return rv;
80 namespace {
82 bool IsScrollEndEffectEnabled() {
83 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
84 switches::kScrollEndEffect) == "1";
87 RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
88 RenderWidgetHostView* view) {
89 if (!view || RenderViewHostFactory::has_factory())
90 return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests.
92 RenderViewHost* rvh = RenderViewHost::From(view->GetRenderWidgetHost());
93 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
94 rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
95 if (BrowserPluginGuest::IsGuest(web_contents))
96 return NULL;
97 return static_cast<RenderWidgetHostViewAura*>(view);
100 // Listens to all mouse drag events during a drag and drop and sends them to
101 // the renderer.
102 class WebDragSourceAura : public NotificationObserver {
103 public:
104 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
105 : window_(window),
106 contents_(contents) {
107 registrar_.Add(this,
108 NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
109 Source<WebContents>(contents));
112 ~WebDragSourceAura() override {}
114 // NotificationObserver:
115 void Observe(int type,
116 const NotificationSource& source,
117 const NotificationDetails& details) override {
118 if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
119 return;
121 // Cancel the drag if it is still in progress.
122 aura::client::DragDropClient* dnd_client =
123 aura::client::GetDragDropClient(window_->GetRootWindow());
124 if (dnd_client && dnd_client->IsDragDropInProgress())
125 dnd_client->DragCancel();
127 window_ = NULL;
128 contents_ = NULL;
131 aura::Window* window() const { return window_; }
133 private:
134 aura::Window* window_;
135 WebContentsImpl* contents_;
136 NotificationRegistrar registrar_;
138 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
141 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
142 // Fill out the OSExchangeData with a file contents, synthesizing a name if
143 // necessary.
144 void PrepareDragForFileContents(const DropData& drop_data,
145 ui::OSExchangeData::Provider* provider) {
146 base::FilePath file_name =
147 base::FilePath::FromUTF16Unsafe(drop_data.file_description_filename);
148 // Images without ALT text will only have a file extension so we need to
149 // synthesize one from the provided extension and URL.
150 if (file_name.BaseName().RemoveExtension().empty()) {
151 const base::FilePath::StringType extension = file_name.Extension();
152 // Retrieve the name from the URL.
153 file_name = net::GenerateFileName(drop_data.url, "", "", "", "", "")
154 .ReplaceExtension(extension);
156 provider->SetFileContents(file_name, drop_data.file_contents);
158 #endif
160 #if defined(OS_WIN)
161 void PrepareDragForDownload(
162 const DropData& drop_data,
163 ui::OSExchangeData::Provider* provider,
164 WebContentsImpl* web_contents) {
165 const GURL& page_url = web_contents->GetLastCommittedURL();
166 const std::string& page_encoding = web_contents->GetEncoding();
168 // Parse the download metadata.
169 base::string16 mime_type;
170 base::FilePath file_name;
171 GURL download_url;
172 if (!ParseDownloadMetadata(drop_data.download_metadata,
173 &mime_type,
174 &file_name,
175 &download_url))
176 return;
178 // Generate the file name based on both mime type and proposed file name.
179 std::string default_name =
180 GetContentClient()->browser()->GetDefaultDownloadName();
181 base::FilePath generated_download_file_name =
182 net::GenerateFileName(download_url,
183 std::string(),
184 std::string(),
185 base::UTF16ToUTF8(file_name.value()),
186 base::UTF16ToUTF8(mime_type),
187 default_name);
189 // http://crbug.com/332579
190 base::ThreadRestrictions::ScopedAllowIO allow_file_operations;
192 base::FilePath temp_dir_path;
193 if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
194 &temp_dir_path))
195 return;
197 base::FilePath download_path =
198 temp_dir_path.Append(generated_download_file_name);
200 // We cannot know when the target application will be done using the temporary
201 // file, so schedule it to be deleted after rebooting.
202 base::DeleteFileAfterReboot(download_path);
203 base::DeleteFileAfterReboot(temp_dir_path);
205 // Provide the data as file (CF_HDROP). A temporary download file with the
206 // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
207 scoped_refptr<DragDownloadFile> download_file =
208 new DragDownloadFile(
209 download_path,
210 base::File(),
211 download_url,
212 Referrer(page_url, drop_data.referrer_policy),
213 page_encoding,
214 web_contents);
215 ui::OSExchangeData::DownloadFileInfo file_download(base::FilePath(),
216 download_file.get());
217 provider->SetDownloadFileInfo(file_download);
219 #endif // defined(OS_WIN)
221 // Returns the CustomFormat to store file system files.
222 const ui::OSExchangeData::CustomFormat& GetFileSystemFileCustomFormat() {
223 static const char kFormatString[] = "chromium/x-file-system-files";
224 CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat,
225 format,
226 (ui::Clipboard::GetFormatType(kFormatString)));
227 return format;
230 // Writes file system files to the pickle.
231 void WriteFileSystemFilesToPickle(
232 const std::vector<DropData::FileSystemFileInfo>& file_system_files,
233 base::Pickle* pickle) {
234 pickle->WriteSizeT(file_system_files.size());
235 for (size_t i = 0; i < file_system_files.size(); ++i) {
236 pickle->WriteString(file_system_files[i].url.spec());
237 pickle->WriteInt64(file_system_files[i].size);
241 // Reads file system files from the pickle.
242 bool ReadFileSystemFilesFromPickle(
243 const base::Pickle& pickle,
244 std::vector<DropData::FileSystemFileInfo>* file_system_files) {
245 base::PickleIterator iter(pickle);
247 size_t num_files = 0;
248 if (!iter.ReadSizeT(&num_files))
249 return false;
250 file_system_files->resize(num_files);
252 for (size_t i = 0; i < num_files; ++i) {
253 std::string url_string;
254 int64 size = 0;
255 if (!iter.ReadString(&url_string) || !iter.ReadInt64(&size))
256 return false;
258 GURL url(url_string);
259 if (!url.is_valid())
260 return false;
262 (*file_system_files)[i].url = url;
263 (*file_system_files)[i].size = size;
265 return true;
268 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
269 void PrepareDragData(const DropData& drop_data,
270 ui::OSExchangeData::Provider* provider,
271 WebContentsImpl* web_contents) {
272 provider->MarkOriginatedFromRenderer();
273 #if defined(OS_WIN)
274 // Put download before file contents to prefer the download of a image over
275 // its thumbnail link.
276 if (!drop_data.download_metadata.empty())
277 PrepareDragForDownload(drop_data, provider, web_contents);
278 #endif
279 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
280 // We set the file contents before the URL because the URL also sets file
281 // contents (to a .URL shortcut). We want to prefer file content data over
282 // a shortcut so we add it first.
283 if (!drop_data.file_contents.empty())
284 PrepareDragForFileContents(drop_data, provider);
285 #endif
286 // Call SetString() before SetURL() when we actually have a custom string.
287 // SetURL() will itself do SetString() when a string hasn't been set yet,
288 // but we want to prefer drop_data.text.string() over the URL string if it
289 // exists.
290 if (!drop_data.text.string().empty())
291 provider->SetString(drop_data.text.string());
292 if (drop_data.url.is_valid())
293 provider->SetURL(drop_data.url, drop_data.url_title);
294 if (!drop_data.html.string().empty())
295 provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
296 if (!drop_data.filenames.empty())
297 provider->SetFilenames(drop_data.filenames);
298 if (!drop_data.file_system_files.empty()) {
299 base::Pickle pickle;
300 WriteFileSystemFilesToPickle(drop_data.file_system_files, &pickle);
301 provider->SetPickledData(GetFileSystemFileCustomFormat(), pickle);
303 if (!drop_data.custom_data.empty()) {
304 base::Pickle pickle;
305 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
306 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
307 pickle);
311 // Utility to fill a DropData object from ui::OSExchangeData.
312 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
313 drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
315 base::string16 plain_text;
316 data.GetString(&plain_text);
317 if (!plain_text.empty())
318 drop_data->text = base::NullableString16(plain_text, false);
320 GURL url;
321 base::string16 url_title;
322 data.GetURLAndTitle(
323 ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES, &url, &url_title);
324 if (url.is_valid()) {
325 drop_data->url = url;
326 drop_data->url_title = url_title;
329 base::string16 html;
330 GURL html_base_url;
331 data.GetHtml(&html, &html_base_url);
332 if (!html.empty())
333 drop_data->html = base::NullableString16(html, false);
334 if (html_base_url.is_valid())
335 drop_data->html_base_url = html_base_url;
337 data.GetFilenames(&drop_data->filenames);
339 base::Pickle pickle;
340 std::vector<DropData::FileSystemFileInfo> file_system_files;
341 if (data.GetPickledData(GetFileSystemFileCustomFormat(), &pickle) &&
342 ReadFileSystemFilesFromPickle(pickle, &file_system_files))
343 drop_data->file_system_files = file_system_files;
345 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
346 ui::ReadCustomDataIntoMap(
347 pickle.data(), pickle.size(), &drop_data->custom_data);
350 // Utilities to convert between blink::WebDragOperationsMask and
351 // ui::DragDropTypes.
352 int ConvertFromWeb(blink::WebDragOperationsMask ops) {
353 int drag_op = ui::DragDropTypes::DRAG_NONE;
354 if (ops & blink::WebDragOperationCopy)
355 drag_op |= ui::DragDropTypes::DRAG_COPY;
356 if (ops & blink::WebDragOperationMove)
357 drag_op |= ui::DragDropTypes::DRAG_MOVE;
358 if (ops & blink::WebDragOperationLink)
359 drag_op |= ui::DragDropTypes::DRAG_LINK;
360 return drag_op;
363 blink::WebDragOperationsMask ConvertToWeb(int drag_op) {
364 int web_drag_op = blink::WebDragOperationNone;
365 if (drag_op & ui::DragDropTypes::DRAG_COPY)
366 web_drag_op |= blink::WebDragOperationCopy;
367 if (drag_op & ui::DragDropTypes::DRAG_MOVE)
368 web_drag_op |= blink::WebDragOperationMove;
369 if (drag_op & ui::DragDropTypes::DRAG_LINK)
370 web_drag_op |= blink::WebDragOperationLink;
371 return (blink::WebDragOperationsMask) web_drag_op;
374 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
375 int web_input_event_modifiers = 0;
376 if (aura_event_flags & ui::EF_SHIFT_DOWN)
377 web_input_event_modifiers |= blink::WebInputEvent::ShiftKey;
378 if (aura_event_flags & ui::EF_CONTROL_DOWN)
379 web_input_event_modifiers |= blink::WebInputEvent::ControlKey;
380 if (aura_event_flags & ui::EF_ALT_DOWN)
381 web_input_event_modifiers |= blink::WebInputEvent::AltKey;
382 if (aura_event_flags & ui::EF_COMMAND_DOWN)
383 web_input_event_modifiers |= blink::WebInputEvent::MetaKey;
384 if (aura_event_flags & ui::EF_LEFT_MOUSE_BUTTON)
385 web_input_event_modifiers |= blink::WebInputEvent::LeftButtonDown;
386 if (aura_event_flags & ui::EF_MIDDLE_MOUSE_BUTTON)
387 web_input_event_modifiers |= blink::WebInputEvent::MiddleButtonDown;
388 if (aura_event_flags & ui::EF_RIGHT_MOUSE_BUTTON)
389 web_input_event_modifiers |= blink::WebInputEvent::RightButtonDown;
390 return web_input_event_modifiers;
393 } // namespace
395 class WebContentsViewAura::WindowObserver
396 : public aura::WindowObserver, public aura::WindowTreeHostObserver {
397 public:
398 explicit WindowObserver(WebContentsViewAura* view)
399 : view_(view),
400 host_window_(NULL) {
401 view_->window_->AddObserver(this);
403 #if defined(OS_WIN)
404 if (view_->window_->GetRootWindow())
405 view_->window_->GetRootWindow()->AddObserver(this);
406 #endif
409 ~WindowObserver() override {
410 view_->window_->RemoveObserver(this);
411 if (view_->window_->GetHost())
412 view_->window_->GetHost()->RemoveObserver(this);
413 if (host_window_)
414 host_window_->RemoveObserver(this);
415 #if defined(OS_WIN)
416 if (host_window_) {
417 const aura::Window::Windows& children = host_window_->children();
418 for (size_t i = 0; i < children.size(); ++i)
419 children[i]->RemoveObserver(this);
422 aura::Window* root_window = view_->window_->GetRootWindow();
423 if (root_window) {
424 root_window->RemoveObserver(this);
425 const aura::Window::Windows& root_children = root_window->children();
426 for (size_t i = 0; i < root_children.size(); ++i)
427 root_children[i]->RemoveObserver(this);
429 #endif
432 #if defined(OS_WIN)
433 // Constrained windows are added as children of the parent's parent's view
434 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
435 // so that it can update the plugins' cutout rects accordingly.
436 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
437 // going to be deprecated in a year, this is ok for now. The test for this is
438 // PrintPreviewTest.WindowedNPAPIPluginHidden.
439 void OnWindowAdded(aura::Window* new_window) override {
440 if (!new_window->Contains(view_->window_.get())) {
441 // Skip the case when the parent moves to the root window.
442 if (new_window != host_window_) {
443 // Observe sibling windows of the WebContents, or children of the root
444 // window.
445 if (new_window->parent() == host_window_ ||
446 new_window->parent() == view_->window_->GetRootWindow()) {
447 new_window->AddObserver(this);
452 if (new_window->parent() == host_window_) {
453 UpdateConstrainedWindows(NULL);
457 void OnWillRemoveWindow(aura::Window* window) override {
458 if (window == view_->window_)
459 return;
461 window->RemoveObserver(this);
462 UpdateConstrainedWindows(window);
465 void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
466 if (window == view_->window_ ||
467 window->parent() == host_window_ ||
468 window->parent() == view_->window_->GetRootWindow()) {
469 UpdateConstrainedWindows(NULL);
472 #endif
474 void OnWindowParentChanged(aura::Window* window,
475 aura::Window* parent) override {
476 if (window != view_->window_)
477 return;
479 aura::Window* host_window =
480 window->GetProperty(aura::client::kHostWindowKey);
481 if (!host_window)
482 host_window = parent;
484 if (host_window_)
485 host_window_->RemoveObserver(this);
487 #if defined(OS_WIN)
488 if (host_window_) {
489 const aura::Window::Windows& children = host_window_->children();
490 for (size_t i = 0; i < children.size(); ++i)
491 children[i]->RemoveObserver(this);
492 RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
493 view_->web_contents_->GetRenderWidgetHostView());
494 if (rwhv)
495 rwhv->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
498 // When we get parented to the root window, the code below will watch the
499 // host window, aka root window. Since we already watch the root window on
500 // Windows, unregister first so that the debug check doesn't fire.
501 if (host_window && host_window == window->GetRootWindow())
502 host_window->RemoveObserver(this);
504 // We need to undo the above if we were parented to the root window and then
505 // got parented to another window. At that point, the code before the ifdef
506 // would have stopped watching the root window.
507 if (window->GetRootWindow() &&
508 host_window != window->GetRootWindow() &&
509 !window->GetRootWindow()->HasObserver(this)) {
510 window->GetRootWindow()->AddObserver(this);
512 #endif
514 host_window_ = host_window;
515 if (host_window) {
516 host_window->AddObserver(this);
517 #if defined(OS_WIN)
518 if (host_window != window->GetRootWindow()) {
519 const aura::Window::Windows& children = host_window->children();
520 for (size_t i = 0; i < children.size(); ++i) {
521 if (!children[i]->Contains(view_->window_.get()))
522 children[i]->AddObserver(this);
525 #endif
529 void OnWindowBoundsChanged(aura::Window* window,
530 const gfx::Rect& old_bounds,
531 const gfx::Rect& new_bounds) override {
532 if (window == host_window_ || window == view_->window_) {
533 SendScreenRects();
534 if (old_bounds.origin() != new_bounds.origin()) {
535 TouchSelectionControllerClientAura* selection_controller_client =
536 view_->GetSelectionControllerClient();
537 if (selection_controller_client)
538 selection_controller_client->OnWindowMoved();
540 #if defined(OS_WIN)
541 } else {
542 UpdateConstrainedWindows(NULL);
543 #endif
547 void OnWindowDestroying(aura::Window* window) override {
548 if (window == host_window_) {
549 host_window_->RemoveObserver(this);
550 host_window_ = NULL;
554 void OnWindowAddedToRootWindow(aura::Window* window) override {
555 if (window == view_->window_) {
556 window->GetHost()->AddObserver(this);
557 #if defined(OS_WIN)
558 if (!window->GetRootWindow()->HasObserver(this))
559 window->GetRootWindow()->AddObserver(this);
560 #endif
564 void OnWindowRemovingFromRootWindow(aura::Window* window,
565 aura::Window* new_root) override {
566 if (window == view_->window_) {
567 window->GetHost()->RemoveObserver(this);
568 #if defined(OS_WIN)
569 window->GetRootWindow()->RemoveObserver(this);
571 const aura::Window::Windows& root_children =
572 window->GetRootWindow()->children();
573 for (size_t i = 0; i < root_children.size(); ++i) {
574 if (root_children[i] != view_->window_ &&
575 root_children[i] != host_window_) {
576 root_children[i]->RemoveObserver(this);
579 #endif
583 // Overridden WindowTreeHostObserver:
584 void OnHostMoved(const aura::WindowTreeHost* host,
585 const gfx::Point& new_origin) override {
586 TRACE_EVENT1("ui",
587 "WebContentsViewAura::WindowObserver::OnHostMoved",
588 "new_origin", new_origin.ToString());
590 // This is for the desktop case (i.e. Aura desktop).
591 SendScreenRects();
594 private:
595 void SendScreenRects() {
596 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
597 SendScreenRects();
600 #if defined(OS_WIN)
601 void UpdateConstrainedWindows(aura::Window* exclude) {
602 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
603 view_->web_contents_->GetRenderWidgetHostView());
604 if (!view)
605 return;
607 std::vector<gfx::Rect> constrained_windows;
608 if (host_window_) {
609 const aura::Window::Windows& children = host_window_->children();
610 for (size_t i = 0; i < children.size(); ++i) {
611 if (!children[i]->Contains(view_->window_.get()) &&
612 children[i] != exclude &&
613 children[i]->IsVisible()) {
614 constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
619 aura::Window* root_window = view_->window_->GetRootWindow();
620 const aura::Window::Windows& root_children = root_window->children();
621 if (root_window) {
622 for (size_t i = 0; i < root_children.size(); ++i) {
623 if (root_children[i]->IsVisible() &&
624 !root_children[i]->Contains(view_->window_.get())) {
625 constrained_windows.push_back(
626 root_children[i]->GetBoundsInRootWindow());
631 view->UpdateConstrainedWindowRects(constrained_windows);
633 #endif
635 WebContentsViewAura* view_;
637 // The parent window that hosts the constrained windows. We cache the old host
638 // view so that we can unregister when it's not the parent anymore.
639 aura::Window* host_window_;
641 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
644 ////////////////////////////////////////////////////////////////////////////////
645 // WebContentsViewAura, public:
647 WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
648 WebContentsViewDelegate* delegate)
649 : web_contents_(web_contents),
650 delegate_(delegate),
651 current_drag_op_(blink::WebDragOperationNone),
652 drag_dest_delegate_(NULL),
653 current_rvh_for_drag_(NULL),
654 current_overscroll_gesture_(OVERSCROLL_NONE),
655 completed_overscroll_gesture_(OVERSCROLL_NONE),
656 navigation_overlay_(nullptr),
657 is_or_was_visible_(false) {
660 ////////////////////////////////////////////////////////////////////////////////
661 // WebContentsViewAura, private:
663 WebContentsViewAura::~WebContentsViewAura() {
664 if (!window_)
665 return;
667 window_observer_.reset();
668 window_->RemoveObserver(this);
670 // Window needs a valid delegate during its destructor, so we explicitly
671 // delete it here.
672 window_.reset();
675 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
676 if (web_contents_->GetInterstitialPage())
677 web_contents_->GetInterstitialPage()->SetSize(size);
678 RenderWidgetHostView* rwhv =
679 web_contents_->GetRenderWidgetHostView();
680 if (rwhv)
681 rwhv->SetSize(size);
684 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
685 aura::Window* root_window = GetNativeView()->GetRootWindow();
686 gfx::Point screen_loc =
687 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
688 gfx::Point client_loc = screen_loc;
689 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
690 aura::Window* window = rvh->GetView()->GetNativeView();
691 aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
692 if (!web_contents_)
693 return;
694 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
695 screen_loc.x(), screen_loc.y(), ops);
698 void WebContentsViewAura::InstallOverscrollControllerDelegate(
699 RenderWidgetHostViewAura* view) {
700 const std::string value = base::CommandLine::ForCurrentProcess()->
701 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation);
702 if (value == "0") {
703 navigation_overlay_.reset();
704 return;
706 if (value == "2") {
707 navigation_overlay_.reset();
708 if (!gesture_nav_simple_)
709 gesture_nav_simple_.reset(new GestureNavSimple(web_contents_));
710 view->overscroll_controller()->set_delegate(gesture_nav_simple_.get());
711 return;
713 view->overscroll_controller()->set_delegate(this);
714 if (!navigation_overlay_) {
715 navigation_overlay_.reset(
716 new OverscrollNavigationOverlay(web_contents_, window_.get()));
720 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
721 if (!web_contents_->GetRenderWidgetHostView())
722 return;
723 navigation_overlay_->relay_delegate()->OnOverscrollComplete(mode);
724 ui::TouchSelectionController* selection_controller = GetSelectionController();
725 if (selection_controller)
726 selection_controller->HideAndDisallowShowingAutomatically();
729 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
730 float delta_y) {
731 if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
732 web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
735 ui::TouchSelectionController* WebContentsViewAura::GetSelectionController()
736 const {
737 RenderWidgetHostViewAura* view =
738 ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
739 return view ? view->selection_controller() : nullptr;
742 TouchSelectionControllerClientAura*
743 WebContentsViewAura::GetSelectionControllerClient() const {
744 RenderWidgetHostViewAura* view =
745 ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
746 return view ? view->selection_controller_client() : nullptr;
749 ////////////////////////////////////////////////////////////////////////////////
750 // WebContentsViewAura, WebContentsView implementation:
752 gfx::NativeView WebContentsViewAura::GetNativeView() const {
753 return window_.get();
756 gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
757 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
758 return rwhv ? rwhv->GetNativeView() : NULL;
761 gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
762 gfx::NativeWindow window = window_->GetToplevelWindow();
763 return window ? window : delegate_->GetNativeWindow();
766 void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
767 *out = window_->GetBoundsInScreen();
770 void WebContentsViewAura::SizeContents(const gfx::Size& size) {
771 gfx::Rect bounds = window_->bounds();
772 if (bounds.size() != size) {
773 bounds.set_size(size);
774 window_->SetBounds(bounds);
775 } else {
776 // Our size matches what we want but the renderers size may not match.
777 // Pretend we were resized so that the renderers size is updated too.
778 SizeChangedCommon(size);
782 void WebContentsViewAura::Focus() {
783 if (web_contents_->GetInterstitialPage()) {
784 web_contents_->GetInterstitialPage()->Focus();
785 return;
788 if (delegate_.get() && delegate_->Focus())
789 return;
791 RenderWidgetHostView* rwhv =
792 web_contents_->GetFullscreenRenderWidgetHostView();
793 if (!rwhv)
794 rwhv = web_contents_->GetRenderWidgetHostView();
795 if (rwhv)
796 rwhv->Focus();
799 void WebContentsViewAura::SetInitialFocus() {
800 if (web_contents_->FocusLocationBarByDefault())
801 web_contents_->SetFocusToLocationBar(false);
802 else
803 Focus();
806 void WebContentsViewAura::StoreFocus() {
807 if (delegate_)
808 delegate_->StoreFocus();
811 void WebContentsViewAura::RestoreFocus() {
812 if (delegate_)
813 delegate_->RestoreFocus();
816 DropData* WebContentsViewAura::GetDropData() const {
817 return current_drop_data_.get();
820 gfx::Rect WebContentsViewAura::GetViewBounds() const {
821 return window_->GetBoundsInScreen();
824 ////////////////////////////////////////////////////////////////////////////////
825 // WebContentsViewAura, WebContentsView implementation:
827 void WebContentsViewAura::CreateView(
828 const gfx::Size& initial_size, gfx::NativeView context) {
829 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
830 // if the bookmark bar is not shown and you create a new tab). The right
831 // value is set shortly after this, so its safe to ignore.
833 DCHECK(aura::Env::GetInstanceDontCreate());
834 window_.reset(new aura::Window(this));
835 window_->set_owned_by_parent(false);
836 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
837 window_->SetTransparent(false);
838 window_->Init(ui::LAYER_NOT_DRAWN);
839 window_->AddObserver(this);
840 aura::Window* root_window = context ? context->GetRootWindow() : NULL;
841 if (root_window) {
842 // There are places where there is no context currently because object
843 // hierarchies are built before they're attached to a Widget. (See
844 // views::WebView as an example; GetWidget() returns NULL at the point
845 // where we are created.)
847 // It should be OK to not set a default parent since such users will
848 // explicitly add this WebContentsViewAura to their tree after they create
849 // us.
850 if (root_window) {
851 aura::client::ParentWindowWithContext(
852 window_.get(), root_window, root_window->GetBoundsInScreen());
855 window_->layer()->SetMasksToBounds(true);
856 window_->SetName("WebContentsViewAura");
858 // WindowObserver is not interesting and is problematic for Browser Plugin
859 // guests.
860 // The use cases for WindowObserver do not apply to Browser Plugins:
861 // 1) guests do not support NPAPI plugins.
862 // 2) guests' window bounds are supposed to come from its embedder.
863 if (!BrowserPluginGuest::IsGuest(web_contents_))
864 window_observer_.reset(new WindowObserver(this));
866 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
867 // Hence, we save a reference to it locally. Similar model is used on other
868 // platforms as well.
869 if (delegate_)
870 drag_dest_delegate_ = delegate_->GetDragDestDelegate();
873 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
874 RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
875 if (render_widget_host->GetView()) {
876 // During testing, the view will already be set up in most cases to the
877 // test view, so we don't want to clobber it with a real one. To verify that
878 // this actually is happening (and somebody isn't accidentally creating the
879 // view twice), we check for the RVH Factory, which will be set when we're
880 // making special ones (which go along with the special views).
881 DCHECK(RenderViewHostFactory::has_factory());
882 return static_cast<RenderWidgetHostViewBase*>(
883 render_widget_host->GetView());
886 RenderWidgetHostViewAura* view =
887 new RenderWidgetHostViewAura(render_widget_host, is_guest_view_hack);
888 view->InitAsChild(NULL);
889 GetNativeView()->AddChild(view->GetNativeView());
891 RenderWidgetHostImpl* host_impl =
892 RenderWidgetHostImpl::From(render_widget_host);
894 if (!host_impl->is_hidden())
895 view->Show();
897 // We listen to drag drop events in the newly created view's window.
898 aura::client::SetDragDropDelegate(view->GetNativeView(), this);
900 if (view->overscroll_controller() &&
901 (!web_contents_->GetDelegate() ||
902 web_contents_->GetDelegate()->CanOverscrollContent())) {
903 InstallOverscrollControllerDelegate(view);
906 return view;
909 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
910 RenderWidgetHost* render_widget_host) {
911 return new RenderWidgetHostViewAura(render_widget_host, false);
914 void WebContentsViewAura::SetPageTitle(const base::string16& title) {
915 window_->SetTitle(title);
918 void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
921 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
924 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
925 RenderWidgetHostViewAura* view =
926 ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
927 if (view) {
928 view->SetOverscrollControllerEnabled(enabled);
929 if (enabled)
930 InstallOverscrollControllerDelegate(view);
933 if (!enabled) {
934 navigation_overlay_.reset();
935 } else if (!navigation_overlay_) {
936 navigation_overlay_.reset(
937 new OverscrollNavigationOverlay(web_contents_, window_.get()));
941 ////////////////////////////////////////////////////////////////////////////////
942 // WebContentsViewAura, RenderViewHostDelegateView implementation:
944 void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
945 const ContextMenuParams& params) {
946 ui::TouchSelectionController* selection_controller = GetSelectionController();
947 if (selection_controller)
948 selection_controller->HideAndDisallowShowingAutomatically();
949 if (delegate_) {
950 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
951 web_contents_->GetRenderWidgetHostView());
952 if (view)
953 view->OnShowContextMenu();
955 delegate_->ShowContextMenu(render_frame_host, params);
956 // WARNING: we may have been deleted during the call to ShowContextMenu().
960 void WebContentsViewAura::StartDragging(
961 const DropData& drop_data,
962 blink::WebDragOperationsMask operations,
963 const gfx::ImageSkia& image,
964 const gfx::Vector2d& image_offset,
965 const DragEventSourceInfo& event_info) {
966 aura::Window* root_window = GetNativeView()->GetRootWindow();
967 if (!aura::client::GetDragDropClient(root_window)) {
968 web_contents_->SystemDragEnded();
969 return;
972 ui::TouchSelectionController* selection_controller = GetSelectionController();
973 if (selection_controller)
974 selection_controller->HideAndDisallowShowingAutomatically();
975 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
976 PrepareDragData(drop_data, provider, web_contents_);
978 ui::OSExchangeData data(provider); // takes ownership of |provider|.
980 if (!image.isNull())
981 drag_utils::SetDragImageOnDataObject(image, image_offset, &data);
983 scoped_ptr<WebDragSourceAura> drag_source(
984 new WebDragSourceAura(GetNativeView(), web_contents_));
986 // We need to enable recursive tasks on the message loop so we can get
987 // updates while in the system DoDragDrop loop.
988 int result_op = 0;
990 gfx::NativeView content_native_view = GetContentNativeView();
991 base::MessageLoop::ScopedNestableTaskAllower allow(
992 base::MessageLoop::current());
993 result_op = aura::client::GetDragDropClient(root_window)
994 ->StartDragAndDrop(data,
995 root_window,
996 content_native_view,
997 event_info.event_location,
998 ConvertFromWeb(operations),
999 event_info.event_source);
1002 // Bail out immediately if the contents view window is gone. Note that it is
1003 // not safe to access any class members in this case since |this| may already
1004 // be destroyed. The local variable |drag_source| will still be valid though,
1005 // so we can use it to determine if the window is gone.
1006 if (!drag_source->window()) {
1007 // Note that in this case, we don't need to call SystemDragEnded() since the
1008 // renderer is going away.
1009 return;
1012 EndDrag(ConvertToWeb(result_op));
1013 web_contents_->SystemDragEnded();
1016 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
1017 current_drag_op_ = operation;
1020 void WebContentsViewAura::GotFocus() {
1021 web_contents_->NotifyWebContentsFocused();
1024 void WebContentsViewAura::TakeFocus(bool reverse) {
1025 if (web_contents_->GetDelegate() &&
1026 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1027 delegate_.get()) {
1028 delegate_->TakeFocus(reverse);
1032 void WebContentsViewAura::ShowDisambiguationPopup(
1033 const gfx::Rect& target_rect,
1034 const SkBitmap& zoomed_bitmap,
1035 const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
1036 const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
1037 if (delegate_) {
1038 delegate_->ShowDisambiguationPopup(target_rect, zoomed_bitmap,
1039 window_.get(), gesture_cb, mouse_cb);
1043 void WebContentsViewAura::HideDisambiguationPopup() {
1044 if (delegate_)
1045 delegate_->HideDisambiguationPopup();
1048 ////////////////////////////////////////////////////////////////////////////////
1049 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1051 gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
1052 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1053 if (!rwhv || !rwhv->IsShowing())
1054 return gfx::Rect();
1056 return rwhv->GetViewBounds();
1059 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1060 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1061 return false;
1063 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
1064 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
1065 OverscrollUpdateForWebContentsDelegate(delta_y);
1066 return delta_y != 0;
1068 return navigation_overlay_->relay_delegate()->OnOverscrollUpdate(delta_x,
1069 delta_y);
1072 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1073 if (web_contents_->GetDelegate() &&
1074 IsScrollEndEffectEnabled() &&
1075 (mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
1076 web_contents_->GetDelegate()->OverscrollComplete();
1078 CompleteOverscrollNavigation(mode);
1081 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1082 OverscrollMode new_mode) {
1083 if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
1084 OverscrollUpdateForWebContentsDelegate(0);
1086 current_overscroll_gesture_ = new_mode;
1087 navigation_overlay_->relay_delegate()->OnOverscrollModeChange(old_mode,
1088 new_mode);
1089 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1092 ////////////////////////////////////////////////////////////////////////////////
1093 // WebContentsViewAura, aura::WindowDelegate implementation:
1095 gfx::Size WebContentsViewAura::GetMinimumSize() const {
1096 return gfx::Size();
1099 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1100 return gfx::Size();
1103 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1104 const gfx::Rect& new_bounds) {
1105 SizeChangedCommon(new_bounds.size());
1106 if (delegate_)
1107 delegate_->SizeChanged(new_bounds.size());
1109 // Constrained web dialogs, need to be kept centered over our content area.
1110 for (size_t i = 0; i < window_->children().size(); i++) {
1111 if (window_->children()[i]->GetProperty(
1112 aura::client::kConstrainedWindowKey)) {
1113 gfx::Rect bounds = window_->children()[i]->bounds();
1114 bounds.set_origin(
1115 gfx::Point((new_bounds.width() - bounds.width()) / 2,
1116 (new_bounds.height() - bounds.height()) / 2));
1117 window_->children()[i]->SetBounds(bounds);
1122 gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1123 return gfx::kNullCursor;
1126 int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1127 return HTCLIENT;
1130 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1131 aura::Window* child,
1132 const gfx::Point& location) {
1133 return true;
1136 bool WebContentsViewAura::CanFocus() {
1137 // Do not take the focus if the render widget host view aura is gone or
1138 // is in the process of shutting down because neither the view window nor
1139 // this window can handle key events.
1140 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
1141 web_contents_->GetRenderWidgetHostView());
1142 if (view != NULL && !view->IsClosing())
1143 return true;
1145 return false;
1148 void WebContentsViewAura::OnCaptureLost() {
1151 void WebContentsViewAura::OnPaint(const ui::PaintContext& context) {
1154 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1155 float device_scale_factor) {
1158 void WebContentsViewAura::OnWindowDestroying(aura::Window* window) {
1159 // This means the destructor is going to be called soon. If there is an
1160 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1161 // then destroying it in the WebContentsViewAura destructor can trigger other
1162 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1163 // destroy the overscroll window here.
1164 navigation_overlay_.reset();
1167 void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) {
1170 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1173 bool WebContentsViewAura::HasHitTestMask() const {
1174 return false;
1177 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1180 ////////////////////////////////////////////////////////////////////////////////
1181 // WebContentsViewAura, ui::EventHandler implementation:
1183 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1186 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1187 if (!web_contents_->GetDelegate())
1188 return;
1190 switch (event->type()) {
1191 case ui::ET_MOUSE_PRESSED:
1192 web_contents_->GetDelegate()->ActivateContents(web_contents_);
1193 break;
1194 case ui::ET_MOUSE_MOVED:
1195 case ui::ET_MOUSE_EXITED:
1196 web_contents_->GetDelegate()->ContentsMouseEvent(
1197 web_contents_,
1198 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1199 event->type() == ui::ET_MOUSE_MOVED);
1200 break;
1201 default:
1202 break;
1206 ////////////////////////////////////////////////////////////////////////////////
1207 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1209 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1210 current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1211 current_drop_data_.reset(new DropData());
1213 PrepareDropData(current_drop_data_.get(), event.data());
1214 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1216 // Give the delegate an opportunity to cancel the drag.
1217 if (web_contents_->GetDelegate() &&
1218 !web_contents_->GetDelegate()->CanDragEnter(
1219 web_contents_, *current_drop_data_.get(), op)) {
1220 current_drop_data_.reset(NULL);
1221 return;
1224 if (drag_dest_delegate_)
1225 drag_dest_delegate_->DragInitialize(web_contents_);
1227 gfx::Point screen_pt =
1228 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1229 web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1230 *current_drop_data_.get(), event.location(), screen_pt, op,
1231 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1233 if (drag_dest_delegate_) {
1234 drag_dest_delegate_->OnReceiveDragData(event.data());
1235 drag_dest_delegate_->OnDragEnter();
1239 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1240 DCHECK(current_rvh_for_drag_);
1241 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1242 OnDragEntered(event);
1244 if (!current_drop_data_)
1245 return ui::DragDropTypes::DRAG_NONE;
1247 blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1248 gfx::Point screen_pt =
1249 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1250 web_contents_->GetRenderViewHost()->DragTargetDragOver(
1251 event.location(), screen_pt, op,
1252 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1254 if (drag_dest_delegate_)
1255 drag_dest_delegate_->OnDragOver();
1257 return ConvertFromWeb(current_drag_op_);
1260 void WebContentsViewAura::OnDragExited() {
1261 DCHECK(current_rvh_for_drag_);
1262 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1263 return;
1265 if (!current_drop_data_)
1266 return;
1268 web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1269 if (drag_dest_delegate_)
1270 drag_dest_delegate_->OnDragLeave();
1272 current_drop_data_.reset();
1275 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1276 DCHECK(current_rvh_for_drag_);
1277 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1278 OnDragEntered(event);
1280 if (!current_drop_data_)
1281 return ui::DragDropTypes::DRAG_NONE;
1283 web_contents_->GetRenderViewHost()->DragTargetDrop(
1284 event.location(),
1285 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1286 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1287 if (drag_dest_delegate_)
1288 drag_dest_delegate_->OnDrop();
1289 current_drop_data_.reset();
1290 return ConvertFromWeb(current_drag_op_);
1293 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
1294 bool visible) {
1295 // Ignore any visibility changes in the hierarchy below.
1296 if (window != window_.get() && window_->Contains(window))
1297 return;
1299 UpdateWebContentsVisibility(visible);
1302 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible) {
1303 if (!is_or_was_visible_) {
1304 // We should not hide the web contents before it was shown the first time,
1305 // since resources would immediately be destroyed and only re-created after
1306 // content got loaded. In this state the window content is undefined and can
1307 // show garbage.
1308 // However - the page load mechanism requires an activation call through a
1309 // visibility call to (re)load.
1310 if (visible) {
1311 is_or_was_visible_ = true;
1312 web_contents_->WasShown();
1314 return;
1316 if (visible) {
1317 if (!web_contents_->should_normally_be_visible())
1318 web_contents_->WasShown();
1319 } else {
1320 if (web_contents_->should_normally_be_visible())
1321 web_contents_->WasHidden();
1325 } // namespace content