summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_view.cc
blob: 5678e081ed295471cdf0ff2d55e91062b1c483a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_view.h"

#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/views/widget/widget.h"

#if defined(OS_WIN)
#include "chrome/browser/renderer_host/render_widget_host_view_win.h"
#endif

ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser,
                             const GURL& content_url)
    : host_(host), browser_(browser), content_url_(content_url),
      initialized_(false) {
  host_->set_view(this);
}

ExtensionView::~ExtensionView() {
  if (GetHWND())
    Detach();
}

void ExtensionView::SetVisible(bool is_visible) {
  HWNDView::SetVisible(is_visible);

  // Also tell RenderWidgetHostView the new visibility. Despite its name, it is
  // not part of the View heirarchy and does not know about the change unless we
  // tell it.
  if (render_view_host()->view()) {
    if (is_visible)
      render_view_host()->view()->Show();
    else
      render_view_host()->view()->Hide();
  }
}

void ExtensionView::DidChangeBounds(const gfx::Rect& previous,
                                    const gfx::Rect& current) {
  // Propagate the new size to RenderWidgetHostView.
  // We can't send size zero because RenderWidget DCHECKs that.
  if (render_view_host()->view() && !current.IsEmpty())
    render_view_host()->view()->SetSize(gfx::Size(width(), height()));
}

void ExtensionView::ShowIfCompletelyLoaded() {
  // We wait to show the ExtensionView until it has loaded and our parent has
  // given us a background. These can happen in different orders.
  if (host_->did_stop_loading() && render_view_host()->view() &&
      !render_view_host()->view()->background().empty()) {
    SetVisible(true);
    DidContentsPreferredWidthChange(pending_preferred_width_);
  }
}

void ExtensionView::SetBackground(const SkBitmap& background) {
  if (initialized_ && render_view_host()->view()) {
    render_view_host()->view()->SetBackground(background);
  } else {
    pending_background_ = background;
  }
  ShowIfCompletelyLoaded();
}

void ExtensionView::DidContentsPreferredWidthChange(const int pref_width) {
  // Don't actually do anything with this information until we have been shown.
  // Size changes will not be honored by lower layers while we are hidden.
  if (!IsVisible()) {
    pending_preferred_width_ = pref_width;
  } else if (pref_width > 0) {
    set_preferred_size(gfx::Size(pref_width, height()));
    SizeToPreferredSize();

    // TODO(rafaelw): This assumes that the extension view is a child of an
    // ExtensionToolstrip, which is a child of the BookmarkBarView. There should
    // be a way to do this where the ExtensionView doesn't have to know it's
    // containment hierarchy.
    if (GetParent() != NULL && GetParent()->GetParent() != NULL) {
      GetParent()->GetParent()->Layout();
    }

    SchedulePaint();
  }
}

void ExtensionView::ViewHierarchyChanged(bool is_add,
                                         views::View *parent,
                                         views::View *child) {
  if (is_add && GetWidget() && !initialized_) {
    initialized_ = true;

    RenderWidgetHostView* view = RenderWidgetHostView::CreateViewForWidget(
        render_view_host());

    // TODO(mpcomplete): RWHV needs a cross-platform Init function.
#if defined(OS_WIN)
    // Create the HWND. Note:
    // RenderWidgetHostHWND supports windowed plugins, but if we ever also
    // wanted to support constrained windows with this, we would need an
    // additional HWND to parent off of because windowed plugin HWNDs cannot
    // exist in the same z-order as constrained windows.
    RenderWidgetHostViewWin* view_win =
        static_cast<RenderWidgetHostViewWin*>(view);
    HWND hwnd = view_win->Create(GetWidget()->GetNativeView());
    view_win->ShowWindow(SW_SHOW);
    Attach(hwnd);
#else
    NOTIMPLEMENTED();
#endif

    host_->CreateRenderView(content_url_, view);
    SetVisible(false);

    if (!pending_background_.empty()) {
      render_view_host()->view()->SetBackground(pending_background_);
      pending_background_.reset();
    }
  }
}