| Index: chrome/browser/sync/notifier/base/mac/network_status_detector_task_mac.cc
|
| ===================================================================
|
| --- chrome/browser/sync/notifier/base/mac/network_status_detector_task_mac.cc (revision 46353)
|
| +++ chrome/browser/sync/notifier/base/mac/network_status_detector_task_mac.cc (working copy)
|
| @@ -1,262 +0,0 @@
|
| -// Copyright (c) 2009 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 "chrome/browser/sync/notifier/base/mac/network_status_detector_task_mac.h"
|
| -
|
| -#include <SystemConfiguration/SCNetworkReachability.h>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/scoped_cftyperef.h"
|
| -#include "base/scoped_ptr.h"
|
| -#include "base/string_util.h"
|
| -#include "base/sys_string_conversions.h"
|
| -#include "talk/base/physicalsocketserver.h"
|
| -#include "talk/base/socket.h"
|
| -#include "talk/base/thread.h"
|
| -
|
| -namespace notifier {
|
| -
|
| -NetworkStatusDetectorTaskMac::WorkerInfo::WorkerInfo(
|
| - PlatformThreadId thread_id)
|
| - : thread_state(WORKER_THREAD_STOPPED),
|
| - thread_id(thread_id),
|
| - thread_run_loop(NULL) {}
|
| -
|
| -NetworkStatusDetectorTaskMac::WorkerInfo::WorkerInfo(
|
| - WorkerThreadState thread_state,
|
| - PlatformThreadId thread_id,
|
| - CFRunLoopRef thread_run_loop)
|
| - : thread_state(thread_state),
|
| - thread_id(thread_id),
|
| - thread_run_loop(thread_run_loop) {
|
| - DCHECK_EQ(thread_state == WORKER_THREAD_RUNNING, thread_run_loop != NULL);
|
| -}
|
| -
|
| -NetworkStatusDetectorTaskMac::NetworkStatusDetectorTaskMac(
|
| - talk_base::Task* parent)
|
| - : NetworkStatusDetectorTask(parent),
|
| - parent_thread_id_(PlatformThread::CurrentId()),
|
| - parent_thread_(talk_base::Thread::Current()),
|
| - worker_thread_(kNullThreadHandle),
|
| - worker_thread_not_stopped_(&worker_lock_),
|
| - worker_shared_info_(parent_thread_id_) {
|
| - DCHECK(parent_thread_);
|
| - DCHECK(IsOnParentThread());
|
| -}
|
| -
|
| -NetworkStatusDetectorTaskMac::~NetworkStatusDetectorTaskMac() {
|
| - ClearWorker();
|
| -}
|
| -
|
| -void NetworkStatusDetectorTaskMac::ClearWorker() {
|
| - DCHECK(IsOnParentThread());
|
| - // Sadly, there's no Lock::AssertNotAcquired().
|
| - WorkerThreadState worker_thread_state;
|
| - CFRunLoopRef worker_thread_run_loop;
|
| - {
|
| - AutoLock auto_lock(worker_lock_);
|
| - worker_thread_state = worker_shared_info_.thread_state;
|
| - worker_thread_run_loop = worker_shared_info_.thread_run_loop;
|
| - }
|
| - if (worker_thread_state == WORKER_THREAD_RUNNING) {
|
| - CFRunLoopStop(worker_thread_run_loop);
|
| - }
|
| - if (worker_thread_ != kNullThreadHandle) {
|
| - DCHECK_NE(worker_thread_state, WORKER_THREAD_STOPPED);
|
| - PlatformThread::Join(worker_thread_);
|
| - }
|
| -
|
| - worker_thread_ = kNullThreadHandle;
|
| - worker_shared_info_ = WorkerInfo(parent_thread_id_);
|
| -}
|
| -
|
| -bool NetworkStatusDetectorTaskMac::IsOnParentThread() const {
|
| - return PlatformThread::CurrentId() == parent_thread_id_;
|
| -}
|
| -
|
| -bool NetworkStatusDetectorTaskMac::IsOnWorkerThread() {
|
| - PlatformThreadId current_thread_id = PlatformThread::CurrentId();
|
| - AutoLock auto_lock(worker_lock_);
|
| - return
|
| - (worker_shared_info_.thread_id != parent_thread_id_) &&
|
| - (current_thread_id == worker_shared_info_.thread_id);
|
| -}
|
| -
|
| -int NetworkStatusDetectorTaskMac::ProcessStart() {
|
| - DCHECK(IsOnParentThread());
|
| - if (logging::DEBUG_MODE) {
|
| - AutoLock auto_lock(worker_lock_);
|
| - DCHECK_EQ(worker_shared_info_.thread_state, WORKER_THREAD_STOPPED);
|
| - DCHECK(!worker_shared_info_.thread_run_loop);
|
| - DCHECK_EQ(worker_shared_info_.thread_id, parent_thread_id_);
|
| - }
|
| -
|
| - if (!PlatformThread::Create(0, this, &worker_thread_)) {
|
| - LOG(WARNING) << "Could not create network reachability thread";
|
| - ClearWorker();
|
| - return STATE_ERROR;
|
| - }
|
| -
|
| - // Wait for the just-created worker thread to start up and
|
| - // initialize itself.
|
| - WorkerThreadState worker_thread_state;
|
| - {
|
| - AutoLock auto_lock(worker_lock_);
|
| - while (worker_shared_info_.thread_state == WORKER_THREAD_STOPPED) {
|
| - worker_thread_not_stopped_.Wait();
|
| - }
|
| - worker_thread_state = worker_shared_info_.thread_state;
|
| - }
|
| -
|
| - if (worker_thread_state == WORKER_THREAD_ERROR) {
|
| - ClearWorker();
|
| - return STATE_ERROR;
|
| - }
|
| -
|
| - if (logging::DEBUG_MODE) {
|
| - AutoLock auto_lock(worker_lock_);
|
| - DCHECK_EQ(worker_shared_info_.thread_state, WORKER_THREAD_RUNNING);
|
| - DCHECK(worker_shared_info_.thread_run_loop);
|
| - DCHECK_NE(worker_shared_info_.thread_id, parent_thread_id_);
|
| - }
|
| -
|
| - return STATE_RESPONSE;
|
| -}
|
| -
|
| -void NetworkStatusDetectorTaskMac::Stop() {
|
| - ClearWorker();
|
| - NetworkStatusDetectorTask::Stop();
|
| -}
|
| -
|
| -void NetworkStatusDetectorTaskMac::OnMessage(talk_base::Message* message) {
|
| - DCHECK(IsOnParentThread());
|
| - bool alive = message->message_id;
|
| - SetNetworkAlive(alive);
|
| -}
|
| -
|
| -NetworkStatusDetectorTask* NetworkStatusDetectorTask::Create(
|
| - talk_base::Task* parent) {
|
| - return new NetworkStatusDetectorTaskMac(parent);
|
| -}
|
| -
|
| -// Everything below is run in the worker thread.
|
| -
|
| -namespace {
|
| -
|
| -// TODO(akalin): Use these constants across all platform
|
| -// implementations.
|
| -const char kTalkHost[] = "talk.google.com";
|
| -const int kTalkPort = 5222;
|
| -
|
| -CFStringRef NetworkReachabilityCopyDescription(const void *info) {
|
| - return base::SysUTF8ToCFStringRef(
|
| - StringPrintf("NetworkStatusDetectorTaskMac(0x%p)", info));
|
| -}
|
| -
|
| -void NetworkReachabilityChangedCallback(SCNetworkReachabilityRef target,
|
| - SCNetworkConnectionFlags flags,
|
| - void* info) {
|
| - bool network_active = ((flags & (kSCNetworkFlagsReachable |
|
| - kSCNetworkFlagsConnectionRequired |
|
| - kSCNetworkFlagsConnectionAutomatic |
|
| - kSCNetworkFlagsInterventionRequired)) ==
|
| - kSCNetworkFlagsReachable);
|
| - NetworkStatusDetectorTaskMac* network_status_detector_task_mac =
|
| - static_cast<NetworkStatusDetectorTaskMac*>(info);
|
| - network_status_detector_task_mac->NetworkReachabilityChanged(
|
| - network_active);
|
| -}
|
| -
|
| -
|
| -SCNetworkReachabilityRef CreateAndScheduleNetworkReachability(
|
| - SCNetworkReachabilityContext* network_reachability_context) {
|
| - scoped_cftyperef<SCNetworkReachabilityRef> network_reachability(
|
| - SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, kTalkHost));
|
| - if (!network_reachability.get()) {
|
| - LOG(WARNING) << "Could not create network reachability object";
|
| - return NULL;
|
| - }
|
| -
|
| - if (!SCNetworkReachabilitySetCallback(network_reachability.get(),
|
| - &NetworkReachabilityChangedCallback,
|
| - network_reachability_context)) {
|
| - LOG(WARNING) << "Could not set network reachability callback";
|
| - return NULL;
|
| - }
|
| -
|
| - if (!SCNetworkReachabilityScheduleWithRunLoop(network_reachability.get(),
|
| - CFRunLoopGetCurrent(),
|
| - kCFRunLoopDefaultMode)) {
|
| - LOG(WARNING) << "Could not schedule network reachability with run loop";
|
| - return NULL;
|
| - }
|
| -
|
| - return network_reachability.release();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -void NetworkStatusDetectorTaskMac::ThreadMain() {
|
| - DCHECK(!IsOnParentThread());
|
| - PlatformThread::SetName("NetworkStatusDetectorTaskMac worker thread");
|
| -
|
| - SCNetworkReachabilityContext network_reachability_context;
|
| - network_reachability_context.version = 0;
|
| - network_reachability_context.info = static_cast<void *>(this);
|
| - network_reachability_context.retain = NULL;
|
| - network_reachability_context.release = NULL;
|
| - network_reachability_context.copyDescription =
|
| - &NetworkReachabilityCopyDescription;
|
| -
|
| - PlatformThreadId worker_thread_id = PlatformThread::CurrentId();
|
| -
|
| - scoped_cftyperef<SCNetworkReachabilityRef> network_reachability(
|
| - CreateAndScheduleNetworkReachability(&network_reachability_context));
|
| - if (!network_reachability.get()) {
|
| - {
|
| - AutoLock auto_lock(worker_lock_);
|
| - worker_shared_info_ =
|
| - WorkerInfo(WORKER_THREAD_ERROR, worker_thread_id, NULL);
|
| - }
|
| - worker_thread_not_stopped_.Signal();
|
| - return;
|
| - }
|
| -
|
| - CFRunLoopRef run_loop = CFRunLoopGetCurrent();
|
| - {
|
| - AutoLock auto_lock(worker_lock_);
|
| - worker_shared_info_ =
|
| - WorkerInfo(WORKER_THREAD_RUNNING, worker_thread_id, run_loop);
|
| - }
|
| - worker_thread_not_stopped_.Signal();
|
| -
|
| - DCHECK(IsOnWorkerThread());
|
| - CFRunLoopRun();
|
| -
|
| - // We reach here only when our run loop is stopped (usually by the
|
| - // parent thread). The parent thread is responsible for resetting
|
| - // worker_thread_shared_info_, et al. to appropriate values.
|
| -}
|
| -
|
| -void NetworkStatusDetectorTaskMac::NetworkReachabilityChanged(
|
| - bool network_active) {
|
| - DCHECK(IsOnWorkerThread());
|
| -
|
| - bool alive = network_active;
|
| - if (alive) {
|
| - talk_base::PhysicalSocketServer physical;
|
| - scoped_ptr<talk_base::Socket> socket(physical.CreateSocket(SOCK_STREAM));
|
| - alive =
|
| - (socket->Connect(talk_base::SocketAddress(kTalkHost, kTalkPort)) == 0);
|
| - LOG(INFO) << "network is " << (alive ? "alive" : "not alive")
|
| - << " based on connecting to " << kTalkHost << ":" << kTalkPort;
|
| - } else {
|
| - LOG(INFO) << "network is not alive";
|
| - }
|
| -
|
| - parent_thread_->Send(this, alive);
|
| -}
|
| -
|
| -} // namespace notifier
|
| -
|
|
|