| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 2009 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/desktop_notification_service.h" | 
 |    6  | 
 |    7 #include "app/l10n_util.h" | 
 |    8 #include "app/resource_bundle.h" | 
 |    9 #include "base/thread.h" | 
 |   10 #include "chrome/browser/browser_list.h" | 
 |   11 #include "chrome/browser/browser_process.h" | 
 |   12 #include "chrome/browser/chrome_thread.h" | 
 |   13 #include "chrome/browser/notifications/notification.h" | 
 |   14 #include "chrome/browser/notifications/notification_object_proxy.h" | 
 |   15 #include "chrome/browser/notifications/notifications_prefs_cache.h" | 
 |   16 #include "chrome/browser/profile.h" | 
 |   17 #include "chrome/browser/renderer_host/render_process_host.h" | 
 |   18 #include "chrome/browser/renderer_host/render_view_host.h" | 
 |   19 #include "chrome/browser/renderer_host/site_instance.h" | 
 |   20 #include "chrome/browser/tab_contents/infobar_delegate.h" | 
 |   21 #include "chrome/browser/tab_contents/tab_contents.h" | 
 |   22 #include "chrome/browser/worker_host/worker_process_host.h" | 
 |   23 #include "chrome/common/child_process_host.h" | 
 |   24 #include "chrome/common/pref_names.h" | 
 |   25 #include "chrome/common/pref_service.h" | 
 |   26 #include "chrome/common/render_messages.h" | 
 |   27 #include "webkit/api/public/WebNotificationPresenter.h" | 
 |   28 #include "grit/chromium_strings.h" | 
 |   29 #include "grit/generated_resources.h" | 
 |   30 #include "grit/theme_resources.h" | 
 |   31  | 
 |   32 using WebKit::WebNotificationPresenter; | 
 |   33  | 
 |   34 // A task object which calls the renderer to inform the web page that the | 
 |   35 // permission request has completed. | 
 |   36 class NotificationPermissionCallbackTask : public Task { | 
 |   37  public: | 
 |   38   NotificationPermissionCallbackTask(int process_id, int route_id, | 
 |   39       int request_id) | 
 |   40       : process_id_(process_id), | 
 |   41         route_id_(route_id), | 
 |   42         request_id_(request_id) { | 
 |   43   } | 
 |   44  | 
 |   45   virtual void Run() { | 
 |   46     DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 
 |   47     RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_); | 
 |   48     if (host) | 
 |   49       host->Send(new ViewMsg_PermissionRequestDone(route_id_, request_id_)); | 
 |   50   } | 
 |   51  | 
 |   52  private: | 
 |   53   int process_id_; | 
 |   54   int route_id_; | 
 |   55   int request_id_; | 
 |   56 }; | 
 |   57  | 
 |   58 // The delegate for the infobar shown when an origin requests notification | 
 |   59 // permissions. | 
 |   60 class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate { | 
 |   61  public: | 
 |   62   NotificationPermissionInfoBarDelegate(TabContents* contents, | 
 |   63                                         const GURL& origin, | 
 |   64                                         int callback_context) | 
 |   65       : ConfirmInfoBarDelegate(contents), | 
 |   66         origin_(origin), | 
 |   67         profile_(contents->profile()), | 
 |   68         process_id_(contents->process()->id()), | 
 |   69         route_id_(contents->render_view_host()->routing_id()), | 
 |   70         callback_context_(callback_context), | 
 |   71         action_taken_(false) { | 
 |   72   } | 
 |   73  | 
 |   74   // Overridden from ConfirmInfoBarDelegate: | 
 |   75   virtual void InfoBarClosed() { | 
 |   76     if (!action_taken_) | 
 |   77       UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1); | 
 |   78  | 
 |   79     base::Thread* io_thread = g_browser_process->io_thread(); | 
 |   80     if (io_thread && io_thread->message_loop()) { | 
 |   81       io_thread->message_loop()->PostTask(FROM_HERE, | 
 |   82         new NotificationPermissionCallbackTask(process_id_, route_id_, | 
 |   83             callback_context_)); | 
 |   84     } | 
 |   85  | 
 |   86     delete this; | 
 |   87   } | 
 |   88  | 
 |   89   virtual std::wstring GetMessageText() const { | 
 |   90     return l10n_util::GetStringF(IDS_NOTIFICATION_PERMISSIONS, | 
 |   91                                  UTF8ToWide(origin_.spec())); | 
 |   92   } | 
 |   93  | 
 |   94   virtual SkBitmap* GetIcon() const { | 
 |   95     return ResourceBundle::GetSharedInstance().GetBitmapNamed( | 
 |   96        IDR_PRODUCT_ICON_32); | 
 |   97   } | 
 |   98  | 
 |   99   virtual int GetButtons() const { | 
 |  100     return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT; | 
 |  101   } | 
 |  102  | 
 |  103   virtual std::wstring GetButtonLabel(InfoBarButton button) const { | 
 |  104     return button == BUTTON_OK ? | 
 |  105         l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_YES) : | 
 |  106         l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_NO); | 
 |  107   } | 
 |  108  | 
 |  109   virtual bool Accept() { | 
 |  110     UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1); | 
 |  111     profile_->GetDesktopNotificationService()->GrantPermission(origin_); | 
 |  112     action_taken_ = true; | 
 |  113     return true; | 
 |  114   } | 
 |  115  | 
 |  116   virtual bool Cancel() { | 
 |  117     UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1); | 
 |  118     profile_->GetDesktopNotificationService()->DenyPermission(origin_); | 
 |  119     action_taken_ = true; | 
 |  120     return true; | 
 |  121   } | 
 |  122  | 
 |  123  private: | 
 |  124   // The origin we are asking for permissions on. | 
 |  125   GURL origin_; | 
 |  126  | 
 |  127   // The Profile that we restore sessions from. | 
 |  128   Profile* profile_; | 
 |  129  | 
 |  130   // The callback information that tells us how to respond to javascript via | 
 |  131   // the correct RenderView. | 
 |  132   int process_id_; | 
 |  133   int route_id_; | 
 |  134   int callback_context_; | 
 |  135  | 
 |  136   // Whether the user clicked one of the buttons. | 
 |  137   bool action_taken_; | 
 |  138  | 
 |  139   DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate); | 
 |  140 }; | 
 |  141  | 
 |  142 DesktopNotificationService::DesktopNotificationService(Profile* profile, | 
 |  143     NotificationUIManager* ui_manager) | 
 |  144     : profile_(profile), | 
 |  145       ui_manager_(ui_manager) { | 
 |  146   InitPrefs(); | 
 |  147 } | 
 |  148  | 
 |  149 DesktopNotificationService::~DesktopNotificationService() { | 
 |  150 } | 
 |  151  | 
 |  152 // Initialize the cache with the allowed and denied origins, or | 
 |  153 // create the preferences if they don't exist yet. | 
 |  154 void DesktopNotificationService::InitPrefs() { | 
 |  155   PrefService* prefs = profile_->GetPrefs(); | 
 |  156   ListValue* allowed_sites = NULL; | 
 |  157   ListValue* denied_sites = NULL; | 
 |  158  | 
 |  159   if (prefs->FindPreference(prefs::kDesktopNotificationAllowedOrigins)) | 
 |  160     allowed_sites = | 
 |  161         prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins); | 
 |  162   else | 
 |  163     prefs->RegisterListPref(prefs::kDesktopNotificationAllowedOrigins); | 
 |  164  | 
 |  165   if (prefs->FindPreference(prefs::kDesktopNotificationDeniedOrigins)) | 
 |  166     denied_sites = | 
 |  167         prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins); | 
 |  168   else | 
 |  169     prefs->RegisterListPref(prefs::kDesktopNotificationDeniedOrigins); | 
 |  170  | 
 |  171   prefs_cache_ = new NotificationsPrefsCache(allowed_sites, denied_sites); | 
 |  172 } | 
 |  173  | 
 |  174 void DesktopNotificationService::GrantPermission(const GURL& origin) { | 
 |  175   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 
 |  176   PrefService* prefs = profile_->GetPrefs(); | 
 |  177   ListValue* allowed_sites = | 
 |  178       prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins); | 
 |  179   ListValue* denied_sites = | 
 |  180       prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins); | 
 |  181   // Remove from the black-list and add to the white-list. | 
 |  182   StringValue* value = new StringValue(origin.spec()); | 
 |  183   denied_sites->Remove(*value); | 
 |  184   allowed_sites->Append(value); | 
 |  185   prefs->ScheduleSavePersistentPrefs(); | 
 |  186  | 
 |  187   // Schedule a cache update on the IO thread. | 
 |  188   base::Thread* io_thread = g_browser_process->io_thread(); | 
 |  189   if (io_thread && io_thread->message_loop()) { | 
 |  190     io_thread->message_loop()->PostTask(FROM_HERE, | 
 |  191         NewRunnableMethod(prefs_cache_.get(), | 
 |  192                           &NotificationsPrefsCache::CacheAllowedOrigin, | 
 |  193                           origin)); | 
 |  194   } | 
 |  195 } | 
 |  196  | 
 |  197 void DesktopNotificationService::DenyPermission(const GURL& origin) { | 
 |  198   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 
 |  199   PrefService* prefs = profile_->GetPrefs(); | 
 |  200   ListValue* allowed_sites = | 
 |  201       prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins); | 
 |  202   ListValue* denied_sites = | 
 |  203       prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins); | 
 |  204   StringValue* value = new StringValue(origin.spec()); | 
 |  205   // Remove from the white-list and add to the black-list. | 
 |  206   allowed_sites->Remove(*value); | 
 |  207   denied_sites->Append(value); | 
 |  208   prefs->ScheduleSavePersistentPrefs(); | 
 |  209  | 
 |  210   // Schedule a cache update on the IO thread. | 
 |  211   base::Thread* io_thread = g_browser_process->io_thread(); | 
 |  212   if (io_thread && io_thread->message_loop()) { | 
 |  213     io_thread->message_loop()->PostTask(FROM_HERE, | 
 |  214         NewRunnableMethod(prefs_cache_.get(), | 
 |  215                           &NotificationsPrefsCache::CacheDeniedOrigin, | 
 |  216                           origin)); | 
 |  217   } | 
 |  218 } | 
 |  219  | 
 |  220 void DesktopNotificationService::RequestPermission( | 
 |  221     const GURL& origin, int callback_context) { | 
 |  222   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 
 |  223   // Show an info bar requesting permission. | 
 |  224   Browser* browser = BrowserList::GetLastActive(); | 
 |  225   if (!browser) { | 
 |  226     // Reached during ui tests. | 
 |  227     return; | 
 |  228   } | 
 |  229   TabContents* tab = browser->GetSelectedTabContents(); | 
 |  230   if (!tab) | 
 |  231     return; | 
 |  232   tab->AddInfoBar(new NotificationPermissionInfoBarDelegate(tab, origin, | 
 |  233                                                             callback_context)); | 
 |  234 } | 
| OLD | NEW |