| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/public/browser/notification_registrar.h" | 5 #include "content/public/browser/notification_registrar.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 NotificationRegistrar::NotificationRegistrar() { | 30 NotificationRegistrar::NotificationRegistrar() { |
| 31 // Force the NotificationService to be constructed (if it isn't already). | 31 // Force the NotificationService to be constructed (if it isn't already). |
| 32 // This ensures the NotificationService will be registered on the | 32 // This ensures the NotificationService will be registered on the |
| 33 // AtExitManager before any objects which access it via NotificationRegistrar. | 33 // AtExitManager before any objects which access it via NotificationRegistrar. |
| 34 // This in turn means it will be destroyed after these objects, so they will | 34 // This in turn means it will be destroyed after these objects, so they will |
| 35 // never try to access the NotificationService after it's been destroyed. | 35 // never try to access the NotificationService after it's been destroyed. |
| 36 NotificationServiceImpl::current(); | 36 NotificationServiceImpl::current(); |
| 37 // It is OK to create a NotificationRegistrar instance on one thread and then | 37 // It is OK to create a NotificationRegistrar instance on one thread and then |
| 38 // use it (exclusively) on another, so we detach from the initial thread. | 38 // use it (exclusively) on another, so we detach from the initial thread. |
| 39 DetachFromThread(); | 39 DETACH_FROM_SEQUENCE(sequence_checker_); |
| 40 } | 40 } |
| 41 | 41 |
| 42 NotificationRegistrar::~NotificationRegistrar() { | 42 NotificationRegistrar::~NotificationRegistrar() { |
| 43 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 43 RemoveAll(); | 44 RemoveAll(); |
| 44 } | 45 } |
| 45 | 46 |
| 46 void NotificationRegistrar::Add(NotificationObserver* observer, | 47 void NotificationRegistrar::Add(NotificationObserver* observer, |
| 47 int type, | 48 int type, |
| 48 const NotificationSource& source) { | 49 const NotificationSource& source) { |
| 49 DCHECK(CalledOnValidThread()); | 50 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 50 DCHECK(!IsRegistered(observer, type, source)) << "Duplicate registration."; | 51 DCHECK(!IsRegistered(observer, type, source)) << "Duplicate registration."; |
| 51 | 52 |
| 52 Record record = { observer, type, source }; | 53 Record record = { observer, type, source }; |
| 53 registered_.push_back(record); | 54 registered_.push_back(record); |
| 54 | 55 |
| 55 NotificationServiceImpl::current()->AddObserver(observer, type, source); | 56 NotificationServiceImpl::current()->AddObserver(observer, type, source); |
| 56 } | 57 } |
| 57 | 58 |
| 58 void NotificationRegistrar::Remove(NotificationObserver* observer, | 59 void NotificationRegistrar::Remove(NotificationObserver* observer, |
| 59 int type, | 60 int type, |
| 60 const NotificationSource& source) { | 61 const NotificationSource& source) { |
| 61 DCHECK(CalledOnValidThread()); | 62 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 62 | 63 |
| 63 Record record = { observer, type, source }; | 64 Record record = { observer, type, source }; |
| 64 RecordVector::iterator found = std::find( | 65 RecordVector::iterator found = std::find( |
| 65 registered_.begin(), registered_.end(), record); | 66 registered_.begin(), registered_.end(), record); |
| 66 DCHECK(found != registered_.end()); | 67 DCHECK(found != registered_.end()); |
| 67 | 68 |
| 68 registered_.erase(found); | 69 registered_.erase(found); |
| 69 | 70 |
| 70 // This can be nullptr if our owner outlives the NotificationService, e.g. if | 71 // This can be nullptr if our owner outlives the NotificationService, e.g. if |
| 71 // our owner is a Singleton. | 72 // our owner is a Singleton. |
| 72 NotificationServiceImpl* service = NotificationServiceImpl::current(); | 73 NotificationServiceImpl* service = NotificationServiceImpl::current(); |
| 73 if (service) | 74 if (service) |
| 74 service->RemoveObserver(observer, type, source); | 75 service->RemoveObserver(observer, type, source); |
| 75 } | 76 } |
| 76 | 77 |
| 77 void NotificationRegistrar::RemoveAll() { | 78 void NotificationRegistrar::RemoveAll() { |
| 78 CHECK(CalledOnValidThread()); | 79 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 79 // Early-exit if no registrations, to avoid calling | 80 // Early-exit if no registrations, to avoid calling |
| 80 // NotificationService::current. If we've constructed an object with a | 81 // NotificationService::current. If we've constructed an object with a |
| 81 // NotificationRegistrar member, but haven't actually used the notification | 82 // NotificationRegistrar member, but haven't actually used the notification |
| 82 // service, and we reach prgram exit, then calling current() below could try | 83 // service, and we reach prgram exit, then calling current() below could try |
| 83 // to initialize the service's lazy TLS pointer during exit, which throws | 84 // to initialize the service's lazy TLS pointer during exit, which throws |
| 84 // wrenches at things. | 85 // wrenches at things. |
| 85 if (registered_.empty()) | 86 if (registered_.empty()) |
| 86 return; | 87 return; |
| 87 | 88 |
| 88 // This can be nullptr if our owner outlives the NotificationService, e.g. if | 89 // This can be nullptr if our owner outlives the NotificationService, e.g. if |
| 89 // our owner is a Singleton. | 90 // our owner is a Singleton. |
| 90 NotificationServiceImpl* service = NotificationServiceImpl::current(); | 91 NotificationServiceImpl* service = NotificationServiceImpl::current(); |
| 91 if (service) { | 92 if (service) { |
| 92 for (size_t i = 0; i < registered_.size(); i++) { | 93 for (size_t i = 0; i < registered_.size(); i++) { |
| 93 service->RemoveObserver(registered_[i].observer, | 94 service->RemoveObserver(registered_[i].observer, |
| 94 registered_[i].type, | 95 registered_[i].type, |
| 95 registered_[i].source); | 96 registered_[i].source); |
| 96 } | 97 } |
| 97 } | 98 } |
| 98 registered_.clear(); | 99 registered_.clear(); |
| 99 } | 100 } |
| 100 | 101 |
| 101 bool NotificationRegistrar::IsEmpty() const { | 102 bool NotificationRegistrar::IsEmpty() const { |
| 102 DCHECK(CalledOnValidThread()); | 103 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 103 return registered_.empty(); | 104 return registered_.empty(); |
| 104 } | 105 } |
| 105 | 106 |
| 106 bool NotificationRegistrar::IsRegistered(NotificationObserver* observer, | 107 bool NotificationRegistrar::IsRegistered(NotificationObserver* observer, |
| 107 int type, | 108 int type, |
| 108 const NotificationSource& source) { | 109 const NotificationSource& source) { |
| 109 DCHECK(CalledOnValidThread()); | 110 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 110 Record record = { observer, type, source }; | 111 Record record = { observer, type, source }; |
| 111 return std::find(registered_.begin(), registered_.end(), record) != | 112 return std::find(registered_.begin(), registered_.end(), record) != |
| 112 registered_.end(); | 113 registered_.end(); |
| 113 } | 114 } |
| 114 | 115 |
| 115 } // namespace content | 116 } // namespace content |
| OLD | NEW |