| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/child/push_messaging/push_provider.h" | 5 #include "content/child/push_messaging/push_provider.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind_helpers.h" |
| 10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 11 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 12 #include "base/stl_util.h" | |
| 13 #include "base/threading/thread_local.h" | 13 #include "base/threading/thread_local.h" |
| 14 #include "content/child/push_messaging/push_dispatcher.h" | 14 #include "content/child/child_thread_impl.h" |
| 15 #include "content/child/service_worker/web_service_worker_registration_impl.h" | 15 #include "content/child/service_worker/web_service_worker_registration_impl.h" |
| 16 #include "content/child/thread_safe_sender.h" | |
| 17 #include "content/common/push_messaging_messages.h" | |
| 18 #include "content/public/common/child_process_host.h" | 16 #include "content/public/common/child_process_host.h" |
| 19 #include "content/public/common/push_subscription_options.h" | 17 #include "content/public/common/push_subscription_options.h" |
| 18 #include "services/service_manager/public/cpp/interface_provider.h" |
| 20 #include "third_party/WebKit/public/platform/WebString.h" | 19 #include "third_party/WebKit/public/platform/WebString.h" |
| 21 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
ription.h" | 20 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
ription.h" |
| 22 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
riptionOptions.h" | 21 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
riptionOptions.h" |
| 23 | 22 |
| 24 namespace content { | 23 namespace content { |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 27 int CurrentWorkerId() { | 26 int CurrentWorkerId() { |
| 28 return WorkerThread::GetCurrentId(); | 27 return WorkerThread::GetCurrentId(); |
| 29 } | 28 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 break; | 65 break; |
| 67 } | 66 } |
| 68 return blink::WebPushError( | 67 return blink::WebPushError( |
| 69 error_type, | 68 error_type, |
| 70 blink::WebString::fromUTF8(PushRegistrationStatusToString(status))); | 69 blink::WebString::fromUTF8(PushRegistrationStatusToString(status))); |
| 71 } | 70 } |
| 72 | 71 |
| 73 static base::LazyInstance<base::ThreadLocalPointer<PushProvider>>::Leaky | 72 static base::LazyInstance<base::ThreadLocalPointer<PushProvider>>::Leaky |
| 74 g_push_provider_tls = LAZY_INSTANCE_INITIALIZER; | 73 g_push_provider_tls = LAZY_INSTANCE_INITIALIZER; |
| 75 | 74 |
| 76 PushProvider::PushProvider(ThreadSafeSender* thread_safe_sender, | 75 PushProvider::PushProvider(const scoped_refptr<base::SingleThreadTaskRunner>& |
| 77 PushDispatcher* push_dispatcher) | 76 main_thread_task_runner) { |
| 78 : thread_safe_sender_(thread_safe_sender), | 77 DCHECK(main_thread_task_runner); |
| 79 push_dispatcher_(push_dispatcher) { | 78 |
| 79 auto request = mojo::MakeRequest(&push_messaging_manager_); |
| 80 if (!main_thread_task_runner->BelongsToCurrentThread()) { |
| 81 main_thread_task_runner->PostTask( |
| 82 FROM_HERE, |
| 83 base::Bind(&PushProvider::GetInterface, base::Passed(&request))); |
| 84 } else { |
| 85 GetInterface(std::move(request)); |
| 86 } |
| 80 g_push_provider_tls.Pointer()->Set(this); | 87 g_push_provider_tls.Pointer()->Set(this); |
| 81 } | 88 } |
| 82 | 89 |
| 83 PushProvider::~PushProvider() { | 90 PushProvider::~PushProvider() { |
| 84 g_push_provider_tls.Pointer()->Set(nullptr); | 91 g_push_provider_tls.Pointer()->Set(nullptr); |
| 85 } | 92 } |
| 86 | 93 |
| 87 PushProvider* PushProvider::ThreadSpecificInstance( | 94 PushProvider* PushProvider::ThreadSpecificInstance( |
| 88 ThreadSafeSender* thread_safe_sender, | 95 const scoped_refptr<base::SingleThreadTaskRunner>& |
| 89 PushDispatcher* push_dispatcher) { | 96 main_thread_task_runner) { |
| 90 if (g_push_provider_tls.Pointer()->Get()) | 97 if (g_push_provider_tls.Pointer()->Get()) |
| 91 return g_push_provider_tls.Pointer()->Get(); | 98 return g_push_provider_tls.Pointer()->Get(); |
| 92 | 99 |
| 93 PushProvider* provider = | 100 PushProvider* provider = new PushProvider(main_thread_task_runner); |
| 94 new PushProvider(thread_safe_sender, push_dispatcher); | |
| 95 if (CurrentWorkerId()) | 101 if (CurrentWorkerId()) |
| 96 WorkerThread::AddObserver(provider); | 102 WorkerThread::AddObserver(provider); |
| 97 return provider; | 103 return provider; |
| 98 } | 104 } |
| 99 | 105 |
| 106 // static |
| 107 void PushProvider::GetInterface(mojom::PushMessagingRequest request) { |
| 108 if (ChildThreadImpl::current()) { |
| 109 ChildThreadImpl::current()->GetRemoteInterfaces()->GetInterface( |
| 110 std::move(request)); |
| 111 } |
| 112 } |
| 113 |
| 100 void PushProvider::WillStopCurrentWorkerThread() { | 114 void PushProvider::WillStopCurrentWorkerThread() { |
| 101 delete this; | 115 delete this; |
| 102 } | 116 } |
| 103 | 117 |
| 104 void PushProvider::subscribe( | 118 void PushProvider::subscribe( |
| 105 blink::WebServiceWorkerRegistration* service_worker_registration, | 119 blink::WebServiceWorkerRegistration* service_worker_registration, |
| 106 const blink::WebPushSubscriptionOptions& options, | 120 const blink::WebPushSubscriptionOptions& options, |
| 107 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { | 121 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { |
| 108 DCHECK(service_worker_registration); | 122 DCHECK(service_worker_registration); |
| 109 DCHECK(callbacks); | 123 DCHECK(callbacks); |
| 110 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | 124 |
| 111 subscription_callbacks_.AddWithID(std::move(callbacks), request_id); | |
| 112 int64_t service_worker_registration_id = | 125 int64_t service_worker_registration_id = |
| 113 GetServiceWorkerRegistrationId(service_worker_registration); | 126 GetServiceWorkerRegistrationId(service_worker_registration); |
| 114 PushSubscriptionOptions content_options; | 127 PushSubscriptionOptions content_options; |
| 115 content_options.user_visible_only = options.userVisibleOnly; | 128 content_options.user_visible_only = options.userVisibleOnly; |
| 116 | 129 |
| 117 // Just treat the server key as a string of bytes and pass it to the push | 130 // Just treat the server key as a string of bytes and pass it to the push |
| 118 // service. | 131 // service. |
| 119 content_options.sender_info = options.applicationServerKey.latin1(); | 132 content_options.sender_info = options.applicationServerKey.latin1(); |
| 120 thread_safe_sender_->Send(new PushMessagingHostMsg_Subscribe( | 133 |
| 121 ChildProcessHost::kInvalidUniqueID, request_id, | 134 push_messaging_manager_->Subscribe( |
| 122 service_worker_registration_id, content_options)); | 135 ChildProcessHost::kInvalidUniqueID, service_worker_registration_id, |
| 136 content_options, |
| 137 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 138 // by |this|. |
| 139 base::Bind(&PushProvider::SubscribeCallback, base::Unretained(this), |
| 140 base::Passed(&callbacks))); |
| 141 } |
| 142 |
| 143 void PushProvider::SubscribeCallback( |
| 144 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks, |
| 145 content::PushRegistrationStatus status, |
| 146 const base::Optional<GURL>& endpoint, |
| 147 const base::Optional<content::PushSubscriptionOptions>& options, |
| 148 const base::Optional<std::vector<uint8_t>>& p256dh, |
| 149 const base::Optional<std::vector<uint8_t>>& auth) { |
| 150 if (!callbacks) { |
| 151 return; |
| 152 } |
| 153 |
| 154 if (status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE || |
| 155 status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE) { |
| 156 DCHECK(endpoint); |
| 157 DCHECK(options); |
| 158 DCHECK(p256dh); |
| 159 DCHECK(auth); |
| 160 |
| 161 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( |
| 162 endpoint.value(), options.value().user_visible_only, |
| 163 blink::WebString::fromLatin1(options.value().sender_info), |
| 164 p256dh.value(), auth.value())); |
| 165 } else { |
| 166 callbacks->onError(PushRegistrationStatusToWebPushError(status)); |
| 167 } |
| 123 } | 168 } |
| 124 | 169 |
| 125 void PushProvider::unsubscribe( | 170 void PushProvider::unsubscribe( |
| 126 blink::WebServiceWorkerRegistration* service_worker_registration, | 171 blink::WebServiceWorkerRegistration* service_worker_registration, |
| 127 std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) { | 172 std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) { |
| 128 DCHECK(service_worker_registration); | 173 DCHECK(service_worker_registration); |
| 129 DCHECK(callbacks); | 174 DCHECK(callbacks); |
| 130 | 175 |
| 131 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | |
| 132 unsubscribe_callbacks_.AddWithID(std::move(callbacks), request_id); | |
| 133 int64_t service_worker_registration_id = | 176 int64_t service_worker_registration_id = |
| 134 GetServiceWorkerRegistrationId(service_worker_registration); | 177 GetServiceWorkerRegistrationId(service_worker_registration); |
| 135 thread_safe_sender_->Send(new PushMessagingHostMsg_Unsubscribe( | 178 |
| 136 request_id, service_worker_registration_id)); | 179 push_messaging_manager_->Unsubscribe( |
| 180 service_worker_registration_id, |
| 181 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 182 // by |this|. |
| 183 base::Bind(&PushProvider::UnsubscribeCallback, base::Unretained(this), |
| 184 base::Passed(&callbacks))); |
| 185 } |
| 186 |
| 187 void PushProvider::UnsubscribeCallback( |
| 188 std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks, |
| 189 bool is_success, |
| 190 bool did_unsubscribe, |
| 191 blink::WebPushError::ErrorType error_type, |
| 192 const base::Optional<std::string>& error_message) { |
| 193 if (!callbacks) { |
| 194 return; |
| 195 } |
| 196 |
| 197 if (is_success) { |
| 198 callbacks->onSuccess(did_unsubscribe); |
| 199 } else { |
| 200 callbacks->onError(blink::WebPushError( |
| 201 error_type, blink::WebString::fromUTF8(error_message->c_str()))); |
| 202 } |
| 137 } | 203 } |
| 138 | 204 |
| 139 void PushProvider::getSubscription( | 205 void PushProvider::getSubscription( |
| 140 blink::WebServiceWorkerRegistration* service_worker_registration, | 206 blink::WebServiceWorkerRegistration* service_worker_registration, |
| 141 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { | 207 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { |
| 142 DCHECK(service_worker_registration); | 208 DCHECK(service_worker_registration); |
| 143 DCHECK(callbacks); | 209 DCHECK(callbacks); |
| 144 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | 210 |
| 145 subscription_callbacks_.AddWithID(std::move(callbacks), request_id); | |
| 146 int64_t service_worker_registration_id = | 211 int64_t service_worker_registration_id = |
| 147 GetServiceWorkerRegistrationId(service_worker_registration); | 212 GetServiceWorkerRegistrationId(service_worker_registration); |
| 148 thread_safe_sender_->Send(new PushMessagingHostMsg_GetSubscription( | 213 |
| 149 request_id, service_worker_registration_id)); | 214 push_messaging_manager_->GetSubscription( |
| 215 service_worker_registration_id, |
| 216 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 217 // by |this|. |
| 218 base::Bind(&PushProvider::GetSubscriptionCallback, base::Unretained(this), |
| 219 base::Passed(&callbacks))); |
| 220 } |
| 221 |
| 222 void PushProvider::GetSubscriptionCallback( |
| 223 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks, |
| 224 content::PushGetRegistrationStatus status, |
| 225 const base::Optional<GURL>& endpoint, |
| 226 const base::Optional<content::PushSubscriptionOptions>& options, |
| 227 const base::Optional<std::vector<uint8_t>>& p256dh, |
| 228 const base::Optional<std::vector<uint8_t>>& auth) { |
| 229 if (!callbacks) |
| 230 return; |
| 231 |
| 232 if (status == PUSH_GETREGISTRATION_STATUS_SUCCESS) { |
| 233 DCHECK(endpoint); |
| 234 DCHECK(options); |
| 235 DCHECK(p256dh); |
| 236 DCHECK(auth); |
| 237 |
| 238 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( |
| 239 endpoint.value(), options.value().user_visible_only, |
| 240 blink::WebString::fromLatin1(options.value().sender_info), |
| 241 p256dh.value(), auth.value())); |
| 242 } else { |
| 243 // We are only expecting an error if we can't find a registration. |
| 244 callbacks->onSuccess(nullptr); |
| 245 } |
| 150 } | 246 } |
| 151 | 247 |
| 152 void PushProvider::getPermissionStatus( | 248 void PushProvider::getPermissionStatus( |
| 153 blink::WebServiceWorkerRegistration* service_worker_registration, | 249 blink::WebServiceWorkerRegistration* service_worker_registration, |
| 154 const blink::WebPushSubscriptionOptions& options, | 250 const blink::WebPushSubscriptionOptions& options, |
| 155 std::unique_ptr<blink::WebPushPermissionStatusCallbacks> callbacks) { | 251 std::unique_ptr<blink::WebPushPermissionStatusCallbacks> callbacks) { |
| 156 DCHECK(service_worker_registration); | 252 DCHECK(service_worker_registration); |
| 157 DCHECK(callbacks); | 253 DCHECK(callbacks); |
| 158 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | 254 |
| 159 permission_status_callbacks_.AddWithID(std::move(callbacks), request_id); | |
| 160 int64_t service_worker_registration_id = | 255 int64_t service_worker_registration_id = |
| 161 GetServiceWorkerRegistrationId(service_worker_registration); | 256 GetServiceWorkerRegistrationId(service_worker_registration); |
| 162 thread_safe_sender_->Send(new PushMessagingHostMsg_GetPermissionStatus( | 257 |
| 163 request_id, service_worker_registration_id, options.userVisibleOnly)); | 258 push_messaging_manager_->GetPermissionStatus( |
| 259 service_worker_registration_id, options.userVisibleOnly, |
| 260 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 261 // by |this|. |
| 262 base::Bind(&PushProvider::GetPermissionStatusCallback, |
| 263 base::Unretained(this), base::Passed(&callbacks))); |
| 164 } | 264 } |
| 165 | 265 |
| 166 bool PushProvider::OnMessageReceived(const IPC::Message& message) { | 266 void PushProvider::GetPermissionStatusCallback( |
| 167 bool handled = true; | 267 std::unique_ptr<blink::WebPushPermissionStatusCallbacks> callbacks, |
| 168 IPC_BEGIN_MESSAGE_MAP(PushProvider, message) | 268 bool is_success, |
| 169 IPC_MESSAGE_HANDLER(PushMessagingMsg_SubscribeFromWorkerSuccess, | 269 blink::WebPushPermissionStatus status, |
| 170 OnSubscribeFromWorkerSuccess); | 270 blink::WebPushError::ErrorType error) { |
| 171 IPC_MESSAGE_HANDLER(PushMessagingMsg_SubscribeFromWorkerError, | |
| 172 OnSubscribeFromWorkerError); | |
| 173 IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeSuccess, | |
| 174 OnUnsubscribeSuccess); | |
| 175 IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeError, OnUnsubscribeError); | |
| 176 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetSubscriptionSuccess, | |
| 177 OnGetSubscriptionSuccess); | |
| 178 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetSubscriptionError, | |
| 179 OnGetSubscriptionError); | |
| 180 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusSuccess, | |
| 181 OnGetPermissionStatusSuccess); | |
| 182 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusError, | |
| 183 OnGetPermissionStatusError); | |
| 184 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 185 IPC_END_MESSAGE_MAP() | |
| 186 | |
| 187 return handled; | |
| 188 } | |
| 189 | |
| 190 void PushProvider::OnSubscribeFromWorkerSuccess( | |
| 191 int request_id, | |
| 192 const GURL& endpoint, | |
| 193 const PushSubscriptionOptions& options, | |
| 194 const std::vector<uint8_t>& p256dh, | |
| 195 const std::vector<uint8_t>& auth) { | |
| 196 blink::WebPushSubscriptionCallbacks* callbacks = | |
| 197 subscription_callbacks_.Lookup(request_id); | |
| 198 if (!callbacks) | 271 if (!callbacks) |
| 199 return; | 272 return; |
| 200 | 273 |
| 201 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( | 274 if (is_success) { |
| 202 endpoint, options.user_visible_only, | 275 callbacks->onSuccess(status); |
| 203 blink::WebString::fromLatin1(options.sender_info), p256dh, auth)); | 276 } else { |
| 204 | 277 std::string error_message; |
| 205 subscription_callbacks_.Remove(request_id); | 278 if (error == blink::WebPushError::ErrorTypeNotSupported) { |
| 206 } | 279 error_message = |
| 207 | 280 "Push subscriptions that don't enable userVisibleOnly are not " |
| 208 void PushProvider::OnSubscribeFromWorkerError(int request_id, | 281 "supported."; |
| 209 PushRegistrationStatus status) { | 282 } |
| 210 blink::WebPushSubscriptionCallbacks* callbacks = | 283 callbacks->onError( |
| 211 subscription_callbacks_.Lookup(request_id); | 284 blink::WebPushError(error, blink::WebString::fromUTF8(error_message))); |
| 212 if (!callbacks) | |
| 213 return; | |
| 214 | |
| 215 callbacks->onError(PushRegistrationStatusToWebPushError(status)); | |
| 216 | |
| 217 subscription_callbacks_.Remove(request_id); | |
| 218 } | |
| 219 | |
| 220 void PushProvider::OnUnsubscribeSuccess(int request_id, bool did_unsubscribe) { | |
| 221 blink::WebPushUnsubscribeCallbacks* callbacks = | |
| 222 unsubscribe_callbacks_.Lookup(request_id); | |
| 223 if (!callbacks) | |
| 224 return; | |
| 225 | |
| 226 callbacks->onSuccess(did_unsubscribe); | |
| 227 | |
| 228 unsubscribe_callbacks_.Remove(request_id); | |
| 229 } | |
| 230 | |
| 231 void PushProvider::OnUnsubscribeError(int request_id, | |
| 232 blink::WebPushError::ErrorType error_type, | |
| 233 const std::string& error_message) { | |
| 234 blink::WebPushUnsubscribeCallbacks* callbacks = | |
| 235 unsubscribe_callbacks_.Lookup(request_id); | |
| 236 if (!callbacks) | |
| 237 return; | |
| 238 | |
| 239 callbacks->onError(blink::WebPushError( | |
| 240 error_type, blink::WebString::fromUTF8(error_message))); | |
| 241 | |
| 242 unsubscribe_callbacks_.Remove(request_id); | |
| 243 } | |
| 244 | |
| 245 void PushProvider::OnGetSubscriptionSuccess( | |
| 246 int request_id, | |
| 247 const GURL& endpoint, | |
| 248 const PushSubscriptionOptions& options, | |
| 249 const std::vector<uint8_t>& p256dh, | |
| 250 const std::vector<uint8_t>& auth) { | |
| 251 blink::WebPushSubscriptionCallbacks* callbacks = | |
| 252 subscription_callbacks_.Lookup(request_id); | |
| 253 if (!callbacks) | |
| 254 return; | |
| 255 | |
| 256 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( | |
| 257 endpoint, options.user_visible_only, | |
| 258 blink::WebString::fromLatin1(options.sender_info), p256dh, auth)); | |
| 259 | |
| 260 subscription_callbacks_.Remove(request_id); | |
| 261 } | |
| 262 | |
| 263 void PushProvider::OnGetSubscriptionError(int request_id, | |
| 264 PushGetRegistrationStatus status) { | |
| 265 blink::WebPushSubscriptionCallbacks* callbacks = | |
| 266 subscription_callbacks_.Lookup(request_id); | |
| 267 if (!callbacks) | |
| 268 return; | |
| 269 | |
| 270 // We are only expecting an error if we can't find a registration. | |
| 271 callbacks->onSuccess(nullptr); | |
| 272 | |
| 273 subscription_callbacks_.Remove(request_id); | |
| 274 } | |
| 275 | |
| 276 void PushProvider::OnGetPermissionStatusSuccess( | |
| 277 int request_id, | |
| 278 blink::WebPushPermissionStatus status) { | |
| 279 blink::WebPushPermissionStatusCallbacks* callbacks = | |
| 280 permission_status_callbacks_.Lookup(request_id); | |
| 281 if (!callbacks) | |
| 282 return; | |
| 283 | |
| 284 callbacks->onSuccess(status); | |
| 285 | |
| 286 permission_status_callbacks_.Remove(request_id); | |
| 287 } | |
| 288 | |
| 289 void PushProvider::OnGetPermissionStatusError( | |
| 290 int request_id, | |
| 291 blink::WebPushError::ErrorType error) { | |
| 292 blink::WebPushPermissionStatusCallbacks* callbacks = | |
| 293 permission_status_callbacks_.Lookup(request_id); | |
| 294 if (!callbacks) | |
| 295 return; | |
| 296 | |
| 297 std::string error_message; | |
| 298 if (error == blink::WebPushError::ErrorTypeNotSupported) { | |
| 299 error_message = | |
| 300 "Push subscriptions that don't enable userVisibleOnly are not " | |
| 301 "supported."; | |
| 302 } | 285 } |
| 303 | |
| 304 callbacks->onError( | |
| 305 blink::WebPushError(error, blink::WebString::fromUTF8(error_message))); | |
| 306 | |
| 307 permission_status_callbacks_.Remove(request_id); | |
| 308 } | 286 } |
| 309 | 287 |
| 310 } // namespace content | 288 } // namespace content |
| OLD | NEW |