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