Landing Recent QUIC changes until 8/19/2015 17:00 UTC.
[chromium-blink-merge.git] / net / base / network_config_watcher_mac.cc
blobbdf75c39ad2a8ac677386bfa760a133446eb18e2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/base/network_config_watcher_mac.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/threading/thread.h"
14 #include "base/threading/thread_restrictions.h"
16 namespace net {
18 namespace {
20 #if !defined(OS_IOS)
21 // Called back by OS. Calls OnNetworkConfigChange().
22 void DynamicStoreCallback(SCDynamicStoreRef /* store */,
23 CFArrayRef changed_keys,
24 void* config_delegate) {
25 NetworkConfigWatcherMac::Delegate* net_config_delegate =
26 static_cast<NetworkConfigWatcherMac::Delegate*>(config_delegate);
27 net_config_delegate->OnNetworkConfigChange(changed_keys);
29 #endif // !defined(OS_IOS)
31 class NetworkConfigWatcherMacThread : public base::Thread {
32 public:
33 NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate);
34 ~NetworkConfigWatcherMacThread() override;
36 protected:
37 // base::Thread
38 void Init() override;
39 void CleanUp() override;
41 private:
42 // The SystemConfiguration calls in this function can lead to contention early
43 // on, so we invoke this function later on in startup to keep it fast.
44 void InitNotifications();
46 base::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_;
47 NetworkConfigWatcherMac::Delegate* const delegate_;
48 base::WeakPtrFactory<NetworkConfigWatcherMacThread> weak_factory_;
50 DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMacThread);
53 NetworkConfigWatcherMacThread::NetworkConfigWatcherMacThread(
54 NetworkConfigWatcherMac::Delegate* delegate)
55 : base::Thread("NetworkConfigWatcher"),
56 delegate_(delegate),
57 weak_factory_(this) {}
59 NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() {
60 // Allow IO because Stop() calls PlatformThread::Join(), which is a blocking
61 // operation. This is expected during shutdown.
62 base::ThreadRestrictions::ScopedAllowIO allow_io;
64 Stop();
67 void NetworkConfigWatcherMacThread::Init() {
68 // Disallow IO to make sure NetworkConfigWatcherMacThread's helper thread does
69 // not perform blocking operations.
70 base::ThreadRestrictions::SetIOAllowed(false);
72 delegate_->Init();
74 // TODO(willchan): Look to see if there's a better signal for when it's ok to
75 // initialize this, rather than just delaying it by a fixed time.
76 const base::TimeDelta kInitializationDelay = base::TimeDelta::FromSeconds(1);
77 message_loop()->PostDelayedTask(
78 FROM_HERE,
79 base::Bind(&NetworkConfigWatcherMacThread::InitNotifications,
80 weak_factory_.GetWeakPtr()),
81 kInitializationDelay);
84 void NetworkConfigWatcherMacThread::CleanUp() {
85 if (!run_loop_source_.get())
86 return;
88 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_.get(),
89 kCFRunLoopCommonModes);
90 run_loop_source_.reset();
93 void NetworkConfigWatcherMacThread::InitNotifications() {
94 #if !defined(OS_IOS)
95 // SCDynamicStore API does not exist on iOS.
96 // Add a run loop source for a dynamic store to the current run loop.
97 SCDynamicStoreContext context = {
98 0, // Version 0.
99 delegate_, // User data.
100 NULL, // This is not reference counted. No retain function.
101 NULL, // This is not reference counted. No release function.
102 NULL, // No description for this.
104 base::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate(
105 NULL, CFSTR("org.chromium"), DynamicStoreCallback, &context));
106 run_loop_source_.reset(SCDynamicStoreCreateRunLoopSource(
107 NULL, store.get(), 0));
108 CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source_.get(),
109 kCFRunLoopCommonModes);
110 #endif // !defined(OS_IOS)
112 // Set up notifications for interface and IP address changes.
113 delegate_->StartReachabilityNotifications();
114 #if !defined(OS_IOS)
115 delegate_->SetDynamicStoreNotificationKeys(store.get());
116 #endif // !defined(OS_IOS)
119 } // namespace
121 NetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate)
122 : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) {
123 // We create this notifier thread because the notification implementation
124 // needs a thread with a CFRunLoop, and there's no guarantee that
125 // MessageLoop::current() meets that criterion.
126 base::Thread::Options thread_options(base::MessageLoop::TYPE_UI, 0);
127 notifier_thread_->StartWithOptions(thread_options);
130 NetworkConfigWatcherMac::~NetworkConfigWatcherMac() {}
132 } // namespace net