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