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 |