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