Home | History | Annotate | Download | only in notifications
      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 
     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 
     48 void BalloonHost::Shutdown() {
     49   NotifyDisconnect();
     50   if (render_view_host_) {
     51     render_view_host_->Shutdown();
     52     render_view_host_ = NULL;
     53   }
     54 }
     55 
     56 Browser* BalloonHost::GetBrowser() {
     57   // Notifications aren't associated with a particular browser.
     58   return NULL;
     59 }
     60 
     61 gfx::NativeView BalloonHost::GetNativeViewOfHost() {
     62   // TODO(aa): Should this return the native view of the BalloonView*?
     63   return NULL;
     64 }
     65 
     66 TabContents* BalloonHost::associated_tab_contents() const { return NULL; }
     67 
     68 const string16& BalloonHost::GetSource() const {
     69   return balloon_->notification().display_source();
     70 }
     71 
     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 
     80 SiteInstance* BalloonHost::GetSiteInstance() const {
     81   return site_instance_.get();
     82 }
     83 
     84 Profile* BalloonHost::GetProfile() const {
     85   return balloon_->profile();
     86 }
     87 
     88 const GURL& BalloonHost::GetURL() const {
     89   return balloon_->notification().content_url();
     90 }
     91 
     92 void BalloonHost::Close(RenderViewHost* render_view_host) {
     93   balloon_->CloseByScript();
     94   NotifyDisconnect();
     95 }
     96 
     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 
    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 
    116 void BalloonHost::RenderViewGone(RenderViewHost* render_view_host,
    117                                  base::TerminationStatus status,
    118                                  int error_code) {
    119   Close(render_view_host);
    120 }
    121 
    122 int BalloonHost::GetBrowserWindowID() const {
    123   return extension_misc::kUnknownWindowId;
    124 }
    125 
    126 ViewType::Type BalloonHost::GetRenderViewType() const {
    127   return ViewType::NOTIFICATION;
    128 }
    129 
    130 RenderViewHostDelegate::View* BalloonHost::GetViewDelegate() {
    131   return this;
    132 }
    133 
    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.
    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 
    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 
    175 bool BalloonHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
    176                                          bool* is_keyboard_shortcut) {
    177   return false;
    178 }
    179 
    180 void BalloonHost::UpdatePreferredSize(const gfx::Size& new_size) {
    181   balloon_->SetContentPreferredSize(new_size);
    182 }
    183 
    184 void BalloonHost::HandleMouseDown() {
    185   balloon_->OnClick();
    186 }
    187 
    188 RendererPreferences BalloonHost::GetRendererPrefs(Profile* profile) const {
    189   RendererPreferences preferences;
    190   renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile);
    191   return preferences;
    192 }
    193 
    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 
    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 
    237 void BalloonHost::UpdateInspectorSetting(const std::string& key,
    238                                          const std::string& value) {
    239   RenderViewHostDelegateHelper::UpdateInspectorSetting(
    240       GetProfile(), key, value);
    241 }
    242 
    243 void BalloonHost::ClearInspectorSettings() {
    244   RenderViewHostDelegateHelper::ClearInspectorSettings(GetProfile());
    245 }
    246 
    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 
    257 BalloonHost::~BalloonHost() {
    258   DCHECK(!render_view_host_);
    259 }
    260 
    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