Commit 65056ef2 authored by Hajime Hoshi's avatar Hajime Hoshi Committed by Commit Bot

RAII way for handling observers of NetworkStateNotifier

This CL changes how to manage observers of NetworkStateNotifier to use
handles in RAII way. Before this CL, we depended on the fact that
WebTaskRunner objects returned from TaskRunnerHelper::Get were always
same for the same execution context. Now we are trying to change the
fact and WebTaskRunnerImpl will always be created for each call.

This is part of the big CL for changing WebFrameSchedulerImpl::
*TaskRunner() to create WebTaskRunnerImpl anytime:
https://chromium-review.googlesource.com/c/chromium/src/+/704459

Bug: 762453
Change-Id: I5308e7cb0493d84c25e4da7f3562cd0fcff0f3af
Reviewed-on: https://chromium-review.googlesource.com/722859
Commit-Queue: Hajime Hoshi <hajimehoshi@chromium.org>
Reviewed-by: default avatarJosh Karlin <jkarlin@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#510012}
parent 5c5c4e4e
...@@ -524,7 +524,7 @@ class Document::NetworkStateObserver final ...@@ -524,7 +524,7 @@ class Document::NetworkStateObserver final
public: public:
explicit NetworkStateObserver(Document& document) explicit NetworkStateObserver(Document& document)
: ContextLifecycleObserver(&document) { : ContextLifecycleObserver(&document) {
GetNetworkStateNotifier().AddOnLineObserver( online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver(
this, this,
TaskRunnerHelper::Get(TaskType::kNetworking, GetExecutionContext())); TaskRunnerHelper::Get(TaskType::kNetworking, GetExecutionContext()));
} }
...@@ -545,11 +545,14 @@ class Document::NetworkStateObserver final ...@@ -545,11 +545,14 @@ class Document::NetworkStateObserver final
void UnregisterAsObserver(ExecutionContext* context) { void UnregisterAsObserver(ExecutionContext* context) {
DCHECK(context); DCHECK(context);
GetNetworkStateNotifier().RemoveOnLineObserver( online_observer_handle_ = nullptr;
this, TaskRunnerHelper::Get(TaskType::kNetworking, context));
} }
DEFINE_INLINE_VIRTUAL_TRACE() { ContextLifecycleObserver::Trace(visitor); } DEFINE_INLINE_VIRTUAL_TRACE() { ContextLifecycleObserver::Trace(visitor); }
private:
std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
online_observer_handle_;
}; };
Document* Document::Create(const Document& document) { Document* Document::Create(const Document& document) {
......
...@@ -66,13 +66,17 @@ NetworkInformation* NetworkInformation::Create(ExecutionContext* context) { ...@@ -66,13 +66,17 @@ NetworkInformation* NetworkInformation::Create(ExecutionContext* context) {
} }
NetworkInformation::~NetworkInformation() { NetworkInformation::~NetworkInformation() {
DCHECK(!observing_); DCHECK(!IsObserving());
} }
bool NetworkInformation::IsObserving() const {
return !!connection_observer_handle_;
};
String NetworkInformation::type() const { String NetworkInformation::type() const {
// type_ is only updated when listening for events, so ask // type_ is only updated when listening for events, so ask
// networkStateNotifier if not listening (crbug.com/379841). // networkStateNotifier if not listening (crbug.com/379841).
if (!observing_) if (!IsObserving())
return ConnectionTypeToString(GetNetworkStateNotifier().ConnectionType()); return ConnectionTypeToString(GetNetworkStateNotifier().ConnectionType());
// If observing, return m_type which changes when the event fires, per spec. // If observing, return m_type which changes when the event fires, per spec.
...@@ -80,7 +84,7 @@ String NetworkInformation::type() const { ...@@ -80,7 +84,7 @@ String NetworkInformation::type() const {
} }
double NetworkInformation::downlinkMax() const { double NetworkInformation::downlinkMax() const {
if (!observing_) if (!IsObserving())
return GetNetworkStateNotifier().MaxBandwidth(); return GetNetworkStateNotifier().MaxBandwidth();
return downlink_max_mbps_; return downlink_max_mbps_;
...@@ -89,7 +93,7 @@ double NetworkInformation::downlinkMax() const { ...@@ -89,7 +93,7 @@ double NetworkInformation::downlinkMax() const {
String NetworkInformation::effectiveType() const { String NetworkInformation::effectiveType() const {
// effective_type_ is only updated when listening for events, so ask // effective_type_ is only updated when listening for events, so ask
// networkStateNotifier if not listening (crbug.com/379841). // networkStateNotifier if not listening (crbug.com/379841).
if (!observing_) { if (!IsObserving()) {
return EffectiveConnectionTypeToString( return EffectiveConnectionTypeToString(
GetNetworkStateNotifier().EffectiveType()); GetNetworkStateNotifier().EffectiveType());
} }
...@@ -99,14 +103,14 @@ String NetworkInformation::effectiveType() const { ...@@ -99,14 +103,14 @@ String NetworkInformation::effectiveType() const {
} }
unsigned long NetworkInformation::rtt() const { unsigned long NetworkInformation::rtt() const {
if (!observing_) if (!IsObserving())
return RoundRtt(GetNetworkStateNotifier().HttpRtt()); return RoundRtt(GetNetworkStateNotifier().HttpRtt());
return http_rtt_msec_; return http_rtt_msec_;
} }
double NetworkInformation::downlink() const { double NetworkInformation::downlink() const {
if (!observing_) if (!IsObserving())
return RoundMbps(GetNetworkStateNotifier().DownlinkThroughputMbps()); return RoundMbps(GetNetworkStateNotifier().DownlinkThroughputMbps());
return downlink_mbps_; return downlink_mbps_;
...@@ -187,10 +191,10 @@ void NetworkInformation::RemoveAllEventListeners() { ...@@ -187,10 +191,10 @@ void NetworkInformation::RemoveAllEventListeners() {
} }
bool NetworkInformation::HasPendingActivity() const { bool NetworkInformation::HasPendingActivity() const {
DCHECK(context_stopped_ || observing_ == HasEventListeners()); DCHECK(context_stopped_ || IsObserving() == HasEventListeners());
// Prevent collection of this object when there are active listeners. // Prevent collection of this object when there are active listeners.
return observing_; return IsObserving();
} }
void NetworkInformation::ContextDestroyed(ExecutionContext*) { void NetworkInformation::ContextDestroyed(ExecutionContext*) {
...@@ -199,21 +203,20 @@ void NetworkInformation::ContextDestroyed(ExecutionContext*) { ...@@ -199,21 +203,20 @@ void NetworkInformation::ContextDestroyed(ExecutionContext*) {
} }
void NetworkInformation::StartObserving() { void NetworkInformation::StartObserving() {
if (!observing_ && !context_stopped_) { if (!IsObserving() && !context_stopped_) {
type_ = GetNetworkStateNotifier().ConnectionType(); type_ = GetNetworkStateNotifier().ConnectionType();
GetNetworkStateNotifier().AddConnectionObserver( DCHECK(!connection_observer_handle_);
this, connection_observer_handle_ =
TaskRunnerHelper::Get(TaskType::kNetworking, GetExecutionContext())); GetNetworkStateNotifier().AddConnectionObserver(
observing_ = true; this, TaskRunnerHelper::Get(TaskType::kNetworking,
GetExecutionContext()));
} }
} }
void NetworkInformation::StopObserving() { void NetworkInformation::StopObserving() {
if (observing_) { if (IsObserving()) {
GetNetworkStateNotifier().RemoveConnectionObserver( DCHECK(connection_observer_handle_);
this, connection_observer_handle_ = nullptr;
TaskRunnerHelper::Get(TaskType::kNetworking, GetExecutionContext()));
observing_ = false;
} }
} }
...@@ -225,7 +228,6 @@ NetworkInformation::NetworkInformation(ExecutionContext* context) ...@@ -225,7 +228,6 @@ NetworkInformation::NetworkInformation(ExecutionContext* context)
http_rtt_msec_(RoundRtt(GetNetworkStateNotifier().HttpRtt())), http_rtt_msec_(RoundRtt(GetNetworkStateNotifier().HttpRtt())),
downlink_mbps_( downlink_mbps_(
RoundMbps(GetNetworkStateNotifier().DownlinkThroughputMbps())), RoundMbps(GetNetworkStateNotifier().DownlinkThroughputMbps())),
observing_(false),
context_stopped_(false) { context_stopped_(false) {
DCHECK_LE(1u, GetNetworkStateNotifier().RandomizationSalt()); DCHECK_LE(1u, GetNetworkStateNotifier().RandomizationSalt());
DCHECK_GE(20u, GetNetworkStateNotifier().RandomizationSalt()); DCHECK_GE(20u, GetNetworkStateNotifier().RandomizationSalt());
......
...@@ -83,6 +83,9 @@ class NetworkInformation final ...@@ -83,6 +83,9 @@ class NetworkInformation final
// returned value is in Mbps. // returned value is in Mbps.
double RoundMbps(const Optional<double>& downlink_mbps) const; double RoundMbps(const Optional<double>& downlink_mbps) const;
// Whether this object is listening for events from NetworkStateNotifier.
bool IsObserving() const;
// Touched only on context thread. // Touched only on context thread.
WebConnectionType type_; WebConnectionType type_;
...@@ -102,11 +105,11 @@ class NetworkInformation final ...@@ -102,11 +105,11 @@ class NetworkInformation final
// only on context thread. // only on context thread.
double downlink_mbps_; double downlink_mbps_;
// Whether this object is listening for events from NetworkStateNotifier.
bool observing_;
// Whether ContextLifecycleObserver::contextDestroyed has been called. // Whether ContextLifecycleObserver::contextDestroyed has been called.
bool context_stopped_; bool context_stopped_;
std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
connection_observer_handle_;
}; };
} // namespace blink } // namespace blink
......
...@@ -65,14 +65,29 @@ NetworkStateNotifier::ScopedNotifier::~ScopedNotifier() { ...@@ -65,14 +65,29 @@ NetworkStateNotifier::ScopedNotifier::~ScopedNotifier() {
after.downlink_throughput_mbps != before_.downlink_throughput_mbps) && after.downlink_throughput_mbps != before_.downlink_throughput_mbps) &&
before_.connection_initialized) { before_.connection_initialized) {
notifier_.NotifyObservers(notifier_.connection_observers_, notifier_.NotifyObservers(notifier_.connection_observers_,
ObserverType::CONNECTION_TYPE, after); ObserverType::kConnectionType, after);
} }
if (after.on_line != before_.on_line && before_.on_line_initialized) { if (after.on_line != before_.on_line && before_.on_line_initialized) {
notifier_.NotifyObservers(notifier_.on_line_state_observers_, notifier_.NotifyObservers(notifier_.on_line_state_observers_,
ObserverType::ONLINE_STATE, after); ObserverType::kOnLineState, after);
} }
} }
NetworkStateNotifier::NetworkStateObserverHandle::NetworkStateObserverHandle(
NetworkStateNotifier* notifier,
NetworkStateNotifier::ObserverType type,
NetworkStateNotifier::NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner)
: notifier_(notifier),
type_(type),
observer_(observer),
task_runner_(std::move(task_runner)) {}
NetworkStateNotifier::NetworkStateObserverHandle::
~NetworkStateObserverHandle() {
notifier_->RemoveObserver(type_, observer_, std::move(task_runner_));
}
void NetworkStateNotifier::SetOnLine(bool on_line) { void NetworkStateNotifier::SetOnLine(bool on_line) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
ScopedNotifier notifier(*this); ScopedNotifier notifier(*this);
...@@ -122,28 +137,20 @@ void NetworkStateNotifier::SetNetworkQuality(WebEffectiveConnectionType type, ...@@ -122,28 +137,20 @@ void NetworkStateNotifier::SetNetworkQuality(WebEffectiveConnectionType type,
} }
} }
void NetworkStateNotifier::AddConnectionObserver( std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
NetworkStateObserver* observer, NetworkStateNotifier::AddConnectionObserver(NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) { RefPtr<WebTaskRunner> task_runner) {
AddObserver(connection_observers_, observer, std::move(task_runner)); AddObserverToMap(connection_observers_, observer, task_runner);
} return std::make_unique<NetworkStateNotifier::NetworkStateObserverHandle>(
this, ObserverType::kConnectionType, observer, task_runner);
void NetworkStateNotifier::AddOnLineObserver(
NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) {
AddObserver(on_line_state_observers_, observer, std::move(task_runner));
}
void NetworkStateNotifier::RemoveConnectionObserver(
NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) {
RemoveObserver(connection_observers_, observer, std::move(task_runner));
} }
void NetworkStateNotifier::RemoveOnLineObserver( std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
NetworkStateObserver* observer, NetworkStateNotifier::AddOnLineObserver(NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) { RefPtr<WebTaskRunner> task_runner) {
RemoveObserver(on_line_state_observers_, observer, std::move(task_runner)); AddObserverToMap(on_line_state_observers_, observer, task_runner);
return std::make_unique<NetworkStateNotifier::NetworkStateObserverHandle>(
this, ObserverType::kOnLineState, observer, task_runner);
} }
void NetworkStateNotifier::SetNetworkConnectionInfoOverride( void NetworkStateNotifier::SetNetworkConnectionInfoOverride(
...@@ -227,10 +234,10 @@ void NetworkStateNotifier::NotifyObserversOnTaskRunner( ...@@ -227,10 +234,10 @@ void NetworkStateNotifier::NotifyObserversOnTaskRunner(
if (!observer_list->observers[i]) if (!observer_list->observers[i])
continue; continue;
switch (type) { switch (type) {
case ObserverType::ONLINE_STATE: case ObserverType::kOnLineState:
observer_list->observers[i]->OnLineStateChange(state.on_line); observer_list->observers[i]->OnLineStateChange(state.on_line);
continue; continue;
case ObserverType::CONNECTION_TYPE: case ObserverType::kConnectionType:
observer_list->observers[i]->ConnectionChange( observer_list->observers[i]->ConnectionChange(
state.type, state.max_bandwidth_mbps, state.effective_type, state.type, state.max_bandwidth_mbps, state.effective_type,
state.http_rtt, state.transport_rtt, state.http_rtt, state.transport_rtt,
...@@ -246,9 +253,9 @@ void NetworkStateNotifier::NotifyObserversOnTaskRunner( ...@@ -246,9 +253,9 @@ void NetworkStateNotifier::NotifyObserversOnTaskRunner(
CollectZeroedObservers(*map, observer_list, std::move(task_runner)); CollectZeroedObservers(*map, observer_list, std::move(task_runner));
} }
void NetworkStateNotifier::AddObserver(ObserverListMap& map, void NetworkStateNotifier::AddObserverToMap(ObserverListMap& map,
NetworkStateObserver* observer, NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) { RefPtr<WebTaskRunner> task_runner) {
DCHECK(task_runner->RunsTasksInCurrentSequence()); DCHECK(task_runner->RunsTasksInCurrentSequence());
DCHECK(observer); DCHECK(observer);
...@@ -262,9 +269,25 @@ void NetworkStateNotifier::AddObserver(ObserverListMap& map, ...@@ -262,9 +269,25 @@ void NetworkStateNotifier::AddObserver(ObserverListMap& map,
result.stored_value->value->observers.push_back(observer); result.stored_value->value->observers.push_back(observer);
} }
void NetworkStateNotifier::RemoveObserver(ObserverListMap& map, void NetworkStateNotifier::RemoveObserver(ObserverType type,
NetworkStateObserver* observer, NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) { RefPtr<WebTaskRunner> task_runner) {
switch (type) {
case ObserverType::kConnectionType:
RemoveObserverFromMap(connection_observers_, observer,
std::move(task_runner));
break;
case ObserverType::kOnLineState:
RemoveObserverFromMap(on_line_state_observers_, observer,
std::move(task_runner));
break;
}
}
void NetworkStateNotifier::RemoveObserverFromMap(
ObserverListMap& map,
NetworkStateObserver* observer,
RefPtr<WebTaskRunner> task_runner) {
DCHECK(task_runner->RunsTasksInCurrentSequence()); DCHECK(task_runner->RunsTasksInCurrentSequence());
DCHECK(observer); DCHECK(observer);
......
...@@ -76,8 +76,37 @@ class PLATFORM_EXPORT NetworkStateNotifier { ...@@ -76,8 +76,37 @@ class PLATFORM_EXPORT NetworkStateNotifier {
virtual void OnLineStateChange(bool on_line) {} virtual void OnLineStateChange(bool on_line) {}
}; };
enum class ObserverType {
kOnLineState,
kConnectionType,
};
class PLATFORM_EXPORT NetworkStateObserverHandle {
USING_FAST_MALLOC(NetworkStateObserverHandle);
public:
NetworkStateObserverHandle(NetworkStateNotifier*,
ObserverType,
NetworkStateObserver*,
RefPtr<WebTaskRunner>);
~NetworkStateObserverHandle();
private:
NetworkStateNotifier* notifier_;
ObserverType type_;
NetworkStateObserver* observer_;
RefPtr<WebTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(NetworkStateObserverHandle);
};
NetworkStateNotifier() : has_override_(false) {} NetworkStateNotifier() : has_override_(false) {}
~NetworkStateNotifier() {
DCHECK(connection_observers_.IsEmpty());
DCHECK(on_line_state_observers_.IsEmpty());
}
// Can be called on any thread. // Can be called on any thread.
bool OnLine() const { bool OnLine() const {
MutexLocker locker(mutex_); MutexLocker locker(mutex_);
...@@ -186,10 +215,12 @@ class PLATFORM_EXPORT NetworkStateNotifier { ...@@ -186,10 +215,12 @@ class PLATFORM_EXPORT NetworkStateNotifier {
// before the observer or its execution context goes away. It's possible for // before the observer or its execution context goes away. It's possible for
// an observer to be called twice for the same event if it is first removed // an observer to be called twice for the same event if it is first removed
// and then added during notification. // and then added during notification.
void AddConnectionObserver(NetworkStateObserver*, RefPtr<WebTaskRunner>); std::unique_ptr<NetworkStateObserverHandle> AddConnectionObserver(
void AddOnLineObserver(NetworkStateObserver*, RefPtr<WebTaskRunner>); NetworkStateObserver*,
void RemoveConnectionObserver(NetworkStateObserver*, RefPtr<WebTaskRunner>); RefPtr<WebTaskRunner>);
void RemoveOnLineObserver(NetworkStateObserver*, RefPtr<WebTaskRunner>); std::unique_ptr<NetworkStateObserverHandle> AddOnLineObserver(
NetworkStateObserver*,
RefPtr<WebTaskRunner>);
// Returns the randomization salt (weak and insecure) that should be used when // Returns the randomization salt (weak and insecure) that should be used when
// adding noise to the network quality metrics. This is known only to the // adding noise to the network quality metrics. This is known only to the
...@@ -198,6 +229,8 @@ class PLATFORM_EXPORT NetworkStateNotifier { ...@@ -198,6 +229,8 @@ class PLATFORM_EXPORT NetworkStateNotifier {
uint8_t RandomizationSalt() const { return randomization_salt_; } uint8_t RandomizationSalt() const { return randomization_salt_; }
private: private:
friend class NetworkStateObserverHandle;
struct ObserverList { struct ObserverList {
ObserverList() : iterating(false) {} ObserverList() : iterating(false) {}
bool iterating; bool iterating;
...@@ -219,11 +252,6 @@ class PLATFORM_EXPORT NetworkStateNotifier { ...@@ -219,11 +252,6 @@ class PLATFORM_EXPORT NetworkStateNotifier {
NetworkState before_; NetworkState before_;
}; };
enum class ObserverType {
ONLINE_STATE,
CONNECTION_TYPE,
};
// The ObserverListMap is cross-thread accessed, adding/removing Observers // The ObserverListMap is cross-thread accessed, adding/removing Observers
// running on a task runner. // running on a task runner.
using ObserverListMap = using ObserverListMap =
...@@ -235,12 +263,15 @@ class PLATFORM_EXPORT NetworkStateNotifier { ...@@ -235,12 +263,15 @@ class PLATFORM_EXPORT NetworkStateNotifier {
RefPtr<WebTaskRunner>, RefPtr<WebTaskRunner>,
const NetworkState&); const NetworkState&);
void AddObserver(ObserverListMap&, void AddObserverToMap(ObserverListMap&,
NetworkStateObserver*, NetworkStateObserver*,
RefPtr<WebTaskRunner>); RefPtr<WebTaskRunner>);
void RemoveObserver(ObserverListMap&, void RemoveObserver(ObserverType,
NetworkStateObserver*, NetworkStateObserver*,
RefPtr<WebTaskRunner>); RefPtr<WebTaskRunner>);
void RemoveObserverFromMap(ObserverListMap&,
NetworkStateObserver*,
RefPtr<WebTaskRunner>);
ObserverList* LockAndFindObserverList(ObserverListMap&, ObserverList* LockAndFindObserverList(ObserverListMap&,
RefPtr<WebTaskRunner>); RefPtr<WebTaskRunner>);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment