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