1 // Copyright (c) 2011 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.
4
5 #include "base/message_loop.h"
6 #include "base/threading/thread.h"
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/io_thread.h"
9 #include "chrome/browser/net/ssl_config_service_manager.h"
10 #include "chrome/browser/prefs/pref_member.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/common/pref_names.h"
13 #include "content/common/notification_details.h"
14 #include "content/common/notification_source.h"
15 #include "content/common/notification_type.h"
16 #include "net/base/ssl_config_service.h"
17
18 ////////////////////////////////////////////////////////////////////////////////
19 // SSLConfigServicePref
20
21 // An SSLConfigService which stores a cached version of the current SSLConfig
22 // prefs, which are updated by SSLConfigServiceManagerPref when the prefs
23 // change.
24 class SSLConfigServicePref : public net::SSLConfigService {
25 public:
SSLConfigServicePref()26 SSLConfigServicePref() {}
~SSLConfigServicePref()27 virtual ~SSLConfigServicePref() {}
28
29 // Store SSL config settings in |config|. Must only be called from IO thread.
30 virtual void GetSSLConfig(net::SSLConfig* config);
31
32 private:
33 // Allow the pref watcher to update our internal state.
34 friend class SSLConfigServiceManagerPref;
35
36 // This method is posted to the IO thread from the browser thread to carry the
37 // new config information.
38 void SetNewSSLConfig(const net::SSLConfig& new_config);
39
40 // Cached value of prefs, should only be accessed from IO thread.
41 net::SSLConfig cached_config_;
42
43 DISALLOW_COPY_AND_ASSIGN(SSLConfigServicePref);
44 };
45
GetSSLConfig(net::SSLConfig * config)46 void SSLConfigServicePref::GetSSLConfig(net::SSLConfig* config) {
47 *config = cached_config_;
48 }
49
SetNewSSLConfig(const net::SSLConfig & new_config)50 void SSLConfigServicePref::SetNewSSLConfig(
51 const net::SSLConfig& new_config) {
52 net::SSLConfig orig_config = cached_config_;
53 cached_config_ = new_config;
54 ProcessConfigUpdate(orig_config, new_config);
55 }
56
57 ////////////////////////////////////////////////////////////////////////////////
58 // SSLConfigServiceManagerPref
59
60 // The manager for holding and updating an SSLConfigServicePref instance.
61 class SSLConfigServiceManagerPref
62 : public SSLConfigServiceManager,
63 public NotificationObserver {
64 public:
65 SSLConfigServiceManagerPref(PrefService* user_prefs,
66 PrefService* local_state);
~SSLConfigServiceManagerPref()67 virtual ~SSLConfigServiceManagerPref() {}
68
69 virtual net::SSLConfigService* Get();
70
71 private:
72 // Register user_prefs and local_state SSL preferences.
73 static void RegisterPrefs(PrefService* prefs);
74
75 // Copy pref values to local_state from user_prefs if local_state doesn't have
76 // the pref value and user_prefs has the pref value. Remove them from
77 // user_prefs.
78 static void MigrateUserPrefs(PrefService* local_state,
79 PrefService* user_prefs);
80
81 // Callback for preference changes. This will post the changes to the IO
82 // thread with SetNewSSLConfig.
83 virtual void Observe(NotificationType type,
84 const NotificationSource& source,
85 const NotificationDetails& details);
86
87 // Store SSL config settings in |config|, directly from the preferences. Must
88 // only be called from UI thread.
89 void GetSSLConfigFromPrefs(net::SSLConfig* config);
90
91 // The prefs (should only be accessed from UI thread)
92 BooleanPrefMember rev_checking_enabled_;
93 BooleanPrefMember ssl3_enabled_;
94 BooleanPrefMember tls1_enabled_;
95
96 scoped_refptr<SSLConfigServicePref> ssl_config_service_;
97
98 DISALLOW_COPY_AND_ASSIGN(SSLConfigServiceManagerPref);
99 };
100
SSLConfigServiceManagerPref(PrefService * user_prefs,PrefService * local_state)101 SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
102 PrefService* user_prefs, PrefService* local_state)
103 : ssl_config_service_(new SSLConfigServicePref()) {
104 DCHECK(user_prefs);
105 DCHECK(local_state);
106
107 RegisterPrefs(user_prefs);
108 RegisterPrefs(local_state);
109
110 // TODO(rtenneti): remove migration code after 6 months.
111 MigrateUserPrefs(local_state, user_prefs);
112
113 rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled,
114 local_state, this);
115 ssl3_enabled_.Init(prefs::kSSL3Enabled, local_state, this);
116 tls1_enabled_.Init(prefs::kTLS1Enabled, local_state, this);
117
118 // Initialize from UI thread. This is okay as there shouldn't be anything on
119 // the IO thread trying to access it yet.
120 GetSSLConfigFromPrefs(&ssl_config_service_->cached_config_);
121 }
122
123 // static
RegisterPrefs(PrefService * prefs)124 void SSLConfigServiceManagerPref::RegisterPrefs(PrefService* prefs) {
125 net::SSLConfig default_config;
126 if (!prefs->FindPreference(prefs::kCertRevocationCheckingEnabled)) {
127 prefs->RegisterBooleanPref(prefs::kCertRevocationCheckingEnabled,
128 default_config.rev_checking_enabled);
129 }
130 if (!prefs->FindPreference(prefs::kSSL3Enabled)) {
131 prefs->RegisterBooleanPref(prefs::kSSL3Enabled,
132 default_config.ssl3_enabled);
133 }
134 if (!prefs->FindPreference(prefs::kTLS1Enabled)) {
135 prefs->RegisterBooleanPref(prefs::kTLS1Enabled,
136 default_config.tls1_enabled);
137 }
138 }
139
140 // static
MigrateUserPrefs(PrefService * local_state,PrefService * user_prefs)141 void SSLConfigServiceManagerPref::MigrateUserPrefs(PrefService* local_state,
142 PrefService* user_prefs) {
143 if (user_prefs->HasPrefPath(prefs::kCertRevocationCheckingEnabled)) {
144 if (!local_state->HasPrefPath(prefs::kCertRevocationCheckingEnabled)) {
145 // Migrate the kCertRevocationCheckingEnabled preference.
146 local_state->SetBoolean(prefs::kCertRevocationCheckingEnabled,
147 user_prefs->GetBoolean(prefs::kCertRevocationCheckingEnabled));
148 }
149 user_prefs->ClearPref(prefs::kCertRevocationCheckingEnabled);
150 }
151 if (user_prefs->HasPrefPath(prefs::kSSL3Enabled)) {
152 if (!local_state->HasPrefPath(prefs::kSSL3Enabled)) {
153 // Migrate the kSSL3Enabled preference.
154 local_state->SetBoolean(prefs::kSSL3Enabled,
155 user_prefs->GetBoolean(prefs::kSSL3Enabled));
156 }
157 user_prefs->ClearPref(prefs::kSSL3Enabled);
158 }
159 if (user_prefs->HasPrefPath(prefs::kTLS1Enabled)) {
160 if (!local_state->HasPrefPath(prefs::kTLS1Enabled)) {
161 // Migrate the kTLS1Enabled preference.
162 local_state->SetBoolean(prefs::kTLS1Enabled,
163 user_prefs->GetBoolean(prefs::kTLS1Enabled));
164 }
165 user_prefs->ClearPref(prefs::kTLS1Enabled);
166 }
167 }
168
Get()169 net::SSLConfigService* SSLConfigServiceManagerPref::Get() {
170 return ssl_config_service_;
171 }
172
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)173 void SSLConfigServiceManagerPref::Observe(NotificationType type,
174 const NotificationSource& source,
175 const NotificationDetails& details) {
176 base::Thread* io_thread = g_browser_process->io_thread();
177 if (io_thread) {
178 net::SSLConfig new_config;
179 GetSSLConfigFromPrefs(&new_config);
180
181 // Post a task to |io_loop| with the new configuration, so it can
182 // update |cached_config_|.
183 io_thread->message_loop()->PostTask(
184 FROM_HERE,
185 NewRunnableMethod(
186 ssl_config_service_.get(),
187 &SSLConfigServicePref::SetNewSSLConfig,
188 new_config));
189 }
190 }
191
GetSSLConfigFromPrefs(net::SSLConfig * config)192 void SSLConfigServiceManagerPref::GetSSLConfigFromPrefs(
193 net::SSLConfig* config) {
194 config->rev_checking_enabled = rev_checking_enabled_.GetValue();
195 config->ssl3_enabled = ssl3_enabled_.GetValue();
196 config->tls1_enabled = tls1_enabled_.GetValue();
197 SSLConfigServicePref::SetSSLConfigFlags(config);
198 }
199
200 ////////////////////////////////////////////////////////////////////////////////
201 // SSLConfigServiceManager
202
203 // static
CreateDefaultManager(PrefService * user_prefs,PrefService * local_state)204 SSLConfigServiceManager* SSLConfigServiceManager::CreateDefaultManager(
205 PrefService* user_prefs,
206 PrefService* local_state) {
207 return new SSLConfigServiceManagerPref(user_prefs, local_state);
208 }
209