Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / web_contents / web_contents_view_aura.cc
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.
4
5 #include "content/browser/web_contents/web_contents_view_aura.h"
6
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/native_widget_types.h"
71 #include "ui/gfx/screen.h"
72 #include "ui/wm/public/drag_drop_client.h"
73 #include "ui/wm/public/drag_drop_delegate.h"
74
75 #if defined(OS_WIN)
76 #include "content/browser/accessibility/browser_accessibility_manager.h"
77 #include "content/browser/accessibility/browser_accessibility_win.h"
78 #include "ui/base/win/hidden_window.h"
79 #endif
80
81 namespace content {
82 WebContentsView* CreateWebContentsView(
83     WebContentsImpl* web_contents,
84     WebContentsViewDelegate* delegate,
85     RenderViewHostDelegateView** render_view_host_delegate_view) {
86   WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
87   *render_view_host_delegate_view = rv;
88   return rv;
89 }
90
91 namespace {
92
93 bool IsScrollEndEffectEnabled() {
94   return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
95       switches::kScrollEndEffect) == "1";
96 }
97
98 bool ShouldNavigateForward(const NavigationController& controller,
99                            OverscrollMode mode) {
100   return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
101          controller.CanGoForward();
102 }
103
104 bool ShouldNavigateBack(const NavigationController& controller,
105                         OverscrollMode mode) {
106   return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
107          controller.CanGoBack();
108 }
109
110 RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
111     RenderWidgetHostView* view) {
112   if (!view || RenderViewHostFactory::has_factory())
113     return NULL;  // Can't cast to RenderWidgetHostViewAura in unit tests.
114
115   RenderViewHost* rvh = RenderViewHost::From(view->GetRenderWidgetHost());
116   WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
117       rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
118   if (BrowserPluginGuest::IsGuest(web_contents))
119     return NULL;
120   return static_cast<RenderWidgetHostViewAura*>(view);
121 }
122
123 // The window delegate for the overscroll window. This redirects trackpad events
124 // to the web-contents window. The delegate destroys itself when the window is
125 // destroyed.
126 class OverscrollWindowDelegate : public ImageWindowDelegate {
127  public:
128   OverscrollWindowDelegate(WebContentsImpl* web_contents,
129                            OverscrollMode overscroll_mode)
130       : web_contents_(web_contents),
131         forward_events_(true) {
132     const NavigationControllerImpl& controller = web_contents->GetController();
133     const NavigationEntryImpl* entry = NULL;
134     if (ShouldNavigateForward(controller, overscroll_mode)) {
135       entry = NavigationEntryImpl::FromNavigationEntry(
136           controller.GetEntryAtOffset(1));
137     } else if (ShouldNavigateBack(controller, overscroll_mode)) {
138       entry = NavigationEntryImpl::FromNavigationEntry(
139           controller.GetEntryAtOffset(-1));
140     }
141
142     gfx::Image image;
143     if (entry && entry->screenshot().get()) {
144       std::vector<gfx::ImagePNGRep> image_reps;
145       image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
146       image = gfx::Image(image_reps);
147     }
148     SetImage(image);
149   }
150
151   void stop_forwarding_events() { forward_events_ = false; }
152
153  private:
154   ~OverscrollWindowDelegate() override {}
155
156   aura::Window* web_contents_window() {
157     return web_contents_->GetView()->GetContentNativeView();
158   }
159
160   // Overridden from ui::EventHandler.
161   void OnScrollEvent(ui::ScrollEvent* event) override {
162     if (forward_events_ && web_contents_window())
163       web_contents_window()->delegate()->OnScrollEvent(event);
164   }
165
166   void OnGestureEvent(ui::GestureEvent* event) override {
167     if (forward_events_ && web_contents_window())
168       web_contents_window()->delegate()->OnGestureEvent(event);
169   }
170
171   WebContentsImpl* web_contents_;
172
173   // The window is displayed both during the gesture, and after the gesture
174   // while the navigation is in progress. During the gesture, it is necessary to
175   // forward input events to the content page (e.g. when the overscroll window
176   // slides under the cursor and starts receiving scroll events). However, once
177   // the gesture is complete, and the window is being displayed as an overlay
178   // window during navigation, events should not be forwarded anymore.
179   bool forward_events_;
180
181   DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
182 };
183
184 // Listens to all mouse drag events during a drag and drop and sends them to
185 // the renderer.
186 class WebDragSourceAura : public NotificationObserver {
187  public:
188   WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
189       : window_(window),
190         contents_(contents) {
191     registrar_.Add(this,
192                    NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
193                    Source<WebContents>(contents));
194   }
195
196   ~WebDragSourceAura() override {}
197
198   // NotificationObserver:
199   void Observe(int type,
200                const NotificationSource& source,
201                const NotificationDetails& details) override {
202     if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
203       return;
204
205     // Cancel the drag if it is still in progress.
206     aura::client::DragDropClient* dnd_client =
207         aura::client::GetDragDropClient(window_->GetRootWindow());
208     if (dnd_client && dnd_client->IsDragDropInProgress())
209       dnd_client->DragCancel();
210
211     window_ = NULL;
212     contents_ = NULL;
213   }
214
215   aura::Window* window() const { return window_; }
216
217  private:
218   aura::Window* window_;
219   WebContentsImpl* contents_;
220   NotificationRegistrar registrar_;
221
222   DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
223 };
224
225 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
226 // Fill out the OSExchangeData with a file contents, synthesizing a name if
227 // necessary.
228 void PrepareDragForFileContents(const DropData& drop_data,
229                                 ui::OSExchangeData::Provider* provider) {
230   base::FilePath file_name =
231       base::FilePath::FromUTF16Unsafe(drop_data.file_description_filename);
232   // Images without ALT text will only have a file extension so we need to
233   // synthesize one from the provided extension and URL.
234   if (file_name.BaseName().RemoveExtension().empty()) {
235     const base::FilePath::StringType extension = file_name.Extension();
236     // Retrieve the name from the URL.
237     file_name = net::GenerateFileName(drop_data.url, "", "", "", "", "")
238                     .ReplaceExtension(extension);
239   }
240   provider->SetFileContents(file_name, drop_data.file_contents);
241 }
242 #endif
243
244 #if defined(OS_WIN)
245 void PrepareDragForDownload(
246     const DropData& drop_data,
247     ui::OSExchangeData::Provider* provider,
248     WebContentsImpl* web_contents) {
249   const GURL& page_url = web_contents->GetLastCommittedURL();
250   const std::string& page_encoding = web_contents->GetEncoding();
251
252   // Parse the download metadata.
253   base::string16 mime_type;
254   base::FilePath file_name;
255   GURL download_url;
256   if (!ParseDownloadMetadata(drop_data.download_metadata,
257                              &mime_type,
258                              &file_name,
259                              &download_url))
260     return;
261
262   // Generate the file name based on both mime type and proposed file name.
263   std::string default_name =
264       GetContentClient()->browser()->GetDefaultDownloadName();
265   base::FilePath generated_download_file_name =
266       net::GenerateFileName(download_url,
267                             std::string(),
268                             std::string(),
269                             base::UTF16ToUTF8(file_name.value()),
270                             base::UTF16ToUTF8(mime_type),
271                             default_name);
272
273   // http://crbug.com/332579
274   base::ThreadRestrictions::ScopedAllowIO allow_file_operations;
275
276   base::FilePath temp_dir_path;
277   if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
278                                     &temp_dir_path))
279     return;
280
281   base::FilePath download_path =
282       temp_dir_path.Append(generated_download_file_name);
283
284   // We cannot know when the target application will be done using the temporary
285   // file, so schedule it to be deleted after rebooting.
286   base::DeleteFileAfterReboot(download_path);
287   base::DeleteFileAfterReboot(temp_dir_path);
288
289   // Provide the data as file (CF_HDROP). A temporary download file with the
290   // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
291   scoped_refptr<DragDownloadFile> download_file =
292       new DragDownloadFile(
293           download_path,
294           base::File(),
295           download_url,
296           Referrer(page_url, drop_data.referrer_policy),
297           page_encoding,
298           web_contents);
299   ui::OSExchangeData::DownloadFileInfo file_download(base::FilePath(),
300                                                      download_file.get());
301   provider->SetDownloadFileInfo(file_download);
302 }
303 #endif  // defined(OS_WIN)
304
305 // Returns the CustomFormat to store file system files.
306 const ui::OSExchangeData::CustomFormat& GetFileSystemFileCustomFormat() {
307   static const char kFormatString[] = "chromium/x-file-system-files";
308   CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat,
309                          format,
310                          (ui::Clipboard::GetFormatType(kFormatString)));
311   return format;
312 }
313
314 // Writes file system files to the pickle.
315 void WriteFileSystemFilesToPickle(
316     const std::vector<DropData::FileSystemFileInfo>& file_system_files,
317     Pickle* pickle) {
318   pickle->WriteSizeT(file_system_files.size());
319   for (size_t i = 0; i < file_system_files.size(); ++i) {
320     pickle->WriteString(file_system_files[i].url.spec());
321     pickle->WriteInt64(file_system_files[i].size);
322   }
323 }
324
325 // Reads file system files from the pickle.
326 bool ReadFileSystemFilesFromPickle(
327     const Pickle& pickle,
328     std::vector<DropData::FileSystemFileInfo>* file_system_files) {
329   PickleIterator iter(pickle);
330
331   size_t num_files = 0;
332   if (!pickle.ReadSizeT(&iter, &num_files))
333     return false;
334   file_system_files->resize(num_files);
335
336   for (size_t i = 0; i < num_files; ++i) {
337     std::string url_string;
338     int64 size = 0;
339     if (!pickle.ReadString(&iter, &url_string) ||
340         !pickle.ReadInt64(&iter, &size))
341       return false;
342
343     GURL url(url_string);
344     if (!url.is_valid())
345       return false;
346
347     (*file_system_files)[i].url = url;
348     (*file_system_files)[i].size = size;
349   }
350   return true;
351 }
352
353 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
354 void PrepareDragData(const DropData& drop_data,
355                      ui::OSExchangeData::Provider* provider,
356                      WebContentsImpl* web_contents) {
357   provider->MarkOriginatedFromRenderer();
358 #if defined(OS_WIN)
359   // Put download before file contents to prefer the download of a image over
360   // its thumbnail link.
361   if (!drop_data.download_metadata.empty())
362     PrepareDragForDownload(drop_data, provider, web_contents);
363 #endif
364 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
365   // We set the file contents before the URL because the URL also sets file
366   // contents (to a .URL shortcut).  We want to prefer file content data over
367   // a shortcut so we add it first.
368   if (!drop_data.file_contents.empty())
369     PrepareDragForFileContents(drop_data, provider);
370 #endif
371   // Call SetString() before SetURL() when we actually have a custom string.
372   // SetURL() will itself do SetString() when a string hasn't been set yet,
373   // but we want to prefer drop_data.text.string() over the URL string if it
374   // exists.
375   if (!drop_data.text.string().empty())
376     provider->SetString(drop_data.text.string());
377   if (drop_data.url.is_valid())
378     provider->SetURL(drop_data.url, drop_data.url_title);
379   if (!drop_data.html.string().empty())
380     provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
381   if (!drop_data.filenames.empty())
382     provider->SetFilenames(drop_data.filenames);
383   if (!drop_data.file_system_files.empty()) {
384     Pickle pickle;
385     WriteFileSystemFilesToPickle(drop_data.file_system_files, &pickle);
386     provider->SetPickledData(GetFileSystemFileCustomFormat(), pickle);
387   }
388   if (!drop_data.custom_data.empty()) {
389     Pickle pickle;
390     ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
391     provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
392                              pickle);
393   }
394 }
395
396 // Utility to fill a DropData object from ui::OSExchangeData.
397 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
398   drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
399
400   base::string16 plain_text;
401   data.GetString(&plain_text);
402   if (!plain_text.empty())
403     drop_data->text = base::NullableString16(plain_text, false);
404
405   GURL url;
406   base::string16 url_title;
407   data.GetURLAndTitle(
408       ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES, &url, &url_title);
409   if (url.is_valid()) {
410     drop_data->url = url;
411     drop_data->url_title = url_title;
412   }
413
414   base::string16 html;
415   GURL html_base_url;
416   data.GetHtml(&html, &html_base_url);
417   if (!html.empty())
418     drop_data->html = base::NullableString16(html, false);
419   if (html_base_url.is_valid())
420     drop_data->html_base_url = html_base_url;
421
422   data.GetFilenames(&drop_data->filenames);
423
424   Pickle pickle;
425   std::vector<DropData::FileSystemFileInfo> file_system_files;
426   if (data.GetPickledData(GetFileSystemFileCustomFormat(), &pickle) &&
427       ReadFileSystemFilesFromPickle(pickle, &file_system_files))
428     drop_data->file_system_files = file_system_files;
429
430   if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
431     ui::ReadCustomDataIntoMap(
432         pickle.data(), pickle.size(), &drop_data->custom_data);
433 }
434
435 // Utilities to convert between blink::WebDragOperationsMask and
436 // ui::DragDropTypes.
437 int ConvertFromWeb(blink::WebDragOperationsMask ops) {
438   int drag_op = ui::DragDropTypes::DRAG_NONE;
439   if (ops & blink::WebDragOperationCopy)
440     drag_op |= ui::DragDropTypes::DRAG_COPY;
441   if (ops & blink::WebDragOperationMove)
442     drag_op |= ui::DragDropTypes::DRAG_MOVE;
443   if (ops & blink::WebDragOperationLink)
444     drag_op |= ui::DragDropTypes::DRAG_LINK;
445   return drag_op;
446 }
447
448 blink::WebDragOperationsMask ConvertToWeb(int drag_op) {
449   int web_drag_op = blink::WebDragOperationNone;
450   if (drag_op & ui::DragDropTypes::DRAG_COPY)
451     web_drag_op |= blink::WebDragOperationCopy;
452   if (drag_op & ui::DragDropTypes::DRAG_MOVE)
453     web_drag_op |= blink::WebDragOperationMove;
454   if (drag_op & ui::DragDropTypes::DRAG_LINK)
455     web_drag_op |= blink::WebDragOperationLink;
456   return (blink::WebDragOperationsMask) web_drag_op;
457 }
458
459 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
460   int web_input_event_modifiers = 0;
461   if (aura_event_flags & ui::EF_SHIFT_DOWN)
462     web_input_event_modifiers |= blink::WebInputEvent::ShiftKey;
463   if (aura_event_flags & ui::EF_CONTROL_DOWN)
464     web_input_event_modifiers |= blink::WebInputEvent::ControlKey;
465   if (aura_event_flags & ui::EF_ALT_DOWN)
466     web_input_event_modifiers |= blink::WebInputEvent::AltKey;
467   if (aura_event_flags & ui::EF_COMMAND_DOWN)
468     web_input_event_modifiers |= blink::WebInputEvent::MetaKey;
469   return web_input_event_modifiers;
470 }
471
472 }  // namespace
473
474 class WebContentsViewAura::WindowObserver
475     : public aura::WindowObserver, public aura::WindowTreeHostObserver {
476  public:
477   explicit WindowObserver(WebContentsViewAura* view)
478       : view_(view),
479         host_window_(NULL) {
480     view_->window_->AddObserver(this);
481
482 #if defined(OS_WIN)
483     if (view_->window_->GetRootWindow())
484       view_->window_->GetRootWindow()->AddObserver(this);
485 #endif
486   }
487
488   ~WindowObserver() override {
489     view_->window_->RemoveObserver(this);
490     if (view_->window_->GetHost())
491       view_->window_->GetHost()->RemoveObserver(this);
492     if (host_window_)
493       host_window_->RemoveObserver(this);
494 #if defined(OS_WIN)
495     if (host_window_) {
496       const aura::Window::Windows& children = host_window_->children();
497       for (size_t i = 0; i < children.size(); ++i)
498         children[i]->RemoveObserver(this);
499     }
500
501     aura::Window* root_window = view_->window_->GetRootWindow();
502     if (root_window) {
503       root_window->RemoveObserver(this);
504       const aura::Window::Windows& root_children = root_window->children();
505       for (size_t i = 0; i < root_children.size(); ++i)
506         root_children[i]->RemoveObserver(this);
507     }
508 #endif
509   }
510
511   // Overridden from aura::WindowObserver:
512   void OnWindowHierarchyChanged(
513       const aura::WindowObserver::HierarchyChangeParams& params) override {
514     if (params.receiver != view_->window_.get() ||
515         !params.target->Contains(view_->window_.get())) {
516       return;
517     }
518
519     // Use the new parent's root window for calculating HiDPI subpixel offset.
520     RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
521         view_->web_contents_->GetRenderWidgetHostView());
522     if (rwhv)
523       rwhv->SnapToPhysicalPixelBoundary();
524   }
525
526 #if defined(OS_WIN)
527   // Constrained windows are added as children of the parent's parent's view
528   // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
529   // so that it can update the plugins' cutout rects accordingly.
530   // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
531   // going to be deprecated in a year, this is ok for now. The test for this is
532   // PrintPreviewTest.WindowedNPAPIPluginHidden.
533   virtual void OnWindowAdded(aura::Window* new_window) override {
534     if (!new_window->Contains(view_->window_.get())) {
535       // Skip the case when the parent moves to the root window.
536       if (new_window != host_window_) {
537         // Observe sibling windows of the WebContents, or children of the root
538         // window.
539         if (new_window->parent() == host_window_ ||
540             new_window->parent() == view_->window_->GetRootWindow()) {
541           new_window->AddObserver(this);
542         }
543       }
544     }
545
546     if (new_window->parent() == host_window_) {
547       UpdateConstrainedWindows(NULL);
548     }
549   }
550
551   virtual void OnWillRemoveWindow(aura::Window* window) override {
552     if (window == view_->window_)
553       return;
554
555     window->RemoveObserver(this);
556     UpdateConstrainedWindows(window);
557   }
558
559   virtual void OnWindowVisibilityChanged(aura::Window* window,
560                                          bool visible) override {
561     if (window == view_->window_ ||
562         window->parent() == host_window_ ||
563         window->parent() == view_->window_->GetRootWindow()) {
564       UpdateConstrainedWindows(NULL);
565     }
566   }
567 #endif
568
569   void OnWindowParentChanged(aura::Window* window,
570                              aura::Window* parent) override {
571     if (window != view_->window_)
572       return;
573
574     aura::Window* host_window =
575         window->GetProperty(aura::client::kHostWindowKey);
576     if (!host_window)
577       host_window = parent;
578
579     if (host_window_)
580       host_window_->RemoveObserver(this);
581
582 #if defined(OS_WIN)
583     if (host_window_) {
584       const aura::Window::Windows& children = host_window_->children();
585       for (size_t i = 0; i < children.size(); ++i)
586         children[i]->RemoveObserver(this);
587       RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
588           view_->web_contents_->GetRenderWidgetHostView());
589       if (rwhv)
590         rwhv->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
591     }
592
593     // When we get parented to the root window, the code below will watch the
594     // host window, aka root window. Since we already watch the root window on
595     // Windows, unregister first so that the debug check doesn't fire.
596     if (host_window && host_window == window->GetRootWindow())
597       host_window->RemoveObserver(this);
598
599     // We need to undo the above if we were parented to the root window and then
600     // got parented to another window. At that point, the code before the ifdef
601     // would have stopped watching the root window.
602     if (window->GetRootWindow() &&
603         host_window != window->GetRootWindow() &&
604         !window->GetRootWindow()->HasObserver(this)) {
605       window->GetRootWindow()->AddObserver(this);
606     }
607 #endif
608
609     host_window_ = host_window;
610     if (host_window) {
611       host_window->AddObserver(this);
612 #if defined(OS_WIN)
613       if (host_window != window->GetRootWindow()) {
614         const aura::Window::Windows& children = host_window->children();
615         for (size_t i = 0; i < children.size(); ++i) {
616           if (!children[i]->Contains(view_->window_.get()))
617             children[i]->AddObserver(this);
618         }
619       }
620 #endif
621     }
622   }
623
624   void OnWindowBoundsChanged(aura::Window* window,
625                              const gfx::Rect& old_bounds,
626                              const gfx::Rect& new_bounds) override {
627     if (window == host_window_ || window == view_->window_) {
628       SendScreenRects();
629       if (view_->touch_editable_)
630         view_->touch_editable_->UpdateEditingController();
631 #if defined(OS_WIN)
632     } else {
633       UpdateConstrainedWindows(NULL);
634 #endif
635     }
636   }
637
638   void OnWindowDestroying(aura::Window* window) override {
639     if (window == host_window_) {
640       host_window_->RemoveObserver(this);
641       host_window_ = NULL;
642     }
643   }
644
645   void OnWindowAddedToRootWindow(aura::Window* window) override {
646     if (window == view_->window_) {
647       window->GetHost()->AddObserver(this);
648 #if defined(OS_WIN)
649       if (!window->GetRootWindow()->HasObserver(this))
650         window->GetRootWindow()->AddObserver(this);
651       if (view_->legacy_hwnd_) {
652         view_->legacy_hwnd_->UpdateParent(
653             window->GetHost()->GetAcceleratedWidget());
654       }
655 #endif
656     }
657   }
658
659   void OnWindowRemovingFromRootWindow(aura::Window* window,
660                                       aura::Window* new_root) override {
661     if (window == view_->window_) {
662       window->GetHost()->RemoveObserver(this);
663 #if defined(OS_WIN)
664       window->GetRootWindow()->RemoveObserver(this);
665
666       const aura::Window::Windows& root_children =
667           window->GetRootWindow()->children();
668       for (size_t i = 0; i < root_children.size(); ++i) {
669         if (root_children[i] != view_->window_ &&
670             root_children[i] != host_window_) {
671           root_children[i]->RemoveObserver(this);
672         }
673       }
674
675       if (view_->legacy_hwnd_)
676         view_->legacy_hwnd_->UpdateParent(ui::GetHiddenWindow());
677 #endif
678     }
679   }
680
681   // Overridden WindowTreeHostObserver:
682   void OnHostMoved(const aura::WindowTreeHost* host,
683                    const gfx::Point& new_origin) override {
684     TRACE_EVENT1("ui",
685                  "WebContentsViewAura::WindowObserver::OnHostMoved",
686                  "new_origin", new_origin.ToString());
687
688     // This is for the desktop case (i.e. Aura desktop).
689     SendScreenRects();
690   }
691
692  private:
693   void SendScreenRects() {
694     RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
695         SendScreenRects();
696   }
697
698 #if defined(OS_WIN)
699   void UpdateConstrainedWindows(aura::Window* exclude) {
700     RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
701         view_->web_contents_->GetRenderWidgetHostView());
702     if (!view)
703       return;
704
705     std::vector<gfx::Rect> constrained_windows;
706     if (host_window_) {
707       const aura::Window::Windows& children = host_window_->children();
708       for (size_t i = 0; i < children.size(); ++i) {
709         if (!children[i]->Contains(view_->window_.get()) &&
710             children[i] != exclude &&
711             children[i]->IsVisible()) {
712           constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
713         }
714       }
715     }
716
717     aura::Window* root_window = view_->window_->GetRootWindow();
718     const aura::Window::Windows& root_children = root_window->children();
719     if (root_window) {
720       for (size_t i = 0; i < root_children.size(); ++i) {
721         if (root_children[i]->IsVisible() &&
722             !root_children[i]->Contains(view_->window_.get())) {
723           constrained_windows.push_back(
724               root_children[i]->GetBoundsInRootWindow());
725         }
726       }
727     }
728
729     view->UpdateConstrainedWindowRects(constrained_windows);
730   }
731 #endif
732
733   WebContentsViewAura* view_;
734
735   // The parent window that hosts the constrained windows. We cache the old host
736   // view so that we can unregister when it's not the parent anymore.
737   aura::Window* host_window_;
738
739   DISALLOW_COPY_AND_ASSIGN(WindowObserver);
740 };
741
742 ////////////////////////////////////////////////////////////////////////////////
743 // WebContentsViewAura, public:
744
745 WebContentsViewAura::WebContentsViewAura(
746     WebContentsImpl* web_contents,
747     WebContentsViewDelegate* delegate)
748     : web_contents_(web_contents),
749       delegate_(delegate),
750       current_drag_op_(blink::WebDragOperationNone),
751       drag_dest_delegate_(NULL),
752       current_rvh_for_drag_(NULL),
753       overscroll_change_brightness_(false),
754       current_overscroll_gesture_(OVERSCROLL_NONE),
755       completed_overscroll_gesture_(OVERSCROLL_NONE),
756       touch_editable_(TouchEditableImplAura::Create()),
757       is_or_was_visible_(false) {
758 }
759
760 ////////////////////////////////////////////////////////////////////////////////
761 // WebContentsViewAura, private:
762
763 WebContentsViewAura::~WebContentsViewAura() {
764   if (!window_)
765     return;
766
767   window_observer_.reset();
768   window_->RemoveObserver(this);
769
770   // Window needs a valid delegate during its destructor, so we explicitly
771   // delete it here.
772   window_.reset();
773 }
774
775 void WebContentsViewAura::SetTouchEditableForTest(
776     TouchEditableImplAura* touch_editable) {
777   touch_editable_.reset(touch_editable);
778   AttachTouchEditableToRenderView();
779 }
780
781 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
782   if (web_contents_->GetInterstitialPage())
783     web_contents_->GetInterstitialPage()->SetSize(size);
784   RenderWidgetHostView* rwhv =
785       web_contents_->GetRenderWidgetHostView();
786   if (rwhv)
787     rwhv->SetSize(size);
788 }
789
790 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
791   aura::Window* root_window = GetNativeView()->GetRootWindow();
792   gfx::Point screen_loc =
793       gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
794   gfx::Point client_loc = screen_loc;
795   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
796   aura::Window* window = rvh->GetView()->GetNativeView();
797   aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
798   if (!web_contents_)
799     return;
800   web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
801       screen_loc.x(), screen_loc.y(), ops);
802 }
803
804 void WebContentsViewAura::InstallOverscrollControllerDelegate(
805     RenderWidgetHostViewAura* view) {
806   const std::string value = base::CommandLine::ForCurrentProcess()->
807       GetSwitchValueASCII(switches::kOverscrollHistoryNavigation);
808   if (value == "0") {
809     navigation_overlay_.reset();
810     return;
811   }
812   if (value == "2") {
813     navigation_overlay_.reset();
814     if (!gesture_nav_simple_)
815       gesture_nav_simple_.reset(new GestureNavSimple(web_contents_));
816     view->overscroll_controller()->set_delegate(gesture_nav_simple_.get());
817     return;
818   }
819   view->overscroll_controller()->set_delegate(this);
820   if (!navigation_overlay_)
821     navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
822 }
823
824 void WebContentsViewAura::PrepareOverscrollWindow() {
825   // If there is an existing |overscroll_window_| which is in the middle of an
826   // animation, then destroying the window here causes the animation to be
827   // completed immediately, which triggers |OnImplicitAnimationsCompleted()|
828   // callback, and that tries to reset |overscroll_window_| again, causing a
829   // double-free. So use a temporary variable here.
830   if (overscroll_window_) {
831     base::AutoReset<OverscrollMode> reset_state(&current_overscroll_gesture_,
832                                                 current_overscroll_gesture_);
833     scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
834   }
835
836   OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
837       web_contents_,
838       current_overscroll_gesture_);
839   overscroll_window_.reset(new aura::Window(overscroll_delegate));
840   overscroll_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
841   overscroll_window_->SetTransparent(true);
842   overscroll_window_->Init(aura::WINDOW_LAYER_TEXTURED);
843   overscroll_window_->layer()->SetMasksToBounds(false);
844   overscroll_window_->SetName("OverscrollOverlay");
845
846   overscroll_change_brightness_ = overscroll_delegate->has_image();
847   window_->AddChild(overscroll_window_.get());
848
849   gfx::Rect bounds = gfx::Rect(window_->bounds().size());
850   if (ShouldNavigateForward(web_contents_->GetController(),
851                             current_overscroll_gesture_)) {
852     // The overlay will be sliding in from the right edge towards the left in
853     // non-RTL, or sliding in from the left edge towards the right in RTL.
854     // So position the overlay window accordingly.
855     bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
856   }
857
858   aura::Window* animate_window = GetWindowToAnimateForOverscroll();
859   if (animate_window == overscroll_window_)
860     window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
861   else
862     window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
863
864   UpdateOverscrollWindowBrightness(0.f);
865
866   overscroll_window_->SetBounds(bounds);
867   overscroll_window_->Show();
868
869   overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
870 }
871
872 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
873   StopObservingImplicitAnimations();
874   aura::Window* content = GetContentNativeView();
875   content->layer()->GetAnimator()->AbortAllAnimations();
876   content->SetTransform(gfx::Transform());
877   content->layer()->SetLayerBrightness(0.f);
878 }
879
880 void WebContentsViewAura::ResetOverscrollTransform() {
881   if (!web_contents_->GetRenderWidgetHostView())
882     return;
883   aura::Window* target = GetWindowToAnimateForOverscroll();
884   if (!target)
885     return;
886   {
887     ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
888     settings.SetPreemptionStrategy(
889         ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
890     settings.SetTweenType(gfx::Tween::EASE_OUT);
891     settings.AddObserver(this);
892     target->SetTransform(gfx::Transform());
893   }
894   {
895     ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
896     settings.SetPreemptionStrategy(
897         ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
898     settings.SetTweenType(gfx::Tween::EASE_OUT);
899     UpdateOverscrollWindowBrightness(0.f);
900   }
901 }
902
903 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
904   if (!web_contents_->GetRenderWidgetHostView())
905     return;
906
907   // Animate out the current view first. Navigate to the requested history at
908   // the end of the animation.
909   if (current_overscroll_gesture_ == OVERSCROLL_NONE)
910     return;
911
912   UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
913                             current_overscroll_gesture_, OVERSCROLL_COUNT);
914   OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
915       overscroll_window_->delegate());
916   delegate->stop_forwarding_events();
917
918   completed_overscroll_gesture_ = mode;
919   aura::Window* target = GetWindowToAnimateForOverscroll();
920   ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
921   settings.SetPreemptionStrategy(
922       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
923   settings.SetTweenType(gfx::Tween::EASE_OUT);
924   settings.AddObserver(this);
925   gfx::Transform transform;
926   int content_width =
927       web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
928   float translate_x = static_cast<float>(mode == OVERSCROLL_WEST ?
929       -content_width : content_width);
930   transform.Translate(translate_x, 0);
931   target->SetTransform(transform);
932   UpdateOverscrollWindowBrightness(translate_x);
933 }
934
935 aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
936   if (current_overscroll_gesture_ == OVERSCROLL_NONE)
937     return NULL;
938
939   return ShouldNavigateForward(web_contents_->GetController(),
940                                current_overscroll_gesture_) ?
941       overscroll_window_.get() : GetContentNativeView();
942 }
943
944 gfx::Vector2dF WebContentsViewAura::GetTranslationForOverscroll(float delta_x,
945                                                                 float delta_y) {
946   if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
947       current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
948     return gfx::Vector2dF(0, delta_y);
949   }
950   // For horizontal overscroll, scroll freely if a navigation is possible. Do a
951   // resistive scroll otherwise.
952   const NavigationControllerImpl& controller = web_contents_->GetController();
953   const gfx::Rect& bounds = GetViewBounds();
954   const float bounds_width = static_cast<float>(bounds.width());
955   if (ShouldNavigateForward(controller, current_overscroll_gesture_))
956     return gfx::Vector2dF(std::max(-bounds_width, delta_x), 0);
957   else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
958     return gfx::Vector2dF(std::min(bounds_width, delta_x), 0);
959   return gfx::Vector2dF();
960 }
961
962 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
963   OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
964       overscroll_window_->delegate());
965   overscroll_window_->SchedulePaintInRect(
966       gfx::Rect(overscroll_window_->bounds().size()));
967   overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size()));
968   overscroll_window_->SetTransform(gfx::Transform());
969   navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
970                                         delegate);
971   navigation_overlay_->StartObserving();
972 }
973
974 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
975   if (!overscroll_change_brightness_)
976     return;
977
978   const float kBrightnessMin = -.1f;
979   const float kBrightnessMax = -.01f;
980
981   float ratio = fabs(delta_x) / GetViewBounds().width();
982   ratio = std::min(1.f, ratio);
983   if (base::i18n::IsRTL())
984     ratio = 1.f - ratio;
985   float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ?
986       kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) :
987       kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin);
988   brightness = std::max(kBrightnessMin, brightness);
989   brightness = std::min(kBrightnessMax, brightness);
990   aura::Window* window = GetWindowToAnimateForOverscroll();
991   window->layer()->SetLayerBrightness(brightness);
992 }
993
994 void WebContentsViewAura::AttachTouchEditableToRenderView() {
995   if (!touch_editable_)
996     return;
997   RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
998       web_contents_->GetRenderWidgetHostView());
999   touch_editable_->AttachToView(rwhva);
1000 }
1001
1002 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
1003     float delta_y) {
1004   if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
1005     web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
1006 }
1007
1008 ////////////////////////////////////////////////////////////////////////////////
1009 // WebContentsViewAura, WebContentsView implementation:
1010
1011 gfx::NativeView WebContentsViewAura::GetNativeView() const {
1012   return window_.get();
1013 }
1014
1015 gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
1016   RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1017   return rwhv ? rwhv->GetNativeView() : NULL;
1018 }
1019
1020 gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
1021   return window_->GetToplevelWindow();
1022 }
1023
1024 void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
1025   *out = window_->GetBoundsInScreen();
1026 }
1027
1028 void WebContentsViewAura::SizeContents(const gfx::Size& size) {
1029   gfx::Rect bounds = window_->bounds();
1030   if (bounds.size() != size) {
1031     bounds.set_size(size);
1032     window_->SetBounds(bounds);
1033 #if defined(OS_WIN)
1034     if (legacy_hwnd_)
1035       legacy_hwnd_->SetBounds(window_->GetBoundsInRootWindow());
1036 #endif
1037   } else {
1038     // Our size matches what we want but the renderers size may not match.
1039     // Pretend we were resized so that the renderers size is updated too.
1040     SizeChangedCommon(size);
1041   }
1042 }
1043
1044 void WebContentsViewAura::Focus() {
1045   if (web_contents_->GetInterstitialPage()) {
1046     web_contents_->GetInterstitialPage()->Focus();
1047     return;
1048   }
1049
1050   if (delegate_.get() && delegate_->Focus())
1051     return;
1052
1053   RenderWidgetHostView* rwhv =
1054       web_contents_->GetFullscreenRenderWidgetHostView();
1055   if (!rwhv)
1056     rwhv = web_contents_->GetRenderWidgetHostView();
1057   if (rwhv)
1058     rwhv->Focus();
1059 }
1060
1061 void WebContentsViewAura::SetInitialFocus() {
1062   if (web_contents_->FocusLocationBarByDefault())
1063     web_contents_->SetFocusToLocationBar(false);
1064   else
1065     Focus();
1066 }
1067
1068 void WebContentsViewAura::StoreFocus() {
1069   if (delegate_)
1070     delegate_->StoreFocus();
1071 }
1072
1073 void WebContentsViewAura::RestoreFocus() {
1074   if (delegate_)
1075     delegate_->RestoreFocus();
1076 }
1077
1078 DropData* WebContentsViewAura::GetDropData() const {
1079   return current_drop_data_.get();
1080 }
1081
1082 gfx::Rect WebContentsViewAura::GetViewBounds() const {
1083   return window_->GetBoundsInScreen();
1084 }
1085
1086 ////////////////////////////////////////////////////////////////////////////////
1087 // WebContentsViewAura, WebContentsView implementation:
1088
1089 void WebContentsViewAura::CreateView(
1090     const gfx::Size& initial_size, gfx::NativeView context) {
1091   // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1092   // if the bookmark bar is not shown and you create a new tab). The right
1093   // value is set shortly after this, so its safe to ignore.
1094
1095   aura::Env::CreateInstance(true);
1096   window_.reset(new aura::Window(this));
1097   window_->set_owned_by_parent(false);
1098   window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
1099   window_->SetTransparent(false);
1100   window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
1101   window_->AddObserver(this);
1102   aura::Window* root_window = context ? context->GetRootWindow() : NULL;
1103   if (root_window) {
1104     // There are places where there is no context currently because object
1105     // hierarchies are built before they're attached to a Widget. (See
1106     // views::WebView as an example; GetWidget() returns NULL at the point
1107     // where we are created.)
1108     //
1109     // It should be OK to not set a default parent since such users will
1110     // explicitly add this WebContentsViewAura to their tree after they create
1111     // us.
1112     if (root_window) {
1113       aura::client::ParentWindowWithContext(
1114           window_.get(), root_window, root_window->GetBoundsInScreen());
1115     }
1116   }
1117   window_->layer()->SetMasksToBounds(true);
1118   window_->SetName("WebContentsViewAura");
1119
1120   // WindowObserver is not interesting and is problematic for Browser Plugin
1121   // guests.
1122   // The use cases for WindowObserver do not apply to Browser Plugins:
1123   // 1) guests do not support NPAPI plugins.
1124   // 2) guests' window bounds are supposed to come from its embedder.
1125   if (!BrowserPluginGuest::IsGuest(web_contents_))
1126     window_observer_.reset(new WindowObserver(this));
1127
1128   // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1129   // Hence, we save a reference to it locally. Similar model is used on other
1130   // platforms as well.
1131   if (delegate_)
1132     drag_dest_delegate_ = delegate_->GetDragDestDelegate();
1133
1134 #if defined(OS_WIN)
1135   if (context && context->GetHost()) {
1136     HWND parent_hwnd = context->GetHost()->GetAcceleratedWidget();
1137     CHECK(parent_hwnd);
1138     legacy_hwnd_.reset(LegacyRenderWidgetHostHWND::Create(parent_hwnd, this));
1139   }
1140 #endif
1141 }
1142
1143 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
1144     RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
1145   if (render_widget_host->GetView()) {
1146     // During testing, the view will already be set up in most cases to the
1147     // test view, so we don't want to clobber it with a real one. To verify that
1148     // this actually is happening (and somebody isn't accidentally creating the
1149     // view twice), we check for the RVH Factory, which will be set when we're
1150     // making special ones (which go along with the special views).
1151     DCHECK(RenderViewHostFactory::has_factory());
1152     return static_cast<RenderWidgetHostViewBase*>(
1153         render_widget_host->GetView());
1154   }
1155
1156   RenderWidgetHostViewAura* view =
1157       new RenderWidgetHostViewAura(render_widget_host, is_guest_view_hack);
1158   view->InitAsChild(NULL);
1159   GetNativeView()->AddChild(view->GetNativeView());
1160
1161   if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1162     navigation_overlay_->StartObserving();
1163   }
1164
1165   RenderWidgetHostImpl* host_impl =
1166       RenderWidgetHostImpl::From(render_widget_host);
1167
1168   if (!host_impl->is_hidden())
1169     view->Show();
1170
1171   // We listen to drag drop events in the newly created view's window.
1172   aura::client::SetDragDropDelegate(view->GetNativeView(), this);
1173
1174   if (view->overscroll_controller() &&
1175       (!web_contents_->GetDelegate() ||
1176        web_contents_->GetDelegate()->CanOverscrollContent())) {
1177     InstallOverscrollControllerDelegate(view);
1178   }
1179
1180   AttachTouchEditableToRenderView();
1181
1182 #if defined(OS_WIN)
1183   if (legacy_hwnd_)
1184     view->SetLegacyRenderWidgetHostHWND(legacy_hwnd_.get());
1185 #endif
1186
1187   return view;
1188 }
1189
1190 RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
1191     RenderWidgetHost* render_widget_host) {
1192   RenderWidgetHostViewAura* view =
1193       new RenderWidgetHostViewAura(render_widget_host, false);
1194 #if defined(OS_WIN)
1195   if (legacy_hwnd_)
1196     view->SetLegacyRenderWidgetHostHWND(legacy_hwnd_.get());
1197 #endif
1198   return view;
1199 }
1200
1201 void WebContentsViewAura::SetPageTitle(const base::string16& title) {
1202   window_->SetTitle(title);
1203 }
1204
1205 void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
1206 }
1207
1208 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
1209   if (navigation_overlay_.get() && navigation_overlay_->has_window())
1210     navigation_overlay_->StartObserving();
1211   AttachTouchEditableToRenderView();
1212 }
1213
1214 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
1215   RenderWidgetHostViewAura* view =
1216       ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
1217   if (view) {
1218     view->SetOverscrollControllerEnabled(enabled);
1219     if (enabled)
1220       InstallOverscrollControllerDelegate(view);
1221   }
1222
1223   if (!enabled)
1224     navigation_overlay_.reset();
1225   else if (!navigation_overlay_)
1226     navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1227 }
1228
1229 ////////////////////////////////////////////////////////////////////////////////
1230 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1231
1232 void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
1233                                           const ContextMenuParams& params) {
1234   if (touch_editable_) {
1235     touch_editable_->EndTouchEditing(false);
1236   }
1237   if (delegate_) {
1238     delegate_->ShowContextMenu(render_frame_host, params);
1239     // WARNING: we may have been deleted during the call to ShowContextMenu().
1240   }
1241 }
1242
1243 void WebContentsViewAura::StartDragging(
1244     const DropData& drop_data,
1245     blink::WebDragOperationsMask operations,
1246     const gfx::ImageSkia& image,
1247     const gfx::Vector2d& image_offset,
1248     const DragEventSourceInfo& event_info) {
1249   aura::Window* root_window = GetNativeView()->GetRootWindow();
1250   if (!aura::client::GetDragDropClient(root_window)) {
1251     web_contents_->SystemDragEnded();
1252     return;
1253   }
1254
1255   if (touch_editable_)
1256     touch_editable_->EndTouchEditing(false);
1257
1258   ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
1259   PrepareDragData(drop_data, provider, web_contents_);
1260
1261   ui::OSExchangeData data(provider);  // takes ownership of |provider|.
1262
1263   if (!image.isNull())
1264     drag_utils::SetDragImageOnDataObject(image, image_offset, &data);
1265
1266   scoped_ptr<WebDragSourceAura> drag_source(
1267       new WebDragSourceAura(GetNativeView(), web_contents_));
1268
1269   // We need to enable recursive tasks on the message loop so we can get
1270   // updates while in the system DoDragDrop loop.
1271   int result_op = 0;
1272   {
1273     gfx::NativeView content_native_view = GetContentNativeView();
1274     base::MessageLoop::ScopedNestableTaskAllower allow(
1275         base::MessageLoop::current());
1276     result_op = aura::client::GetDragDropClient(root_window)
1277         ->StartDragAndDrop(data,
1278                            root_window,
1279                            content_native_view,
1280                            event_info.event_location,
1281                            ConvertFromWeb(operations),
1282                            event_info.event_source);
1283   }
1284
1285   // Bail out immediately if the contents view window is gone. Note that it is
1286   // not safe to access any class members in this case since |this| may already
1287   // be destroyed. The local variable |drag_source| will still be valid though,
1288   // so we can use it to determine if the window is gone.
1289   if (!drag_source->window()) {
1290     // Note that in this case, we don't need to call SystemDragEnded() since the
1291     // renderer is going away.
1292     return;
1293   }
1294
1295   EndDrag(ConvertToWeb(result_op));
1296   web_contents_->SystemDragEnded();
1297 }
1298
1299 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
1300   current_drag_op_ = operation;
1301 }
1302
1303 void WebContentsViewAura::GotFocus() {
1304   if (web_contents_->GetDelegate())
1305     web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
1306 }
1307
1308 void WebContentsViewAura::TakeFocus(bool reverse) {
1309   if (web_contents_->GetDelegate() &&
1310       !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1311       delegate_.get()) {
1312     delegate_->TakeFocus(reverse);
1313   }
1314 }
1315
1316 void WebContentsViewAura::ShowDisambiguationPopup(
1317     const gfx::Rect& target_rect,
1318     const SkBitmap& zoomed_bitmap,
1319     const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
1320     const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
1321   if (delegate_) {
1322     delegate_->ShowDisambiguationPopup(target_rect, zoomed_bitmap,
1323         window_.get(), gesture_cb, mouse_cb);
1324   }
1325 }
1326
1327 void WebContentsViewAura::HideDisambiguationPopup() {
1328   if (delegate_)
1329     delegate_->HideDisambiguationPopup();
1330 }
1331
1332 ////////////////////////////////////////////////////////////////////////////////
1333 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1334
1335 gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
1336   RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1337   if (!rwhv || !rwhv->IsShowing())
1338     return gfx::Rect();
1339
1340   return rwhv->GetViewBounds();
1341 }
1342
1343 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1344   if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1345     return false;
1346
1347   aura::Window* target = GetWindowToAnimateForOverscroll();
1348   gfx::Vector2dF translate = GetTranslationForOverscroll(delta_x, delta_y);
1349   gfx::Transform transform;
1350
1351   if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
1352       current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
1353     OverscrollUpdateForWebContentsDelegate(translate.y());
1354   } else {
1355     // Only horizontal overscrolls participate in the navigation gesture.
1356     transform.Translate(translate.x(), translate.y());
1357     target->SetTransform(transform);
1358     UpdateOverscrollWindowBrightness(delta_x);
1359   }
1360
1361   return !translate.IsZero();
1362 }
1363
1364 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1365   UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
1366   if (web_contents_->GetDelegate() &&
1367       IsScrollEndEffectEnabled() &&
1368       (mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
1369     web_contents_->GetDelegate()->OverscrollComplete();
1370   }
1371   NavigationControllerImpl& controller = web_contents_->GetController();
1372   if (ShouldNavigateForward(controller, mode) ||
1373       ShouldNavigateBack(controller, mode)) {
1374     CompleteOverscrollNavigation(mode);
1375     return;
1376   }
1377
1378   ResetOverscrollTransform();
1379 }
1380
1381 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1382                                                  OverscrollMode new_mode) {
1383   // Reset any in-progress overscroll animation first.
1384   ResetOverscrollTransform();
1385
1386   if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
1387     OverscrollUpdateForWebContentsDelegate(0);
1388
1389   if (new_mode != OVERSCROLL_NONE && touch_editable_)
1390     touch_editable_->OverscrollStarted();
1391
1392   if (new_mode == OVERSCROLL_NONE ||
1393       !GetContentNativeView() ||
1394       ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
1395        navigation_overlay_.get() && navigation_overlay_->has_window())) {
1396     current_overscroll_gesture_ = OVERSCROLL_NONE;
1397   } else {
1398     aura::Window* target = GetWindowToAnimateForOverscroll();
1399     if (target) {
1400       StopObservingImplicitAnimations();
1401       target->layer()->GetAnimator()->AbortAllAnimations();
1402     }
1403     // Cleanup state of the content window first, because that can reset the
1404     // value of |current_overscroll_gesture_|.
1405     PrepareContentWindowForOverscroll();
1406
1407     current_overscroll_gesture_ = new_mode;
1408     if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
1409         current_overscroll_gesture_ == OVERSCROLL_WEST)
1410       PrepareOverscrollWindow();
1411
1412     UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
1413   }
1414   completed_overscroll_gesture_ = OVERSCROLL_NONE;
1415 }
1416
1417 ////////////////////////////////////////////////////////////////////////////////
1418 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1419
1420 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1421   overscroll_shadow_.reset();
1422
1423   if (ShouldNavigateForward(web_contents_->GetController(),
1424                             completed_overscroll_gesture_)) {
1425     web_contents_->GetController().GoForward();
1426     PrepareOverscrollNavigationOverlay();
1427   } else if (ShouldNavigateBack(web_contents_->GetController(),
1428                                 completed_overscroll_gesture_)) {
1429     web_contents_->GetController().GoBack();
1430     PrepareOverscrollNavigationOverlay();
1431   } else {
1432     if (touch_editable_)
1433       touch_editable_->OverscrollCompleted();
1434   }
1435
1436   aura::Window* content = GetContentNativeView();
1437   if (content) {
1438     content->SetTransform(gfx::Transform());
1439     content->layer()->SetLayerBrightness(0.f);
1440   }
1441   current_overscroll_gesture_ = OVERSCROLL_NONE;
1442   completed_overscroll_gesture_ = OVERSCROLL_NONE;
1443   overscroll_window_.reset();
1444 }
1445
1446 ////////////////////////////////////////////////////////////////////////////////
1447 // WebContentsViewAura, aura::WindowDelegate implementation:
1448
1449 gfx::Size WebContentsViewAura::GetMinimumSize() const {
1450   return gfx::Size();
1451 }
1452
1453 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1454   return gfx::Size();
1455 }
1456
1457 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1458                                           const gfx::Rect& new_bounds) {
1459   SizeChangedCommon(new_bounds.size());
1460   if (delegate_)
1461     delegate_->SizeChanged(new_bounds.size());
1462
1463   // Constrained web dialogs, need to be kept centered over our content area.
1464   for (size_t i = 0; i < window_->children().size(); i++) {
1465     if (window_->children()[i]->GetProperty(
1466             aura::client::kConstrainedWindowKey)) {
1467       gfx::Rect bounds = window_->children()[i]->bounds();
1468       bounds.set_origin(
1469           gfx::Point((new_bounds.width() - bounds.width()) / 2,
1470                      (new_bounds.height() - bounds.height()) / 2));
1471       window_->children()[i]->SetBounds(bounds);
1472     }
1473   }
1474 }
1475
1476 gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1477   return gfx::kNullCursor;
1478 }
1479
1480 int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1481   return HTCLIENT;
1482 }
1483
1484 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1485     aura::Window* child,
1486     const gfx::Point& location) {
1487   return true;
1488 }
1489
1490 bool WebContentsViewAura::CanFocus() {
1491   // Do not take the focus if the render widget host view aura is gone or
1492   // is in the process of shutting down because neither the view window nor
1493   // this window can handle key events.
1494   RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
1495       web_contents_->GetRenderWidgetHostView());
1496   if (view != NULL && !view->IsClosing())
1497     return true;
1498
1499   return false;
1500 }
1501
1502 void WebContentsViewAura::OnCaptureLost() {
1503 }
1504
1505 void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
1506 }
1507
1508 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1509     float device_scale_factor) {
1510 }
1511
1512 void WebContentsViewAura::OnWindowDestroying(aura::Window* window) {
1513   // This means the destructor is going to be called soon. If there is an
1514   // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1515   // then destroying it in the WebContentsViewAura destructor can trigger other
1516   // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1517   // destroy the overscroll window here.
1518   navigation_overlay_.reset();
1519   overscroll_window_.reset();
1520 }
1521
1522 void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) {
1523 }
1524
1525 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1526 }
1527
1528 bool WebContentsViewAura::HasHitTestMask() const {
1529   return false;
1530 }
1531
1532 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1533 }
1534
1535 ////////////////////////////////////////////////////////////////////////////////
1536 // WebContentsViewAura, ui::EventHandler implementation:
1537
1538 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1539 }
1540
1541 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1542   if (!web_contents_->GetDelegate())
1543     return;
1544
1545   switch (event->type()) {
1546     case ui::ET_MOUSE_PRESSED:
1547       web_contents_->GetDelegate()->ActivateContents(web_contents_);
1548       break;
1549     case ui::ET_MOUSE_MOVED:
1550     case ui::ET_MOUSE_EXITED:
1551       web_contents_->GetDelegate()->ContentsMouseEvent(
1552           web_contents_,
1553           gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1554           event->type() == ui::ET_MOUSE_MOVED);
1555       break;
1556     default:
1557       break;
1558   }
1559 }
1560
1561 ////////////////////////////////////////////////////////////////////////////////
1562 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1563
1564 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1565   current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1566   current_drop_data_.reset(new DropData());
1567
1568   PrepareDropData(current_drop_data_.get(), event.data());
1569   blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1570
1571   // Give the delegate an opportunity to cancel the drag.
1572   if (web_contents_->GetDelegate() &&
1573       !web_contents_->GetDelegate()->CanDragEnter(
1574           web_contents_, *current_drop_data_.get(), op)) {
1575     current_drop_data_.reset(NULL);
1576     return;
1577   }
1578
1579   if (drag_dest_delegate_)
1580     drag_dest_delegate_->DragInitialize(web_contents_);
1581
1582   gfx::Point screen_pt =
1583       gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1584   web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1585       *current_drop_data_.get(), event.location(), screen_pt, op,
1586       ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1587
1588   if (drag_dest_delegate_) {
1589     drag_dest_delegate_->OnReceiveDragData(event.data());
1590     drag_dest_delegate_->OnDragEnter();
1591   }
1592 }
1593
1594 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1595   DCHECK(current_rvh_for_drag_);
1596   if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1597     OnDragEntered(event);
1598
1599   if (!current_drop_data_)
1600     return ui::DragDropTypes::DRAG_NONE;
1601
1602   blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1603   gfx::Point screen_pt =
1604       gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1605   web_contents_->GetRenderViewHost()->DragTargetDragOver(
1606       event.location(), screen_pt, op,
1607       ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1608
1609   if (drag_dest_delegate_)
1610     drag_dest_delegate_->OnDragOver();
1611
1612   return ConvertFromWeb(current_drag_op_);
1613 }
1614
1615 void WebContentsViewAura::OnDragExited() {
1616   DCHECK(current_rvh_for_drag_);
1617   if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1618     return;
1619
1620   if (!current_drop_data_)
1621     return;
1622
1623   web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1624   if (drag_dest_delegate_)
1625     drag_dest_delegate_->OnDragLeave();
1626
1627   current_drop_data_.reset();
1628 }
1629
1630 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1631   DCHECK(current_rvh_for_drag_);
1632   if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1633     OnDragEntered(event);
1634
1635   if (!current_drop_data_)
1636     return ui::DragDropTypes::DRAG_NONE;
1637
1638   web_contents_->GetRenderViewHost()->DragTargetDrop(
1639       event.location(),
1640       gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1641       ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1642   if (drag_dest_delegate_)
1643     drag_dest_delegate_->OnDrop();
1644   current_drop_data_.reset();
1645   return ConvertFromWeb(current_drag_op_);
1646 }
1647
1648 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
1649                                                     bool visible) {
1650   // Ignore any visibility changes in the hierarchy below.
1651   if (window != window_.get() && window_->Contains(window))
1652     return;
1653
1654   UpdateWebContentsVisibility(visible);
1655 }
1656
1657 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible) {
1658   if (!is_or_was_visible_) {
1659     // We should not hide the web contents before it was shown the first time,
1660     // since resources would immediately be destroyed and only re-created after
1661     // content got loaded. In this state the window content is undefined and can
1662     // show garbage.
1663     // However - the page load mechanism requires an activation call through a
1664     // visibility call to (re)load.
1665     if (visible) {
1666       is_or_was_visible_ = true;
1667       web_contents_->WasShown();
1668     }
1669     return;
1670   }
1671   if (visible) {
1672     if (!web_contents_->should_normally_be_visible())
1673       web_contents_->WasShown();
1674   } else {
1675     if (web_contents_->should_normally_be_visible())
1676       web_contents_->WasHidden();
1677   }
1678
1679 #if defined(OS_WIN)
1680   if (!legacy_hwnd_)
1681     return;
1682
1683   if (visible && GetNativeView() && GetNativeView()->GetHost()) {
1684     legacy_hwnd_->UpdateParent(
1685         GetNativeView()->GetHost()->GetAcceleratedWidget());
1686     legacy_hwnd_->SetBounds(window_->GetBoundsInRootWindow());
1687     legacy_hwnd_->Show();
1688   } else {
1689     // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
1690     // hidden window on the same lines as Windowed plugin windows.
1691     legacy_hwnd_->UpdateParent(ui::GetHiddenWindow());
1692     legacy_hwnd_->Hide();
1693   }
1694 #endif
1695 }
1696
1697 #if defined(OS_WIN)
1698 gfx::NativeViewAccessible
1699 WebContentsViewAura::GetNativeViewAccessible() {
1700   BrowserAccessibilityManager* manager =
1701       web_contents_->GetRootBrowserAccessibilityManager();
1702   if (!manager)
1703     return nullptr;
1704
1705   return manager->GetRoot()->ToBrowserAccessibilityWin();
1706 }
1707 #endif
1708
1709 }  // namespace content