Index: content/browser/push_messaging/push_messaging_message_filter.cc |
diff --git a/content/browser/push_messaging/push_messaging_message_filter.cc b/content/browser/push_messaging/push_messaging_message_filter.cc |
index 5024d8ce33cd97c6151434280d68acc6c4fadd65..fc10ab1e58b155cf0513a3c352a6b58a06a86987 100644 |
--- a/content/browser/push_messaging/push_messaging_message_filter.cc |
+++ b/content/browser/push_messaging/push_messaging_message_filter.cc |
@@ -7,6 +7,7 @@ |
#include <string> |
#include "base/bind.h" |
+#include "base/bind_helpers.h" |
#include "base/logging.h" |
#include "base/metrics/histogram.h" |
#include "base/strings/string_number_conversions.h" |
@@ -28,41 +29,139 @@ const char kPushRegistrationIdServiceWorkerKey[] = "push_registration_id"; |
namespace { |
void RecordRegistrationStatus(PushRegistrationStatus status) { |
- // Called from both UI and IO threads. Slightly racy, but acceptable, see |
+ // Only called from IO thread, but would be acceptable (even though slightly |
+ // racy) to call from UI thread as well, see |
// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CWAXJJ1kJ |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", |
status, |
PUSH_REGISTRATION_STATUS_LAST + 1); |
} |
-const char kSenderIdServiceWorkerKey[] = |
- "push_sender_id"; |
+const char kSenderIdServiceWorkerKey[] = "push_sender_id"; |
} // namespace |
+struct PushMessagingMessageFilter::RegisterData { |
+ RegisterData(); |
+ RegisterData(const RegisterData& other) = default; |
+ bool FromDocument() const; |
+ int request_id; |
+ GURL requesting_origin; |
+ int64 service_worker_registration_id; |
+ // The following two members should only be read if FromDocument() is true. |
+ int render_frame_id; |
+ bool user_visible_only; |
+}; |
+ |
+ |
+// Inner core of this message filter which lives on the UI thread. |
+class PushMessagingMessageFilter::Core { |
+ public: |
+ Core(const base::WeakPtr<PushMessagingMessageFilter>& io_parent, |
+ int render_process_id); |
+ |
+ // Public Register methods on UI thread -------------------------------------- |
+ |
+ // Called via PostTask from IO thread. |
+ void RegisterOnUI(const RegisterData& data, const std::string& sender_id); |
+ |
+ // Public Unregister methods on UI thread ------------------------------------ |
+ |
+ // Called via PostTask from IO thread. |
+ void UnregisterFromService(int request_id, |
+ int64 service_worker_registration_id, |
+ const GURL& requesting_origin); |
+ |
+ // Public GetPermission methods on UI thread --------------------------------- |
+ |
+ // Called via PostTask from IO thread. |
+ void GetPermissionStatusOnUI(const GURL& requesting_origin, int request_id); |
+ |
+ // Public helper methods on UI thread ---------------------------------------- |
+ |
+ // Returns a push messaging service. May return null. |
+ PushMessagingService* service(); |
+ |
+ private: |
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
+ friend class base::DeleteHelper<Core>; |
+ |
+ ~Core(); |
+ |
+ // Private Register methods on UI thread ------------------------------------- |
+ |
+ void DidRegister(const RegisterData& data, |
+ const std::string& push_registration_id, |
+ PushRegistrationStatus status); |
+ |
+ // Private Unregister methods on UI thread ----------------------------------- |
+ |
+ void DidUnregisterFromService(int request_id, |
+ int64 service_worker_registration_id, |
+ PushUnregistrationStatus unregistration_status); |
+ |
+ // Private helper methods on UI thread --------------------------------------- |
+ |
+ void Send(IPC::Message* message); |
+ |
+ // Outer part of this message filter which lives on the IO thread. |
+ base::WeakPtr<PushMessagingMessageFilter> io_parent_; |
+ |
+ int render_process_id_; |
+ |
+ base::WeakPtrFactory<Core> weak_factory_ui_to_ui_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Core); |
+}; |
+ |
+ |
PushMessagingMessageFilter::RegisterData::RegisterData() |
: request_id(0), |
service_worker_registration_id(0), |
render_frame_id(ChildProcessHost::kInvalidUniqueID), |
- user_visible_only(false) {} |
+ user_visible_only(false) { |
+} |
bool PushMessagingMessageFilter::RegisterData::FromDocument() const { |
return render_frame_id != ChildProcessHost::kInvalidUniqueID; |
} |
+PushMessagingMessageFilter::Core::Core( |
+ const base::WeakPtr<PushMessagingMessageFilter>& io_parent, |
+ int render_process_id) |
+ : io_parent_(io_parent), |
+ render_process_id_(render_process_id), |
+ weak_factory_ui_to_ui_(this) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+} |
+ |
+PushMessagingMessageFilter::Core::~Core() {} |
+ |
PushMessagingMessageFilter::PushMessagingMessageFilter( |
int render_process_id, |
ServiceWorkerContextWrapper* service_worker_context) |
: BrowserMessageFilter(PushMessagingMsgStart), |
- render_process_id_(render_process_id), |
service_worker_context_(service_worker_context), |
- service_(NULL), |
- weak_factory_io_to_io_(this), |
- weak_factory_ui_to_ui_(this) { |
+ weak_factory_io_to_io_(this) { |
+ // Although this class is used only on the IO thread, it is constructed on UI. |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ // Normally, it would be unsafe to obtain a weak pointer from the UI thread, |
+ // but it's ok in the constructor since we can't be destroyed before our |
+ // constructor finishes. |
+ ui_core_.reset(new Core(weak_factory_io_to_io_.GetWeakPtr(), |
+ render_process_id)); |
+ PushMessagingService* push_service = ui_core_->service(); |
+ if (push_service) |
+ push_endpoint_ = push_service->GetPushEndpoint(); |
} |
PushMessagingMessageFilter::~PushMessagingMessageFilter() {} |
+void PushMessagingMessageFilter::OnDestruct() const { |
+ BrowserThread::DeleteOnIOThread::Destruct(this); |
+} |
+ |
bool PushMessagingMessageFilter::OnMessageReceived( |
const IPC::Message& message) { |
bool handled = true; |
@@ -81,6 +180,10 @@ bool PushMessagingMessageFilter::OnMessageReceived( |
return handled; |
} |
+// Register methods on both IO and UI threads, merged in order of use from |
+// PushMessagingMessageFilter and Core. |
+// ----------------------------------------------------------------------------- |
+ |
void PushMessagingMessageFilter::OnRegisterFromDocument( |
int render_frame_id, |
int request_id, |
@@ -89,27 +192,22 @@ void PushMessagingMessageFilter::OnRegisterFromDocument( |
int64 service_worker_registration_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
// TODO(mvanouwerkerk): Validate arguments? |
+ // TODO(peter): Persist |user_visible_only| in Service Worker storage. |
+ RegisterData data; |
+ data.request_id = request_id; |
+ data.service_worker_registration_id = service_worker_registration_id; |
+ data.render_frame_id = render_frame_id; |
+ data.user_visible_only = user_visible_only; |
+ |
ServiceWorkerRegistration* service_worker_registration = |
service_worker_context_->context()->GetLiveRegistration( |
service_worker_registration_id); |
- DCHECK(service_worker_registration); |
if (!service_worker_registration || |
!service_worker_registration->active_version()) { |
- PushRegistrationStatus status = PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER; |
- Send(new PushMessagingMsg_RegisterFromDocumentError(render_frame_id, |
- request_id, status)); |
- RecordRegistrationStatus(status); |
+ SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); |
return; |
} |
- |
- // TODO(peter): Persist |user_visible_only| in Service Worker storage. |
- |
- RegisterData data; |
- data.request_id = request_id; |
data.requesting_origin = service_worker_registration->pattern().GetOrigin(); |
- data.service_worker_registration_id = service_worker_registration_id; |
- data.render_frame_id = render_frame_id; |
- data.user_visible_only = user_visible_only; |
service_worker_context_->context()->storage()->StoreUserData( |
service_worker_registration_id, |
@@ -125,39 +223,21 @@ void PushMessagingMessageFilter::OnRegisterFromWorker( |
int request_id, |
int64 service_worker_registration_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- ServiceWorkerRegistration* service_worker_registration = |
- service_worker_context_->context()->GetLiveRegistration( |
- service_worker_registration_id); |
- DCHECK(service_worker_registration); |
- if (!service_worker_registration) |
- return; |
- |
RegisterData data; |
data.request_id = request_id; |
- data.requesting_origin = service_worker_registration->pattern().GetOrigin(); |
data.service_worker_registration_id = service_worker_registration_id; |
- // This sender_id will be ignored; instead it will be fetched from storage. |
- CheckForExistingRegistration(data, "" /* sender_id */); |
-} |
- |
-void PushMessagingMessageFilter::OnGetPermissionStatus( |
- int request_id, |
- int64 service_worker_registration_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
ServiceWorkerRegistration* service_worker_registration = |
service_worker_context_->context()->GetLiveRegistration( |
service_worker_registration_id); |
- DCHECK(service_worker_registration); |
- if (!service_worker_registration) |
+ if (!service_worker_registration) { |
+ SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); |
return; |
+ } |
+ data.requesting_origin = service_worker_registration->pattern().GetOrigin(); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&PushMessagingMessageFilter::GetPermissionStatusOnUI, |
- this, |
- service_worker_registration->pattern().GetOrigin(), |
- request_id)); |
+ // This sender_id will be ignored; instead it will be fetched from storage. |
+ CheckForExistingRegistration(data, std::string() /* sender_id */); |
} |
void PushMessagingMessageFilter::DidPersistSenderId( |
@@ -179,8 +259,7 @@ void PushMessagingMessageFilter::CheckForExistingRegistration( |
data.service_worker_registration_id, |
kPushRegistrationIdServiceWorkerKey, |
base::Bind(&PushMessagingMessageFilter::DidCheckForExistingRegistration, |
- weak_factory_io_to_io_.GetWeakPtr(), |
- data, sender_id)); |
+ weak_factory_io_to_io_.GetWeakPtr(), data, sender_id)); |
} |
void PushMessagingMessageFilter::DidCheckForExistingRegistration( |
@@ -190,11 +269,8 @@ void PushMessagingMessageFilter::DidCheckForExistingRegistration( |
ServiceWorkerStatusCode service_worker_status) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
if (service_worker_status == SERVICE_WORKER_OK) { |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&PushMessagingMessageFilter::SendRegisterSuccessOnUI, |
- this, data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, |
- push_registration_id)); |
+ SendRegisterSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, |
+ push_registration_id); |
return; |
} |
// TODO(johnme): The spec allows the register algorithm to reject with an |
@@ -205,8 +281,8 @@ void PushMessagingMessageFilter::DidCheckForExistingRegistration( |
if (data.FromDocument()) { |
BrowserThread::PostTask( |
BrowserThread::UI, FROM_HERE, |
- base::Bind(&PushMessagingMessageFilter::RegisterOnUI, |
- this, data, sender_id)); |
+ base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), |
+ data, sender_id)); |
} else { |
service_worker_context_->context()->storage()->GetUserData( |
data.service_worker_registration_id, |
@@ -227,67 +303,58 @@ void PushMessagingMessageFilter::DidGetSenderIdFromStorage( |
} |
BrowserThread::PostTask( |
BrowserThread::UI, FROM_HERE, |
- base::Bind(&PushMessagingMessageFilter::RegisterOnUI, |
- this, data, sender_id)); |
+ base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), |
+ data, sender_id)); |
} |
-void PushMessagingMessageFilter::RegisterOnUI( |
- const RegisterData& data, |
+void PushMessagingMessageFilter::Core::RegisterOnUI( |
+ const PushMessagingMessageFilter::RegisterData& data, |
const std::string& sender_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- if (!service()) { |
- SendRegisterError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); |
+ PushMessagingService* push_service = service(); |
+ if (!push_service) { |
+ // TODO(johnme): Prevent websites from detecting incognito mode. |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&PushMessagingMessageFilter::SendRegisterError, io_parent_, |
+ data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); |
return; |
} |
if (data.FromDocument()) { |
- service()->RegisterFromDocument( |
+ push_service->RegisterFromDocument( |
data.requesting_origin, data.service_worker_registration_id, sender_id, |
render_process_id_, data.render_frame_id, data.user_visible_only, |
- base::Bind(&PushMessagingMessageFilter::DidRegister, |
- weak_factory_ui_to_ui_.GetWeakPtr(), data)); |
+ base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(), |
+ data)); |
} else { |
- service()->RegisterFromWorker( |
+ push_service->RegisterFromWorker( |
data.requesting_origin, data.service_worker_registration_id, sender_id, |
- base::Bind(&PushMessagingMessageFilter::DidRegister, |
- weak_factory_ui_to_ui_.GetWeakPtr(), data)); |
+ base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(), |
+ data)); |
} |
} |
-void PushMessagingMessageFilter::GetPermissionStatusOnUI( |
- const GURL& requesting_origin, |
- int request_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- if (!service()) { |
- Send(new PushMessagingMsg_GetPermissionStatusError(request_id)); |
- return; |
- } |
- GURL embedding_origin = requesting_origin; |
- blink::WebPushPermissionStatus permission_status = |
- service()->GetPermissionStatus(requesting_origin, embedding_origin); |
- Send(new PushMessagingMsg_GetPermissionStatusSuccess(request_id, |
- permission_status)); |
-} |
- |
-void PushMessagingMessageFilter::DidRegister( |
+void PushMessagingMessageFilter::Core::DidRegister( |
const RegisterData& data, |
const std::string& push_registration_id, |
PushRegistrationStatus status) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
if (status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE) { |
- GURL push_endpoint(service()->GetPushEndpoint()); |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
base::Bind(&PushMessagingMessageFilter::PersistRegistrationOnIO, |
- this, data, push_endpoint, push_registration_id)); |
+ io_parent_, data, push_registration_id)); |
} else { |
- SendRegisterError(data, status); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&PushMessagingMessageFilter::SendRegisterError, io_parent_, |
+ data, status)); |
} |
} |
void PushMessagingMessageFilter::PersistRegistrationOnIO( |
const RegisterData& data, |
- const GURL& push_endpoint, |
const std::string& push_registration_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
service_worker_context_->context()->storage()->StoreUserData( |
@@ -297,19 +364,18 @@ void PushMessagingMessageFilter::PersistRegistrationOnIO( |
push_registration_id, |
base::Bind(&PushMessagingMessageFilter::DidPersistRegistrationOnIO, |
weak_factory_io_to_io_.GetWeakPtr(), |
- data, push_endpoint, push_registration_id)); |
+ data, push_registration_id)); |
} |
void PushMessagingMessageFilter::DidPersistRegistrationOnIO( |
const RegisterData& data, |
- const GURL& push_endpoint, |
const std::string& push_registration_id, |
ServiceWorkerStatusCode service_worker_status) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
if (service_worker_status == SERVICE_WORKER_OK) { |
SendRegisterSuccess(data, |
PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE, |
- push_endpoint, push_registration_id); |
+ push_registration_id); |
} else { |
// TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count. |
SendRegisterError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); |
@@ -318,13 +384,14 @@ void PushMessagingMessageFilter::DidPersistRegistrationOnIO( |
void PushMessagingMessageFilter::SendRegisterError( |
const RegisterData& data, PushRegistrationStatus status) { |
- // May be called from both IO and UI threads. |
+ // Only called from IO thread, but would be safe to call from UI thread. |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
if (data.FromDocument()) { |
Send(new PushMessagingMsg_RegisterFromDocumentError( |
- data.render_frame_id, data.request_id, status)); |
+ data.render_frame_id, data.request_id, status)); |
} else { |
Send(new PushMessagingMsg_RegisterFromWorkerError( |
- data.request_id, status)); |
+ data.request_id, status)); |
} |
RecordRegistrationStatus(status); |
} |
@@ -332,28 +399,28 @@ void PushMessagingMessageFilter::SendRegisterError( |
void PushMessagingMessageFilter::SendRegisterSuccess( |
const RegisterData& data, |
PushRegistrationStatus status, |
- const GURL& push_endpoint, |
const std::string& push_registration_id) { |
- // May be called from both IO and UI threads. |
+ // Only called from IO thread, but would be safe to call from UI thread. |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ if (push_endpoint_.is_empty()) { |
+ // TODO(johnme): Prevent websites from detecting incognito mode. |
+ SendRegisterError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); |
+ return; |
+ } |
if (data.FromDocument()) { |
Send(new PushMessagingMsg_RegisterFromDocumentSuccess( |
data.render_frame_id, |
- data.request_id, push_endpoint, push_registration_id)); |
+ data.request_id, push_endpoint_, push_registration_id)); |
} else { |
Send(new PushMessagingMsg_RegisterFromWorkerSuccess( |
- data.request_id, push_endpoint, push_registration_id)); |
+ data.request_id, push_endpoint_, push_registration_id)); |
} |
RecordRegistrationStatus(status); |
} |
-void PushMessagingMessageFilter::SendRegisterSuccessOnUI( |
- const RegisterData& data, |
- PushRegistrationStatus status, |
- const std::string& push_registration_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- GURL push_endpoint(service()->GetPushEndpoint()); |
- SendRegisterSuccess(data, status, push_endpoint, push_registration_id); |
-} |
+// Unregister methods on both IO and UI threads, merged in order of use from |
+// PushMessagingMessageFilter and Core. |
+// ----------------------------------------------------------------------------- |
void PushMessagingMessageFilter::OnUnregister( |
int request_id, int64 service_worker_registration_id) { |
@@ -361,9 +428,10 @@ void PushMessagingMessageFilter::OnUnregister( |
ServiceWorkerRegistration* service_worker_registration = |
service_worker_context_->context()->GetLiveRegistration( |
service_worker_registration_id); |
- DCHECK(service_worker_registration); |
- if (!service_worker_registration) |
+ if (!service_worker_registration) { |
+ DidUnregister(request_id, PUSH_UNREGISTRATION_STATUS_UNKNOWN_ERROR); |
return; |
+ } |
service_worker_context_->context()->storage()->GetUserData( |
service_worker_registration_id, |
@@ -387,11 +455,9 @@ void PushMessagingMessageFilter::DoUnregister( |
case SERVICE_WORKER_OK: |
BrowserThread::PostTask( |
BrowserThread::UI, FROM_HERE, |
- base::Bind(&PushMessagingMessageFilter::UnregisterFromService, |
- this, |
- request_id, |
- service_worker_registration_id, |
- requesting_origin)); |
+ base::Bind(&Core::UnregisterFromService, |
+ base::Unretained(ui_core_.get()), request_id, |
+ service_worker_registration_id, requesting_origin)); |
return; |
case SERVICE_WORKER_ERROR_NOT_FOUND: |
// We did not find a registration, stop here and notify the renderer that |
@@ -421,26 +487,29 @@ void PushMessagingMessageFilter::DoUnregister( |
} |
} |
-void PushMessagingMessageFilter::UnregisterFromService( |
+void PushMessagingMessageFilter::Core::UnregisterFromService( |
int request_id, |
int64 service_worker_registration_id, |
const GURL& requesting_origin) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- if (!service()) { |
- DidUnregister(request_id, PUSH_UNREGISTRATION_STATUS_UNKNOWN_ERROR); |
+ PushMessagingService* push_service = service(); |
+ if (!push_service) { |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&PushMessagingMessageFilter::DidUnregister, io_parent_, |
+ request_id, PUSH_UNREGISTRATION_STATUS_UNKNOWN_ERROR)); |
return; |
} |
- service()->Unregister( |
+ push_service->Unregister( |
requesting_origin, service_worker_registration_id, |
false /* retry_on_failure */, |
- base::Bind(&PushMessagingMessageFilter::DidUnregisterFromService, |
+ base::Bind(&Core::DidUnregisterFromService, |
weak_factory_ui_to_ui_.GetWeakPtr(), |
- request_id, |
- service_worker_registration_id)); |
+ request_id, service_worker_registration_id)); |
} |
-void PushMessagingMessageFilter::DidUnregisterFromService( |
+void PushMessagingMessageFilter::Core::DidUnregisterFromService( |
int request_id, |
int64 service_worker_registration_id, |
PushUnregistrationStatus unregistration_status) { |
@@ -455,24 +524,52 @@ void PushMessagingMessageFilter::DidUnregisterFromService( |
case PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED: |
case PUSH_UNREGISTRATION_STATUS_NETWORK_ERROR: |
case PUSH_UNREGISTRATION_STATUS_UNKNOWN_ERROR: |
- DidUnregister(request_id, unregistration_status); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&PushMessagingMessageFilter::DidUnregister, io_parent_, |
+ request_id, unregistration_status)); |
return; |
} |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
- base::Bind(&PushMessagingMessageFilter::ClearRegistrationData, |
- this, |
- service_worker_registration_id, |
- base::Bind(&PushMessagingMessageFilter::DidUnregister, |
- weak_factory_io_to_io_.GetWeakPtr(), |
- request_id, |
- unregistration_status))); |
+ base::Bind(&PushMessagingMessageFilter::ClearRegistrationData, io_parent_, |
+ request_id, service_worker_registration_id, |
+ unregistration_status)); |
+} |
+ |
+void PushMessagingMessageFilter::ClearRegistrationData( |
+ int request_id, |
+ int64 service_worker_registration_id, |
+ PushUnregistrationStatus unregistration_status) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ service_worker_context_->context()->storage()->ClearUserData( |
+ service_worker_registration_id, |
+ kPushRegistrationIdServiceWorkerKey, |
+ base::Bind(&PushMessagingMessageFilter::DidClearRegistrationData, |
+ weak_factory_io_to_io_.GetWeakPtr(), |
+ request_id, unregistration_status)); |
+} |
+ |
+void PushMessagingMessageFilter::DidClearRegistrationData( |
+ int request_id, |
+ PushUnregistrationStatus unregistration_status, |
+ ServiceWorkerStatusCode service_worker_status) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ DCHECK(service_worker_status == SERVICE_WORKER_OK) |
+ << "Got unexpected error code: " << service_worker_status |
+ << " " << ServiceWorkerStatusToString(service_worker_status); |
+ |
+ DidUnregister(request_id, unregistration_status); |
} |
void PushMessagingMessageFilter::DidUnregister( |
int request_id, |
PushUnregistrationStatus unregistration_status) { |
+ // Only called from IO thread, but would be safe to call from UI thread. |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
switch (unregistration_status) { |
case PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTER: |
case PUSH_UNREGISTRATION_STATUS_SUCCESS_WILL_RETRY_NETWORK_ERROR: |
@@ -483,19 +580,21 @@ void PushMessagingMessageFilter::DidUnregister( |
return; |
case PUSH_UNREGISTRATION_STATUS_NETWORK_ERROR: |
Send(new PushMessagingMsg_UnregisterError( |
- request_id, |
- blink::WebPushError::ErrorTypeNetwork, |
+ request_id, blink::WebPushError::ErrorTypeNetwork, |
"Failed to connect to the push server.")); |
return; |
case PUSH_UNREGISTRATION_STATUS_UNKNOWN_ERROR: |
Send(new PushMessagingMsg_UnregisterError( |
- request_id, |
- blink::WebPushError::ErrorTypeUnknown, |
+ request_id, blink::WebPushError::ErrorTypeUnknown, |
"Unexpected error while trying to unregister from the push server.")); |
return; |
} |
} |
+// GetRegistration methods on both IO and UI threads, merged in order of use |
+// from PushMessagingMessageFilter and Core. |
+// ----------------------------------------------------------------------------- |
+ |
void PushMessagingMessageFilter::OnGetRegistration( |
int request_id, |
int64 service_worker_registration_id) { |
@@ -505,8 +604,7 @@ void PushMessagingMessageFilter::OnGetRegistration( |
service_worker_registration_id, |
kPushRegistrationIdServiceWorkerKey, |
base::Bind(&PushMessagingMessageFilter::DidGetRegistration, |
- weak_factory_io_to_io_.GetWeakPtr(), |
- request_id)); |
+ weak_factory_io_to_io_.GetWeakPtr(), request_id)); |
} |
void PushMessagingMessageFilter::DidGetRegistration( |
@@ -518,11 +616,15 @@ void PushMessagingMessageFilter::DidGetRegistration( |
PUSH_GETREGISTRATION_STATUS_SERVICE_WORKER_ERROR; |
switch (service_worker_status) { |
case SERVICE_WORKER_OK: |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind( |
- &PushMessagingMessageFilter::SendGetRegistrationSuccessOnUI, |
- this, request_id, push_registration_id)); |
+ if (push_endpoint_.is_empty()) { |
+ // TODO(johnme): Prevent websites from detecting incognito mode. |
+ Send(new PushMessagingMsg_GetRegistrationError( |
+ request_id, PUSH_GETREGISTRATION_STATUS_SERVICE_WORKER_ERROR)); |
+ return; |
+ } |
+ Send(new PushMessagingMsg_GetRegistrationSuccess(request_id, |
+ push_endpoint_, |
+ push_registration_id)); |
return; |
case SERVICE_WORKER_ERROR_NOT_FOUND: |
get_status = PUSH_GETREGISTRATION_STATUS_REGISTRATION_NOT_FOUND; |
@@ -550,50 +652,69 @@ void PushMessagingMessageFilter::DidGetRegistration( |
// TODO(johnme): RecordGetRegistrationStatus(status); ? |
} |
-void PushMessagingMessageFilter::SendGetRegistrationSuccessOnUI( |
- int request_id, |
- const std::string& push_registration_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- GURL push_endpoint(service()->GetPushEndpoint()); |
- Send(new PushMessagingMsg_GetRegistrationSuccess(request_id, push_endpoint, |
- push_registration_id)); |
-} |
+// GetPermission methods on both IO and UI threads, merged in order of use from |
+// PushMessagingMessageFilter and Core. |
+// ----------------------------------------------------------------------------- |
-void PushMessagingMessageFilter::ClearRegistrationData( |
- int64 service_worker_registration_id, |
- const base::Closure& closure) { |
+void PushMessagingMessageFilter::OnGetPermissionStatus( |
+ int request_id, |
+ int64 service_worker_registration_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ ServiceWorkerRegistration* service_worker_registration = |
+ service_worker_context_->context()->GetLiveRegistration( |
+ service_worker_registration_id); |
+ if (!service_worker_registration) { |
+ Send(new PushMessagingMsg_GetPermissionStatusError(request_id)); |
+ return; |
+ } |
- service_worker_context_->context()->storage()->ClearUserData( |
- service_worker_registration_id, |
- kPushRegistrationIdServiceWorkerKey, |
- base::Bind(&PushMessagingMessageFilter::DidClearRegistrationData, |
- weak_factory_io_to_io_.GetWeakPtr(), |
- closure)); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&Core::GetPermissionStatusOnUI, |
+ base::Unretained(ui_core_.get()), |
+ service_worker_registration->pattern().GetOrigin(), |
+ request_id)); |
} |
-void PushMessagingMessageFilter::DidClearRegistrationData( |
- const base::Closure& closure, |
- ServiceWorkerStatusCode service_worker_status) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+void PushMessagingMessageFilter::Core::GetPermissionStatusOnUI( |
+ const GURL& requesting_origin, |
+ int request_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ PushMessagingService* push_service = service(); |
+ if (!push_service) { |
+ // TODO(johnme): Prevent websites from detecting incognito mode. |
+ Send(new PushMessagingMsg_GetPermissionStatusError(request_id)); |
+ return; |
+ } |
+ GURL embedding_origin = requesting_origin; |
+ blink::WebPushPermissionStatus permission_status = |
+ push_service->GetPermissionStatus(requesting_origin, embedding_origin); |
+ Send(new PushMessagingMsg_GetPermissionStatusSuccess(request_id, |
+ permission_status)); |
+} |
- DCHECK(service_worker_status == SERVICE_WORKER_OK) |
- << "Got unexpected error code: " << service_worker_status |
- << " " << ServiceWorkerStatusToString(service_worker_status); |
+// Helper methods on both IO and UI threads, merged from |
+// PushMessagingMessageFilter and Core. |
+// ----------------------------------------------------------------------------- |
- closure.Run(); |
+void PushMessagingMessageFilter::Core::Send(IPC::Message* message) { |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&PushMessagingMessageFilter::SendIPC, io_parent_, |
+ base::Passed(make_scoped_ptr(message)))); |
} |
-PushMessagingService* PushMessagingMessageFilter::service() { |
+void PushMessagingMessageFilter::SendIPC(scoped_ptr<IPC::Message> message) { |
+ Send(message.release()); |
+} |
+ |
+PushMessagingService* PushMessagingMessageFilter::Core::service() { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- if (!service_) { |
- RenderProcessHost* process_host = |
- RenderProcessHost::FromID(render_process_id_); |
- if (!process_host) |
- return NULL; |
- service_ = process_host->GetBrowserContext()->GetPushMessagingService(); |
- } |
- return service_; |
+ RenderProcessHost* process_host = |
+ RenderProcessHost::FromID(render_process_id_); |
+ return process_host |
+ ? process_host->GetBrowserContext()->GetPushMessagingService() |
+ : nullptr; |
} |
} // namespace content |