1// Copyright (c) 2012 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/chrome_notification_types.h" 8#include "chrome/browser/notifications/balloon.h" 9#include "chrome/browser/notifications/balloon_collection_impl.h" 10#include "chrome/browser/notifications/notification.h" 11#include "chrome/browser/profiles/profile.h" 12#include "chrome/browser/renderer_preferences_util.h" 13#include "chrome/browser/ui/browser.h" 14#include "chrome/browser/ui/browser_finder.h" 15#include "chrome/browser/ui/browser_tabstrip.h" 16#include "chrome/browser/ui/host_desktop.h" 17#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" 18#include "chrome/common/extensions/extension_messages.h" 19#include "chrome/common/render_messages.h" 20#include "chrome/common/url_constants.h" 21#include "content/public/browser/navigation_controller.h" 22#include "content/public/browser/notification_service.h" 23#include "content/public/browser/notification_source.h" 24#include "content/public/browser/render_process_host.h" 25#include "content/public/browser/render_view_host.h" 26#include "content/public/browser/site_instance.h" 27#include "content/public/browser/web_contents.h" 28#include "content/public/common/bindings_policy.h" 29#include "content/public/common/renderer_preferences.h" 30#include "extensions/browser/view_type_utils.h" 31#include "ipc/ipc_message.h" 32 33using content::SiteInstance; 34using content::WebContents; 35 36BalloonHost::BalloonHost(Balloon* balloon) 37 : balloon_(balloon), 38 initialized_(false), 39 should_notify_on_disconnect_(false), 40 enable_web_ui_(false), 41 extension_function_dispatcher_(balloon_->profile(), this) { 42 site_instance_ = SiteInstance::CreateForURL( 43 balloon_->profile(), balloon_->notification().content_url()); 44} 45 46void BalloonHost::Shutdown() { 47 NotifyDisconnect(); 48 web_contents_.reset(); 49 site_instance_ = NULL; 50 balloon_ = NULL; // No longer safe to access |balloon_| 51} 52 53extensions::WindowController* 54BalloonHost::GetExtensionWindowController() const { 55 // Notifications don't have a window controller. 56 return NULL; 57} 58 59content::WebContents* BalloonHost::GetAssociatedWebContents() const { 60 return NULL; 61} 62 63const string16& BalloonHost::GetSource() const { 64 return balloon_->notification().display_source(); 65} 66 67void BalloonHost::CloseContents(WebContents* source) { 68 if (!balloon_) 69 return; 70 balloon_->CloseByScript(); 71 NotifyDisconnect(); 72} 73 74void BalloonHost::HandleMouseDown() { 75 if (balloon_) 76 balloon_->OnClick(); 77} 78 79void BalloonHost::ResizeDueToAutoResize(WebContents* source, 80 const gfx::Size& pref_size) { 81 if (balloon_) 82 balloon_->ResizeDueToAutoResize(pref_size); 83} 84 85void BalloonHost::AddNewContents(WebContents* source, 86 WebContents* new_contents, 87 WindowOpenDisposition disposition, 88 const gfx::Rect& initial_pos, 89 bool user_gesture, 90 bool* was_blocked) { 91 Browser* browser = chrome::FindLastActiveWithProfile( 92 Profile::FromBrowserContext(new_contents->GetBrowserContext()), 93 chrome::GetActiveDesktop()); 94 if (browser) { 95 chrome::AddWebContents(browser, NULL, new_contents, disposition, 96 initial_pos, user_gesture, was_blocked); 97 } 98} 99 100void BalloonHost::RenderViewCreated(content::RenderViewHost* render_view_host) { 101 gfx::Size min_size(BalloonCollectionImpl::min_balloon_width(), 102 BalloonCollectionImpl::min_balloon_height()); 103 gfx::Size max_size(BalloonCollectionImpl::max_balloon_width(), 104 BalloonCollectionImpl::max_balloon_height()); 105 render_view_host->EnableAutoResize(min_size, max_size); 106 107 if (enable_web_ui_) 108 render_view_host->AllowBindings(content::BINDINGS_POLICY_WEB_UI); 109} 110 111void BalloonHost::RenderViewReady() { 112 should_notify_on_disconnect_ = true; 113 content::NotificationService::current()->Notify( 114 chrome::NOTIFICATION_NOTIFY_BALLOON_CONNECTED, 115 content::Source<BalloonHost>(this), 116 content::NotificationService::NoDetails()); 117} 118 119void BalloonHost::RenderProcessGone(base::TerminationStatus status) { 120 CloseContents(web_contents_.get()); 121} 122 123bool BalloonHost::OnMessageReceived(const IPC::Message& message) { 124 bool handled = true; 125 IPC_BEGIN_MESSAGE_MAP(BalloonHost, message) 126 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) 127 IPC_MESSAGE_UNHANDLED(handled = false) 128 IPC_END_MESSAGE_MAP() 129 return handled; 130} 131 132void BalloonHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { 133 extension_function_dispatcher_.Dispatch(params, 134 web_contents_->GetRenderViewHost()); 135} 136 137void BalloonHost::Init() { 138 DCHECK(!web_contents_.get()) << "BalloonViewHost already initialized."; 139 web_contents_.reset(WebContents::Create( 140 WebContents::CreateParams(balloon_->profile(), site_instance_.get()))); 141 extensions::SetViewType( 142 web_contents_.get(), extensions::VIEW_TYPE_NOTIFICATION); 143 web_contents_->SetDelegate(this); 144 Observe(web_contents_.get()); 145 renderer_preferences_util::UpdateFromSystemSettings( 146 web_contents_->GetMutableRendererPrefs(), balloon_->profile()); 147 web_contents_->GetRenderViewHost()->SyncRendererPrefs(); 148 149 web_contents_->GetController().LoadURL( 150 balloon_->notification().content_url(), content::Referrer(), 151 content::PAGE_TRANSITION_LINK, std::string()); 152 153 initialized_ = true; 154} 155 156void BalloonHost::EnableWebUI() { 157 DCHECK(!web_contents_.get()) << 158 "EnableWebUI has to be called before a renderer is created."; 159 enable_web_ui_ = true; 160} 161 162BalloonHost::~BalloonHost() { 163} 164 165void BalloonHost::NotifyDisconnect() { 166 if (!should_notify_on_disconnect_) 167 return; 168 169 should_notify_on_disconnect_ = false; 170 content::NotificationService::current()->Notify( 171 chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED, 172 content::Source<BalloonHost>(this), 173 content::NotificationService::NoDetails()); 174} 175 176bool BalloonHost::IsRenderViewReady() const { 177 return should_notify_on_disconnect_; 178} 179 180bool BalloonHost::CanLoadDataURLsInWebUI() const { 181#if defined(OS_CHROMEOS) 182 // Chrome OS uses data URLs in WebUI BalloonHosts. We normally do not allow 183 // data URLs in WebUI renderers, but normal pages cannot target BalloonHosts, 184 // so this should be safe. 185 return true; 186#else 187 return false; 188#endif 189} 190