• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/notifications/balloon_host.h"
6 #include "chrome/browser/extensions/extension_process_manager.h"
7 #include "chrome/browser/extensions/extension_service.h"
8 #include "chrome/browser/notifications/balloon.h"
9 #include "chrome/browser/notifications/notification.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/renderer_preferences_util.h"
12 #include "chrome/browser/ui/browser_list.h"
13 #include "chrome/browser/ui/webui/chrome_web_ui_factory.h"
14 #include "chrome/common/render_messages.h"
15 #include "chrome/common/url_constants.h"
16 #include "content/browser/renderer_host/browser_render_process_host.h"
17 #include "content/browser/renderer_host/render_view_host.h"
18 #include "content/browser/site_instance.h"
19 #include "content/common/bindings_policy.h"
20 #include "content/common/notification_service.h"
21 #include "content/common/notification_source.h"
22 #include "content/common/notification_type.h"
23 #include "content/common/renderer_preferences.h"
24 #include "content/common/view_messages.h"
25 #include "webkit/glue/webpreferences.h"
26 
BalloonHost(Balloon * balloon)27 BalloonHost::BalloonHost(Balloon* balloon)
28     : render_view_host_(NULL),
29       balloon_(balloon),
30       initialized_(false),
31       should_notify_on_disconnect_(false),
32       enable_web_ui_(false) {
33   DCHECK(balloon_);
34 
35   // If the notification is for an extension URL, make sure to use the extension
36   // process to render it, so that it can communicate with other views in the
37   // extension.
38   const GURL& balloon_url = balloon_->notification().content_url();
39   if (balloon_url.SchemeIs(chrome::kExtensionScheme)) {
40     site_instance_ =
41       balloon_->profile()->GetExtensionProcessManager()->GetSiteInstanceForURL(
42           balloon_url);
43   } else {
44     site_instance_ = SiteInstance::CreateSiteInstance(balloon_->profile());
45   }
46 }
47 
Shutdown()48 void BalloonHost::Shutdown() {
49   NotifyDisconnect();
50   if (render_view_host_) {
51     render_view_host_->Shutdown();
52     render_view_host_ = NULL;
53   }
54 }
55 
GetBrowser()56 Browser* BalloonHost::GetBrowser() {
57   // Notifications aren't associated with a particular browser.
58   return NULL;
59 }
60 
GetNativeViewOfHost()61 gfx::NativeView BalloonHost::GetNativeViewOfHost() {
62   // TODO(aa): Should this return the native view of the BalloonView*?
63   return NULL;
64 }
65 
associated_tab_contents() const66 TabContents* BalloonHost::associated_tab_contents() const { return NULL; }
67 
GetSource() const68 const string16& BalloonHost::GetSource() const {
69   return balloon_->notification().display_source();
70 }
71 
GetWebkitPrefs()72 WebPreferences BalloonHost::GetWebkitPrefs() {
73   WebPreferences web_prefs =
74       RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(),
75                                                    enable_web_ui_);
76   web_prefs.allow_scripts_to_close_windows = true;
77   return web_prefs;
78 }
79 
GetSiteInstance() const80 SiteInstance* BalloonHost::GetSiteInstance() const {
81   return site_instance_.get();
82 }
83 
GetProfile() const84 Profile* BalloonHost::GetProfile() const {
85   return balloon_->profile();
86 }
87 
GetURL() const88 const GURL& BalloonHost::GetURL() const {
89   return balloon_->notification().content_url();
90 }
91 
Close(RenderViewHost * render_view_host)92 void BalloonHost::Close(RenderViewHost* render_view_host) {
93   balloon_->CloseByScript();
94   NotifyDisconnect();
95 }
96 
RenderViewCreated(RenderViewHost * render_view_host)97 void BalloonHost::RenderViewCreated(RenderViewHost* render_view_host) {
98   render_view_host->Send(new ViewMsg_DisableScrollbarsForSmallWindows(
99       render_view_host->routing_id(), balloon_->min_scrollbar_size()));
100   render_view_host->WasResized();
101 #if !defined(OS_MACOSX)
102   // TODO(levin): Make all of the code that went in originally with this change
103   // to be cross-platform. See http://crbug.com/64720
104   render_view_host->EnablePreferredSizeChangedMode(
105       kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
106 #endif
107 }
108 
RenderViewReady(RenderViewHost * render_view_host)109 void BalloonHost::RenderViewReady(RenderViewHost* render_view_host) {
110   should_notify_on_disconnect_ = true;
111   NotificationService::current()->Notify(
112       NotificationType::NOTIFY_BALLOON_CONNECTED,
113       Source<BalloonHost>(this), NotificationService::NoDetails());
114 }
115 
RenderViewGone(RenderViewHost * render_view_host,base::TerminationStatus status,int error_code)116 void BalloonHost::RenderViewGone(RenderViewHost* render_view_host,
117                                  base::TerminationStatus status,
118                                  int error_code) {
119   Close(render_view_host);
120 }
121 
GetBrowserWindowID() const122 int BalloonHost::GetBrowserWindowID() const {
123   return extension_misc::kUnknownWindowId;
124 }
125 
GetRenderViewType() const126 ViewType::Type BalloonHost::GetRenderViewType() const {
127   return ViewType::NOTIFICATION;
128 }
129 
GetViewDelegate()130 RenderViewHostDelegate::View* BalloonHost::GetViewDelegate() {
131   return this;
132 }
133 
ProcessWebUIMessage(const ExtensionHostMsg_DomMessage_Params & params)134 void BalloonHost::ProcessWebUIMessage(
135     const ExtensionHostMsg_DomMessage_Params& params) {
136   if (extension_function_dispatcher_.get()) {
137     extension_function_dispatcher_->HandleRequest(params);
138   }
139 }
140 
141 // RenderViewHostDelegate::View methods implemented to allow links to
142 // open pages in new tabs.
CreateNewWindow(int route_id,const ViewHostMsg_CreateWindow_Params & params)143 void BalloonHost::CreateNewWindow(
144     int route_id,
145     const ViewHostMsg_CreateWindow_Params& params) {
146   delegate_view_helper_.CreateNewWindow(
147       route_id,
148       balloon_->profile(),
149       site_instance_.get(),
150       ChromeWebUIFactory::GetInstance()->GetWebUIType(balloon_->profile(),
151           balloon_->notification().content_url()),
152       this,
153       params.window_container_type,
154       params.frame_name);
155 }
156 
ShowCreatedWindow(int route_id,WindowOpenDisposition disposition,const gfx::Rect & initial_pos,bool user_gesture)157 void BalloonHost::ShowCreatedWindow(int route_id,
158                                     WindowOpenDisposition disposition,
159                                     const gfx::Rect& initial_pos,
160                                     bool user_gesture) {
161   // Don't allow pop-ups from notifications.
162   if (disposition == NEW_POPUP)
163     return;
164 
165   TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id);
166   if (!contents)
167     return;
168   Browser* browser = BrowserList::GetLastActiveWithProfile(balloon_->profile());
169   if (!browser)
170     return;
171 
172   browser->AddTabContents(contents, disposition, initial_pos, user_gesture);
173 }
174 
PreHandleKeyboardEvent(const NativeWebKeyboardEvent & event,bool * is_keyboard_shortcut)175 bool BalloonHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
176                                          bool* is_keyboard_shortcut) {
177   return false;
178 }
179 
UpdatePreferredSize(const gfx::Size & new_size)180 void BalloonHost::UpdatePreferredSize(const gfx::Size& new_size) {
181   balloon_->SetContentPreferredSize(new_size);
182 }
183 
HandleMouseDown()184 void BalloonHost::HandleMouseDown() {
185   balloon_->OnClick();
186 }
187 
GetRendererPrefs(Profile * profile) const188 RendererPreferences BalloonHost::GetRendererPrefs(Profile* profile) const {
189   RendererPreferences preferences;
190   renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile);
191   return preferences;
192 }
193 
Init()194 void BalloonHost::Init() {
195   DCHECK(!render_view_host_) << "BalloonViewHost already initialized.";
196   RenderViewHost* rvh = new RenderViewHost(
197       site_instance_.get(), this, MSG_ROUTING_NONE, NULL);
198   if (GetProfile()->GetExtensionService()) {
199     extension_function_dispatcher_.reset(
200         ExtensionFunctionDispatcher::Create(
201             rvh, this, balloon_->notification().content_url()));
202   }
203   if (extension_function_dispatcher_.get()) {
204     rvh->AllowBindings(BindingsPolicy::EXTENSION);
205     rvh->set_is_extension_process(true);
206     const Extension* installed_app =
207         GetProfile()->GetExtensionService()->GetInstalledApp(
208             balloon_->notification().content_url());
209     static_cast<BrowserRenderProcessHost*>(rvh->process())->set_installed_app(
210         installed_app);
211   } else if (enable_web_ui_) {
212     rvh->AllowBindings(BindingsPolicy::WEB_UI);
213   }
214 
215   // Do platform-specific initialization.
216   render_view_host_ = rvh;
217   InitRenderWidgetHostView();
218   DCHECK(render_widget_host_view());
219 
220   rvh->set_view(render_widget_host_view());
221   rvh->CreateRenderView(string16());
222 #if defined(OS_MACOSX)
223   registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT,
224       Source<RenderWidgetHost>(render_view_host_));
225 #endif
226   rvh->NavigateToURL(balloon_->notification().content_url());
227 
228   initialized_ = true;
229 }
230 
EnableWebUI()231 void BalloonHost::EnableWebUI() {
232   DCHECK(render_view_host_ == NULL) <<
233       "EnableWebUI has to be called before a renderer is created.";
234   enable_web_ui_ = true;
235 }
236 
UpdateInspectorSetting(const std::string & key,const std::string & value)237 void BalloonHost::UpdateInspectorSetting(const std::string& key,
238                                          const std::string& value) {
239   RenderViewHostDelegateHelper::UpdateInspectorSetting(
240       GetProfile(), key, value);
241 }
242 
ClearInspectorSettings()243 void BalloonHost::ClearInspectorSettings() {
244   RenderViewHostDelegateHelper::ClearInspectorSettings(GetProfile());
245 }
246 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)247 void BalloonHost::Observe(NotificationType type,
248     const NotificationSource& source,
249     const NotificationDetails& details) {
250   if (type == NotificationType::RENDER_WIDGET_HOST_DID_PAINT) {
251     registrar_.RemoveAll();
252     render_view_host_->EnablePreferredSizeChangedMode(
253         kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
254   }
255 }
256 
~BalloonHost()257 BalloonHost::~BalloonHost() {
258   DCHECK(!render_view_host_);
259 }
260 
NotifyDisconnect()261 void BalloonHost::NotifyDisconnect() {
262   if (!should_notify_on_disconnect_)
263     return;
264 
265   should_notify_on_disconnect_ = false;
266   NotificationService::current()->Notify(
267       NotificationType::NOTIFY_BALLOON_DISCONNECTED,
268       Source<BalloonHost>(this), NotificationService::NoDetails());
269 }
270