// 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 "net/base/network_config_watcher_mac.h"

#include <algorithm>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"

namespace net {

namespace {

#if !defined(OS_IOS)
// Called back by OS.  Calls OnNetworkConfigChange().
void DynamicStoreCallback(SCDynamicStoreRef /* store */,
                          CFArrayRef changed_keys,
                          void* config_delegate) {
  NetworkConfigWatcherMac::Delegate* net_config_delegate =
      static_cast<NetworkConfigWatcherMac::Delegate*>(config_delegate);
  net_config_delegate->OnNetworkConfigChange(changed_keys);
}
#endif  // !defined(OS_IOS)

class NetworkConfigWatcherMacThread : public base::Thread {
 public:
  NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate);
  virtual ~NetworkConfigWatcherMacThread();

 protected:
  // base::Thread
  virtual void Init() OVERRIDE;
  virtual void CleanUp() OVERRIDE;

 private:
  // The SystemConfiguration calls in this function can lead to contention early
  // on, so we invoke this function later on in startup to keep it fast.
  void InitNotifications();

  base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_;
  NetworkConfigWatcherMac::Delegate* const delegate_;
  base::WeakPtrFactory<NetworkConfigWatcherMacThread> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMacThread);
};

NetworkConfigWatcherMacThread::NetworkConfigWatcherMacThread(
    NetworkConfigWatcherMac::Delegate* delegate)
    : base::Thread("NetworkConfigWatcher"),
      delegate_(delegate),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}

NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() {
  // Allow IO because Stop() calls PlatformThread::Join(), which is a blocking
  // operation. This is expected during shutdown.
  base::ThreadRestrictions::ScopedAllowIO allow_io;

  Stop();
}

void NetworkConfigWatcherMacThread::Init() {
  // Disallow IO to make sure NetworkConfigWatcherMacThread's helper thread does
  // not perform blocking operations.
  base::ThreadRestrictions::SetIOAllowed(false);

  delegate_->Init();

  // TODO(willchan): Look to see if there's a better signal for when it's ok to
  // initialize this, rather than just delaying it by a fixed time.
  const base::TimeDelta kInitializationDelay = base::TimeDelta::FromSeconds(1);
  message_loop()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&NetworkConfigWatcherMacThread::InitNotifications,
                 weak_factory_.GetWeakPtr()),
      kInitializationDelay);
}

void NetworkConfigWatcherMacThread::CleanUp() {
  if (!run_loop_source_.get())
    return;

  CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_.get(),
                        kCFRunLoopCommonModes);
  run_loop_source_.reset();
}

void NetworkConfigWatcherMacThread::InitNotifications() {
#if !defined(OS_IOS)
  // SCDynamicStore API does not exist on iOS.
  // Add a run loop source for a dynamic store to the current run loop.
  SCDynamicStoreContext context = {
    0,          // Version 0.
    delegate_,  // User data.
    NULL,       // This is not reference counted.  No retain function.
    NULL,       // This is not reference counted.  No release function.
    NULL,       // No description for this.
  };
  base::mac::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate(
      NULL, CFSTR("org.chromium"), DynamicStoreCallback, &context));
  run_loop_source_.reset(SCDynamicStoreCreateRunLoopSource(
      NULL, store.get(), 0));
  CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source_.get(),
                     kCFRunLoopCommonModes);
#endif  // !defined(OS_IOS)

  // Set up notifications for interface and IP address changes.
  delegate_->StartReachabilityNotifications();
#if !defined(OS_IOS)
  delegate_->SetDynamicStoreNotificationKeys(store.get());
#endif  // !defined(OS_IOS)
}

}  // namespace

NetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate)
    : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) {
  // We create this notifier thread because the notification implementation
  // needs a thread with a CFRunLoop, and there's no guarantee that
  // MessageLoop::current() meets that criterion.
  base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
  notifier_thread_->StartWithOptions(thread_options);
}

NetworkConfigWatcherMac::~NetworkConfigWatcherMac() {}

}  // namespace net
