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 33 using content::SiteInstance; 34 using content::WebContents; 35 36 BalloonHost::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 46 void BalloonHost::Shutdown() { 47 NotifyDisconnect(); 48 web_contents_.reset(); 49 site_instance_ = NULL; 50 balloon_ = NULL; // No longer safe to access |balloon_| 51 } 52 53 extensions::WindowController* 54 BalloonHost::GetExtensionWindowController() const { 55 // Notifications don't have a window controller. 56 return NULL; 57 } 58 59 content::WebContents* BalloonHost::GetAssociatedWebContents() const { 60 return NULL; 61 } 62 63 const string16& BalloonHost::GetSource() const { 64 return balloon_->notification().display_source(); 65 } 66 67 void BalloonHost::CloseContents(WebContents* source) { 68 if (!balloon_) 69 return; 70 balloon_->CloseByScript(); 71 NotifyDisconnect(); 72 } 73 74 void BalloonHost::HandleMouseDown() { 75 if (balloon_) 76 balloon_->OnClick(); 77 } 78 79 void BalloonHost::ResizeDueToAutoResize(WebContents* source, 80 const gfx::Size& pref_size) { 81 if (balloon_) 82 balloon_->ResizeDueToAutoResize(pref_size); 83 } 84 85 void 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 100 void 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 111 void 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 119 void BalloonHost::RenderProcessGone(base::TerminationStatus status) { 120 CloseContents(web_contents_.get()); 121 } 122 123 bool 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 132 void BalloonHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { 133 extension_function_dispatcher_.Dispatch(params, 134 web_contents_->GetRenderViewHost()); 135 } 136 137 void 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 156 void 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 162 BalloonHost::~BalloonHost() { 163 } 164 165 void 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 176 bool BalloonHost::IsRenderViewReady() const { 177 return should_notify_on_disconnect_; 178 } 179 180 bool 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