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