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