Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 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.h"
      6 
      7 #include "chrome/browser/extensions/extension_host.h"
      8 #include "chrome/browser/ui/views/extensions/extension_popup.h"
      9 #include "content/browser/renderer_host/render_view_host.h"
     10 #include "content/browser/renderer_host/render_widget_host_view.h"
     11 #include "views/widget/widget.h"
     12 
     13 #if defined(OS_WIN)
     14 #include "chrome/browser/renderer_host/render_widget_host_view_win.h"
     15 #elif defined(TOUCH_UI)
     16 #include "chrome/browser/renderer_host/render_widget_host_view_views.h"
     17 #elif defined(OS_LINUX)
     18 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
     19 #endif
     20 
     21 ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser)
     22     : host_(host),
     23       browser_(browser),
     24       initialized_(false),
     25       container_(NULL),
     26       is_clipped_(false) {
     27   host_->set_view(this);
     28 
     29   // This view needs to be focusable so it can act as the focused view for the
     30   // focus manager. This is required to have SkipDefaultKeyEventProcessing
     31   // called so the tab key events are forwarded to the renderer.
     32   SetFocusable(true);
     33 }
     34 
     35 ExtensionView::~ExtensionView() {
     36   if (parent())
     37     parent()->RemoveChildView(this);
     38   CleanUp();
     39 }
     40 
     41 const Extension* ExtensionView::extension() const {
     42   return host_->extension();
     43 }
     44 
     45 RenderViewHost* ExtensionView::render_view_host() const {
     46   return host_->render_view_host();
     47 }
     48 
     49 void ExtensionView::DidStopLoading() {
     50   ShowIfCompletelyLoaded();
     51 }
     52 
     53 void ExtensionView::SetIsClipped(bool is_clipped) {
     54   if (is_clipped_ != is_clipped) {
     55     is_clipped_ = is_clipped;
     56     if (IsVisible())
     57       ShowIfCompletelyLoaded();
     58   }
     59 }
     60 
     61 void ExtensionView::SetVisible(bool is_visible) {
     62   if (is_visible != IsVisible()) {
     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()->view()) {
     69       if (is_visible)
     70         render_view_host()->view()->Show();
     71       else
     72         render_view_host()->view()->Hide();
     73     }
     74   }
     75 }
     76 
     77 void ExtensionView::CreateWidgetHostView() {
     78   DCHECK(!initialized_);
     79   initialized_ = true;
     80   RenderWidgetHostView* view =
     81       RenderWidgetHostView::CreateViewForWidget(render_view_host());
     82 
     83   // TODO(mpcomplete): RWHV needs a cross-platform Init function.
     84 #if defined(OS_WIN)
     85   // Create the HWND. Note:
     86   // RenderWidgetHostHWND supports windowed plugins, but if we ever also
     87   // wanted to support constrained windows with this, we would need an
     88   // additional HWND to parent off of because windowed plugin HWNDs cannot
     89   // exist in the same z-order as constrained windows.
     90   RenderWidgetHostViewWin* view_win =
     91       static_cast<RenderWidgetHostViewWin*>(view);
     92   HWND hwnd = view_win->Create(GetWidget()->GetNativeView());
     93   view_win->ShowWindow(SW_SHOW);
     94   Attach(hwnd);
     95 #elif defined(TOUCH_UI)
     96   RenderWidgetHostViewViews* view_views =
     97       static_cast<RenderWidgetHostViewViews*>(view);
     98   view_views->InitAsChild();
     99   AttachToView(view_views);
    100 #elif defined(OS_LINUX)
    101   RenderWidgetHostViewGtk* view_gtk =
    102       static_cast<RenderWidgetHostViewGtk*>(view);
    103   view_gtk->InitAsChild();
    104   Attach(view_gtk->GetNativeView());
    105 #else
    106   NOTIMPLEMENTED();
    107 #endif
    108 
    109   host_->CreateRenderViewSoon(view);
    110   SetVisible(false);
    111 }
    112 
    113 void ExtensionView::ShowIfCompletelyLoaded() {
    114   if (IsVisible() || is_clipped_)
    115     return;
    116 
    117   // We wait to show the ExtensionView until it has loaded, and the view has
    118   // actually been created. These can happen in different orders.
    119   if (host_->did_stop_loading()) {
    120     SetVisible(true);
    121     UpdatePreferredSize(pending_preferred_size_);
    122   }
    123 }
    124 
    125 void ExtensionView::CleanUp() {
    126   if (!initialized_)
    127     return;
    128   if (native_view())
    129     Detach();
    130   initialized_ = false;
    131 }
    132 
    133 void ExtensionView::SetBackground(const SkBitmap& background) {
    134   if (render_view_host()->IsRenderViewLive() && render_view_host()->view()) {
    135     render_view_host()->view()->SetBackground(background);
    136   } else {
    137     pending_background_ = background;
    138   }
    139   ShowIfCompletelyLoaded();
    140 }
    141 
    142 void ExtensionView::UpdatePreferredSize(const gfx::Size& new_size) {
    143   // Don't actually do anything with this information until we have been shown.
    144   // Size changes will not be honored by lower layers while we are hidden.
    145   if (!IsVisible()) {
    146     pending_preferred_size_ = new_size;
    147     return;
    148   }
    149 
    150   gfx::Size preferred_size = GetPreferredSize();
    151   if (new_size != preferred_size)
    152     SetPreferredSize(new_size);
    153 }
    154 
    155 void ExtensionView::ViewHierarchyChanged(bool is_add,
    156                                          views::View *parent,
    157                                          views::View *child) {
    158   NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
    159   if (is_add && GetWidget() && !initialized_)
    160     CreateWidgetHostView();
    161 }
    162 
    163 void ExtensionView::PreferredSizeChanged() {
    164   View::PreferredSizeChanged();
    165   if (container_)
    166     container_->OnExtensionPreferredSizeChanged(this);
    167 }
    168 
    169 bool ExtensionView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
    170   // Let the tab key event be processed by the renderer (instead of moving the
    171   // focus to the next focusable view).
    172   return (e.key_code() == ui::VKEY_TAB);
    173 }
    174 
    175 void ExtensionView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
    176   // Propagate the new size to RenderWidgetHostView.
    177   // We can't send size zero because RenderWidget DCHECKs that.
    178   if (render_view_host()->view() && !bounds().IsEmpty())
    179     render_view_host()->view()->SetSize(size());
    180 }
    181 
    182 void ExtensionView::HandleMouseMove() {
    183   if (container_)
    184     container_->OnExtensionMouseMove(this);
    185 }
    186 
    187 void ExtensionView::HandleMouseLeave() {
    188   if (container_)
    189     container_->OnExtensionMouseLeave(this);
    190 }
    191 
    192 void ExtensionView::RenderViewCreated() {
    193   if (!pending_background_.empty() && render_view_host()->view()) {
    194     render_view_host()->view()->SetBackground(pending_background_);
    195     pending_background_.reset();
    196   }
    197 
    198   // Tell the renderer not to draw scroll bars in popups unless the
    199   // popups are at the maximum allowed size.
    200   gfx::Size largest_popup_size(ExtensionPopup::kMaxWidth,
    201                                ExtensionPopup::kMaxHeight);
    202   host_->DisableScrollbarsForSmallWindows(largest_popup_size);
    203 }
    204