| Index: chrome/common/net/network_change_observer_proxy.cc
|
| ===================================================================
|
| --- chrome/common/net/network_change_observer_proxy.cc (revision 50775)
|
| +++ chrome/common/net/network_change_observer_proxy.cc (working copy)
|
| @@ -1,137 +0,0 @@
|
| -// Copyright (c) 2010 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.
|
| -
|
| -// Some notes that may help anyone trying to reason about this code:
|
| -//
|
| -// - The source thread must be guaranteed to outlive the target
|
| -// thread. This is so that it is guaranteed that any task posted to
|
| -// the source thread will eventually be run. In particular, we want
|
| -// to make sure that Detach() causes us to eventually be removed as
|
| -// an observer.
|
| -//
|
| -// Note that this implies that any task posted to the target thread
|
| -// from the source thread may not run. But we post only
|
| -// TargetObserverOnIPAddressChanged() tasks on the target thread,
|
| -// which we can safely drop.
|
| -//
|
| -// - The source NetworkChangeNotifier must be guaranteed to outlive
|
| -// the target thread. This is so that it is guaranteed that any
|
| -// task posted to the source thread can safely access the source
|
| -// NetworkChangeNotifier.
|
| -//
|
| -// - Ref-counting this class is necessary, although as a consequence
|
| -// we can't make any guarantees about which thread will destroy an
|
| -// instance. Earlier versions of this class tried to get away
|
| -// without ref-counting. One version deleted the class in
|
| -// Unobserve(); this didn't work because there may still be
|
| -// TargetObserverOnIPAddressChanged() tasks on the target thread.
|
| -// An attempt to fix this was to post a DeleteTask on the target
|
| -// thread from Unobserve(), but this meant that there would be no
|
| -// way of knowing when on the target thread the instance would be
|
| -// deleted. Indeed, as mentioned above, any tasks posted on the
|
| -// target thread may not run, so this introduced the possibility of
|
| -// a memory leak.
|
| -//
|
| -// - It is important that all posted tasks that work with a proxy be
|
| -// RunnableMethods so that the ref-counting guarantees that the
|
| -// proxy is still valid when the task runs.
|
| -
|
| -#include "chrome/common/net/network_change_observer_proxy.h"
|
| -
|
| -#include <cstddef>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/task.h"
|
| -#include "chrome/common/net/network_change_notifier_thread.h"
|
| -#include "net/base/network_change_notifier.h"
|
| -
|
| -namespace chrome_common_net {
|
| -
|
| -NetworkChangeObserverProxy::NetworkChangeObserverProxy(
|
| - const NetworkChangeNotifierThread* source_thread,
|
| - MessageLoop* target_message_loop)
|
| - : source_thread_(source_thread),
|
| - target_message_loop_(target_message_loop),
|
| - target_observer_(NULL) {
|
| - DCHECK(source_thread_);
|
| - MessageLoop* source_message_loop = source_thread_->GetMessageLoop();
|
| - DCHECK(source_message_loop);
|
| - DCHECK(target_message_loop_);
|
| - DCHECK_NE(source_message_loop, target_message_loop_);
|
| - DCHECK_EQ(MessageLoop::current(), target_message_loop_);
|
| -}
|
| -
|
| -void NetworkChangeObserverProxy::Attach(
|
| - net::NetworkChangeNotifier::Observer* target_observer) {
|
| - DCHECK_EQ(MessageLoop::current(), target_message_loop_);
|
| - DCHECK(!target_observer_);
|
| - target_observer_ = target_observer;
|
| - DCHECK(target_observer_);
|
| - source_thread_->GetMessageLoop()->PostTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &NetworkChangeObserverProxy::Observe));
|
| -}
|
| -
|
| -void NetworkChangeObserverProxy::Detach() {
|
| - DCHECK_EQ(MessageLoop::current(), target_message_loop_);
|
| - DCHECK(target_observer_);
|
| - target_observer_ = NULL;
|
| - source_thread_->GetMessageLoop()->PostTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &NetworkChangeObserverProxy::Unobserve));
|
| -}
|
| -
|
| -NetworkChangeObserverProxy::~NetworkChangeObserverProxy() {
|
| - MessageLoop* current_message_loop = MessageLoop::current();
|
| - // We can be deleted on either the source or target thread, so the
|
| - // best we can do is check that we're on either.
|
| - DCHECK((current_message_loop == source_thread_->GetMessageLoop()) ||
|
| - (current_message_loop == target_message_loop_));
|
| - // Even though only the target thread uses target_observer_, it
|
| - // should still be unset even if we're on the source thread; posting
|
| - // a task is effectively a memory barrier.
|
| - DCHECK(!target_observer_);
|
| -}
|
| -
|
| -void NetworkChangeObserverProxy::Observe() {
|
| - DCHECK_EQ(MessageLoop::current(), source_thread_->GetMessageLoop());
|
| - net::NetworkChangeNotifier* source_network_change_notifier =
|
| - source_thread_->GetNetworkChangeNotifier();
|
| - DCHECK(source_network_change_notifier);
|
| - source_network_change_notifier->AddObserver(this);
|
| -}
|
| -
|
| -// The Task from which this was called may hold the last reference to
|
| -// us (this is how we can get deleted on the source thread).
|
| -void NetworkChangeObserverProxy::Unobserve() {
|
| - DCHECK_EQ(MessageLoop::current(), source_thread_->GetMessageLoop());
|
| - net::NetworkChangeNotifier* source_network_change_notifier =
|
| - source_thread_->GetNetworkChangeNotifier();
|
| - DCHECK(source_network_change_notifier);
|
| - source_network_change_notifier->RemoveObserver(this);
|
| -}
|
| -
|
| -// Although we may get this event after Detach() has been called on
|
| -// the target thread, we know that Unobserve() hasn't been called yet.
|
| -// But we know that it has been posted, so it at least holds a
|
| -// reference to us.
|
| -void NetworkChangeObserverProxy::OnIPAddressChanged() {
|
| - DCHECK_EQ(MessageLoop::current(), source_thread_->GetMessageLoop());
|
| - target_message_loop_->PostTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(
|
| - this,
|
| - &NetworkChangeObserverProxy::TargetObserverOnIPAddressChanged));
|
| -}
|
| -
|
| -// The Task from which this was called may hold the last reference to
|
| -// us (this is how we can get deleted on the target thread).
|
| -void NetworkChangeObserverProxy::TargetObserverOnIPAddressChanged() {
|
| - DCHECK_EQ(MessageLoop::current(), target_message_loop_);
|
| - if (target_observer_)
|
| - target_observer_->OnIPAddressChanged();
|
| -}
|
| -
|
| -} // namespace chrome_common_net
|
|
|