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