balloon_host.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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/notifications/balloon_host.h"
6
7#include "chrome/browser/browser_list.h"
8#include "chrome/browser/extensions/extension_process_manager.h"
9#include "chrome/browser/notifications/balloon.h"
10#include "chrome/browser/profile.h"
11#include "chrome/browser/renderer_host/render_view_host.h"
12#include "chrome/browser/renderer_host/site_instance.h"
13#include "chrome/browser/renderer_preferences_util.h"
14#include "chrome/common/bindings_policy.h"
15#include "chrome/common/notification_service.h"
16#include "chrome/common/notification_type.h"
17#include "chrome/common/render_messages.h"
18#include "chrome/common/renderer_preferences.h"
19#include "chrome/common/url_constants.h"
20
21BalloonHost::BalloonHost(Balloon* balloon)
22    : render_view_host_(NULL),
23      balloon_(balloon),
24      initialized_(false),
25      should_notify_on_disconnect_(false),
26      enable_dom_ui_(false) {
27  DCHECK(balloon_);
28
29  // If the notification is for an extension URL, make sure to use the extension
30  // process to render it, so that it can communicate with other views in the
31  // extension.
32  const GURL& balloon_url = balloon_->notification().content_url();
33  if (balloon_url.SchemeIs(chrome::kExtensionScheme)) {
34    site_instance_ =
35      balloon_->profile()->GetExtensionProcessManager()->GetSiteInstanceForURL(
36          balloon_url);
37  } else {
38    site_instance_ = SiteInstance::CreateSiteInstance(balloon_->profile());
39  }
40}
41
42void BalloonHost::Shutdown() {
43  if (render_view_host_) {
44    render_view_host_->Shutdown();
45    render_view_host_ = NULL;
46  }
47}
48
49Browser* BalloonHost::GetBrowser() const {
50  // Notifications aren't associated with a particular browser.
51  return NULL;
52}
53
54gfx::NativeView BalloonHost::GetNativeViewOfHost() {
55  // TODO(aa): Should this return the native view of the BalloonView*?
56  return NULL;
57}
58
59TabContents* BalloonHost::associated_tab_contents() const { return NULL; }
60
61WebPreferences BalloonHost::GetWebkitPrefs() {
62  WebPreferences prefs;
63  prefs.allow_scripts_to_close_windows = true;
64  return prefs;
65}
66
67SiteInstance* BalloonHost::GetSiteInstance() const {
68  return site_instance_.get();
69}
70
71Profile* BalloonHost::GetProfile() const {
72  return balloon_->profile();
73}
74
75const GURL& BalloonHost::GetURL() const {
76  return balloon_->notification().content_url();
77}
78
79void BalloonHost::Close(RenderViewHost* render_view_host) {
80  balloon_->CloseByScript();
81  NotifyDisconnect();
82}
83
84void BalloonHost::RenderViewCreated(RenderViewHost* render_view_host) {
85  render_view_host->Send(new ViewMsg_DisableScrollbarsForSmallWindows(
86      render_view_host->routing_id(), balloon_->min_scrollbar_size()));
87  render_view_host->WasResized();
88  render_view_host->EnablePreferredSizeChangedMode(
89      kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
90}
91
92void BalloonHost::RenderViewReady(RenderViewHost* render_view_host) {
93  should_notify_on_disconnect_ = true;
94  NotificationService::current()->Notify(
95      NotificationType::NOTIFY_BALLOON_CONNECTED,
96      Source<BalloonHost>(this), NotificationService::NoDetails());
97}
98
99void BalloonHost::RenderViewGone(RenderViewHost* render_view_host) {
100  Close(render_view_host);
101}
102
103int BalloonHost::GetBrowserWindowID() const {
104  return extension_misc::kUnknownWindowId;
105}
106
107ViewType::Type BalloonHost::GetRenderViewType() const {
108  return ViewType::NOTIFICATION;
109}
110
111RenderViewHostDelegate::View* BalloonHost::GetViewDelegate() {
112  return this;
113}
114
115void BalloonHost::ProcessDOMUIMessage(
116    const ViewHostMsg_DomMessage_Params& params) {
117  if (extension_function_dispatcher_.get()) {
118    extension_function_dispatcher_->HandleRequest(params);
119  }
120}
121
122// RenderViewHostDelegate::View methods implemented to allow links to
123// open pages in new tabs.
124void BalloonHost::CreateNewWindow(
125    int route_id,
126    WindowContainerType window_container_type,
127    const string16& frame_name) {
128  delegate_view_helper_.CreateNewWindow(
129      route_id,
130      balloon_->profile(),
131      site_instance_.get(),
132      DOMUIFactory::GetDOMUIType(balloon_->profile(),
133          balloon_->notification().content_url()),
134      this,
135      window_container_type,
136      frame_name);
137}
138
139void BalloonHost::ShowCreatedWindow(int route_id,
140                                    WindowOpenDisposition disposition,
141                                    const gfx::Rect& initial_pos,
142                                    bool user_gesture) {
143  // Don't allow pop-ups from notifications.
144  if (disposition == NEW_POPUP)
145    return;
146
147  TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id);
148  if (!contents)
149    return;
150  Browser* browser = BrowserList::GetLastActiveWithProfile(balloon_->profile());
151  if (!browser)
152    return;
153
154  browser->AddTabContents(contents, disposition, initial_pos, user_gesture);
155}
156
157void BalloonHost::UpdatePreferredSize(const gfx::Size& new_size) {
158  balloon_->SetContentPreferredSize(new_size);
159}
160
161void BalloonHost::HandleMouseDown() {
162  balloon_->OnClick();
163}
164
165RendererPreferences BalloonHost::GetRendererPrefs(Profile* profile) const {
166  RendererPreferences preferences;
167  renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile);
168  return preferences;
169}
170
171void BalloonHost::Init() {
172  DCHECK(!render_view_host_) << "BalloonViewHost already initialized.";
173  RenderViewHost* rvh = new RenderViewHost(
174      site_instance_.get(), this, MSG_ROUTING_NONE, NULL);
175  if (GetProfile()->GetExtensionsService()) {
176    extension_function_dispatcher_.reset(
177        ExtensionFunctionDispatcher::Create(
178            rvh, this, balloon_->notification().content_url()));
179  }
180  if (extension_function_dispatcher_.get()) {
181    rvh->AllowBindings(BindingsPolicy::EXTENSION);
182    rvh->set_is_extension_process(true);
183  } else if (enable_dom_ui_) {
184    rvh->AllowBindings(BindingsPolicy::DOM_UI);
185  }
186
187  // Do platform-specific initialization.
188  render_view_host_ = rvh;
189  InitRenderWidgetHostView();
190  DCHECK(render_widget_host_view());
191
192  rvh->set_view(render_widget_host_view());
193  rvh->CreateRenderView(string16());
194  rvh->NavigateToURL(balloon_->notification().content_url());
195
196  initialized_ = true;
197}
198
199void BalloonHost::EnableDOMUI() {
200  DCHECK(render_view_host_ == NULL) <<
201      "EnableDOMUI has to be called before a renderer is created.";
202  enable_dom_ui_ = true;
203}
204
205void BalloonHost::UpdateInspectorSetting(const std::string& key,
206                                         const std::string& value) {
207  RenderViewHostDelegateHelper::UpdateInspectorSetting(
208      GetProfile(), key, value);
209}
210
211void BalloonHost::ClearInspectorSettings() {
212  RenderViewHostDelegateHelper::ClearInspectorSettings(GetProfile());
213}
214
215BalloonHost::~BalloonHost() {}
216
217void BalloonHost::NotifyDisconnect() {
218  if (!should_notify_on_disconnect_)
219    return;
220
221  should_notify_on_disconnect_ = false;
222  NotificationService::current()->Notify(
223      NotificationType::NOTIFY_BALLOON_DISCONNECTED,
224      Source<BalloonHost>(this), NotificationService::NoDetails());
225}
226