Home | History | Annotate | Download | only in extensions
      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 "chrome/browser/ui/views/extensions/extension_view_views.h"
      6 
      7 #include "chrome/browser/extensions/extension_host.h"
      8 #include "chrome/browser/ui/views/extensions/extension_popup.h"
      9 #include "content/public/browser/content_browser_client.h"
     10 #include "content/public/browser/render_view_host.h"
     11 #include "content/public/browser/render_widget_host_view.h"
     12 #include "content/public/browser/web_contents.h"
     13 #include "content/public/browser/web_contents_view.h"
     14 #include "extensions/common/view_type.h"
     15 #include "ui/base/events/event.h"
     16 #include "ui/views/widget/widget.h"
     17 
     18 ExtensionViewViews::ExtensionViewViews(extensions::ExtensionHost* host,
     19                                        Browser* browser)
     20     : host_(host),
     21       browser_(browser),
     22       initialized_(false),
     23       container_(NULL),
     24       is_clipped_(false) {
     25   // This view needs to be focusable so it can act as the focused view for the
     26   // focus manager. This is required to have SkipDefaultKeyEventProcessing
     27   // called so the tab key events are forwarded to the renderer.
     28   set_focusable(true);
     29 }
     30 
     31 ExtensionViewViews::~ExtensionViewViews() {
     32   if (parent())
     33     parent()->RemoveChildView(this);
     34   CleanUp();
     35 }
     36 
     37 const extensions::Extension* ExtensionViewViews::extension() const {
     38   return host_->extension();
     39 }
     40 
     41 content::RenderViewHost* ExtensionViewViews::render_view_host() const {
     42   return host_->render_view_host();
     43 }
     44 
     45 void ExtensionViewViews::DidStopLoading() {
     46   ShowIfCompletelyLoaded();
     47 }
     48 
     49 void ExtensionViewViews::SetIsClipped(bool is_clipped) {
     50   if (is_clipped_ != is_clipped) {
     51     is_clipped_ = is_clipped;
     52     if (visible())
     53       ShowIfCompletelyLoaded();
     54   }
     55 }
     56 
     57 gfx::NativeCursor ExtensionViewViews::GetCursor(const ui::MouseEvent& event) {
     58   return gfx::kNullCursor;
     59 }
     60 
     61 void ExtensionViewViews::SetVisible(bool is_visible) {
     62   if (is_visible != visible()) {
     63     NativeViewHost::SetVisible(is_visible);
     64 
     65     // Also tell RenderWidgetHostView the new visibility. Despite its name, it
     66     // is not part of the View hierarchy and does not know about the change
     67     // unless we tell it.
     68     if (render_view_host()->GetView()) {
     69       if (is_visible)
     70         render_view_host()->GetView()->Show();
     71       else
     72         render_view_host()->GetView()->Hide();
     73     }
     74   }
     75 }
     76 
     77 void ExtensionViewViews::CreateWidgetHostView() {
     78   DCHECK(!initialized_);
     79   initialized_ = true;
     80   Attach(host_->host_contents()->GetView()->GetNativeView());
     81   host_->CreateRenderViewSoon();
     82   SetVisible(false);
     83 }
     84 
     85 void ExtensionViewViews::ShowIfCompletelyLoaded() {
     86   if (visible() || is_clipped_)
     87     return;
     88 
     89   // We wait to show the ExtensionViewViews until it has loaded, and the view
     90   // has actually been created. These can happen in different orders.
     91   if (host_->did_stop_loading()) {
     92     SetVisible(true);
     93     ResizeDueToAutoResize(pending_preferred_size_);
     94   }
     95 }
     96 
     97 void ExtensionViewViews::CleanUp() {
     98   if (!initialized_)
     99     return;
    100   if (native_view())
    101     Detach();
    102   initialized_ = false;
    103 }
    104 
    105 void ExtensionViewViews::ResizeDueToAutoResize(const gfx::Size& new_size) {
    106   // Don't actually do anything with this information until we have been shown.
    107   // Size changes will not be honored by lower layers while we are hidden.
    108   if (!visible()) {
    109     pending_preferred_size_ = new_size;
    110     return;
    111   }
    112 
    113   gfx::Size preferred_size = GetPreferredSize();
    114   if (new_size != preferred_size)
    115     SetPreferredSize(new_size);
    116 }
    117 
    118 void ExtensionViewViews::ViewHierarchyChanged(
    119     const ViewHierarchyChangedDetails& details) {
    120   NativeViewHost::ViewHierarchyChanged(details);
    121   if (details.is_add && GetWidget() && !initialized_)
    122     CreateWidgetHostView();
    123 }
    124 
    125 bool ExtensionViewViews::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
    126   // Let the tab key event be processed by the renderer (instead of moving the
    127   // focus to the next focusable view). Also handle Backspace, since otherwise
    128   // (on Windows at least), pressing Backspace, when focus is on a text field
    129   // within the ExtensionViewViews, will navigate the page back instead of
    130   // erasing a character.
    131   return (e.key_code() == ui::VKEY_TAB || e.key_code() == ui::VKEY_BACK);
    132 }
    133 
    134 void ExtensionViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
    135   // Propagate the new size to RenderWidgetHostView.
    136   // We can't send size zero because RenderWidget DCHECKs that.
    137   if (render_view_host()->GetView() && !bounds().IsEmpty()) {
    138     render_view_host()->GetView()->SetSize(size());
    139 
    140     if (container_)
    141       container_->OnViewWasResized();
    142   }
    143 }
    144 
    145 void ExtensionViewViews::PreferredSizeChanged() {
    146   View::PreferredSizeChanged();
    147   if (container_)
    148     container_->OnExtensionSizeChanged(this);
    149 }
    150 
    151 void ExtensionViewViews::OnFocus() {
    152   host()->host_contents()->GetView()->Focus();
    153 }
    154 
    155 void ExtensionViewViews::RenderViewCreated() {
    156   extensions::ViewType host_type = host_->extension_host_type();
    157   if (host_type == extensions::VIEW_TYPE_EXTENSION_POPUP) {
    158     gfx::Size min_size(ExtensionPopup::kMinWidth,
    159                        ExtensionPopup::kMinHeight);
    160     gfx::Size max_size(ExtensionPopup::kMaxWidth,
    161                        ExtensionPopup::kMaxHeight);
    162     render_view_host()->EnableAutoResize(min_size, max_size);
    163   }
    164 
    165   if (container_)
    166     container_->OnViewWasResized();
    167 }
    168 
    169 void ExtensionViewViews::HandleKeyboardEvent(
    170     const content::NativeWebKeyboardEvent& event) {
    171   unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
    172                                                         GetFocusManager());
    173 }
    174