
This also makes it intercept all profiles' frame requests, which is more consistent with how it sniffs all profiles' subresources. Bug: 776589 Change-Id: I7b53f3f370b4d70e0335801a5b19f5b59be715a3 Reviewed-on: https://chromium-review.googlesource.com/831246 Commit-Queue: John Abd-El-Malek <jam@chromium.org> Reviewed-by: Doug Turner <dougt@chromium.org> Cr-Commit-Position: refs/heads/master@{#524829}
156 lines
5.2 KiB
C++
156 lines
5.2 KiB
C++
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "content/browser/notification_service_impl.h"
|
|
|
|
#include "base/lazy_instance.h"
|
|
#include "base/threading/thread_local.h"
|
|
#include "content/public/browser/notification_observer.h"
|
|
#include "content/public/browser/notification_types.h"
|
|
|
|
namespace content {
|
|
|
|
namespace {
|
|
|
|
base::LazyInstance<base::ThreadLocalPointer<NotificationServiceImpl>>::
|
|
DestructorAtExit lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER;
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
NotificationServiceImpl* NotificationServiceImpl::current() {
|
|
return lazy_tls_ptr.Pointer()->Get();
|
|
}
|
|
|
|
// static
|
|
NotificationService* NotificationService::current() {
|
|
return NotificationServiceImpl::current();
|
|
}
|
|
|
|
// static
|
|
NotificationService* NotificationService::Create() {
|
|
return new NotificationServiceImpl;
|
|
}
|
|
|
|
// static
|
|
bool NotificationServiceImpl::HasKey(const NotificationSourceMap& map,
|
|
const NotificationSource& source) {
|
|
return map.find(source.map_key()) != map.end();
|
|
}
|
|
|
|
NotificationServiceImpl::NotificationServiceImpl() {
|
|
DCHECK(current() == nullptr);
|
|
lazy_tls_ptr.Pointer()->Set(this);
|
|
}
|
|
|
|
void NotificationServiceImpl::AddObserver(NotificationObserver* observer,
|
|
int type,
|
|
const NotificationSource& source) {
|
|
// We have gotten some crashes where the observer pointer is NULL. The problem
|
|
// is that this happens when we actually execute a notification, so have no
|
|
// way of knowing who the bad observer was. We want to know when this happens
|
|
// in release mode so we know what code to blame the crash on (since this is
|
|
// guaranteed to crash later).
|
|
CHECK(observer);
|
|
|
|
NotificationObserverList* observer_list;
|
|
if (HasKey(observers_[type], source)) {
|
|
observer_list = observers_[type][source.map_key()];
|
|
} else {
|
|
observer_list = new NotificationObserverList;
|
|
observers_[type][source.map_key()] = observer_list;
|
|
}
|
|
|
|
observer_list->AddObserver(observer);
|
|
#ifndef NDEBUG
|
|
++observer_counts_[type];
|
|
#endif
|
|
}
|
|
|
|
void NotificationServiceImpl::RemoveObserver(NotificationObserver* observer,
|
|
int type,
|
|
const NotificationSource& source) {
|
|
// This is a very serious bug. An object is most likely being deleted on
|
|
// the wrong thread, and as a result another thread's NotificationServiceImpl
|
|
// has its deleted pointer in its map. A garbge object will be called in the
|
|
// future.
|
|
// NOTE: when this check shows crashes, use BrowserThread::DeleteOnIOThread or
|
|
// other variants as the trait on the object.
|
|
CHECK(HasKey(observers_[type], source));
|
|
|
|
NotificationObserverList* observer_list =
|
|
observers_[type][source.map_key()];
|
|
if (observer_list) {
|
|
observer_list->RemoveObserver(observer);
|
|
if (!observer_list->might_have_observers()) {
|
|
observers_[type].erase(source.map_key());
|
|
delete observer_list;
|
|
}
|
|
#ifndef NDEBUG
|
|
--observer_counts_[type];
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void NotificationServiceImpl::Notify(int type,
|
|
const NotificationSource& source,
|
|
const NotificationDetails& details) {
|
|
DCHECK_GT(type, NOTIFICATION_ALL) <<
|
|
"Allowed for observing, but not posting.";
|
|
|
|
// There's no particular reason for the order in which the different
|
|
// classes of observers get notified here.
|
|
|
|
// Notify observers of all types and all sources
|
|
if (HasKey(observers_[NOTIFICATION_ALL], AllSources()) &&
|
|
source != AllSources()) {
|
|
for (auto& observer : *observers_[NOTIFICATION_ALL][AllSources().map_key()])
|
|
observer.Observe(type, source, details);
|
|
}
|
|
|
|
// Notify observers of all types and the given source
|
|
if (HasKey(observers_[NOTIFICATION_ALL], source)) {
|
|
for (auto& observer : *observers_[NOTIFICATION_ALL][source.map_key()])
|
|
observer.Observe(type, source, details);
|
|
}
|
|
|
|
// Notify observers of the given type and all sources
|
|
if (HasKey(observers_[type], AllSources()) &&
|
|
source != AllSources()) {
|
|
for (auto& observer : *observers_[type][AllSources().map_key()])
|
|
observer.Observe(type, source, details);
|
|
}
|
|
|
|
// Notify observers of the given type and the given source
|
|
if (HasKey(observers_[type], source)) {
|
|
for (auto& observer : *observers_[type][source.map_key()])
|
|
observer.Observe(type, source, details);
|
|
}
|
|
}
|
|
|
|
|
|
NotificationServiceImpl::~NotificationServiceImpl() {
|
|
lazy_tls_ptr.Pointer()->Set(nullptr);
|
|
|
|
#ifndef NDEBUG
|
|
for (int i = 0; i < static_cast<int>(observer_counts_.size()); i++) {
|
|
if (observer_counts_[i] > 0) {
|
|
// This may not be completely fixable -- see
|
|
// http://code.google.com/p/chromium/issues/detail?id=11010 .
|
|
VLOG(1) << observer_counts_[i] << " notification observer(s) leaked "
|
|
"of notification type " << i;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for (int i = 0; i < static_cast<int>(observers_.size()); i++) {
|
|
NotificationSourceMap omap = observers_[i];
|
|
for (NotificationSourceMap::iterator it = omap.begin();
|
|
it != omap.end(); ++it)
|
|
delete it->second;
|
|
}
|
|
}
|
|
|
|
} // namespace content
|