1 // Copyright 2015 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.
9 #include "base/lazy_instance.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "chromeos/network/managed_network_configuration_handler.h"
13 #include "chromeos/network/network_handler.h"
14 #include "chromeos/network/network_state.h"
15 #include "chromeos/network/network_state_handler.h"
16 #include "extensions/browser/api/networking_config/networking_config_service.h"
17 #include "extensions/common/api/networking_config.h"
19 namespace extensions
{
23 bool IsValidNonEmptyHexString(const std::string
& input
) {
24 size_t count
= input
.size();
25 if (count
== 0 || (count
% 2) != 0)
27 for (const char& c
: input
)
28 if (!base::IsHexDigit
<char>(c
))
35 NetworkingConfigService::AuthenticationResult::AuthenticationResult()
36 : authentication_state(NetworkingConfigService::NOTRY
) {
39 NetworkingConfigService::AuthenticationResult::AuthenticationResult(
40 ExtensionId extension_id
,
42 AuthenticationState authentication_state
)
43 : extension_id(extension_id
),
45 authentication_state(authentication_state
) {
48 NetworkingConfigService::NetworkingConfigService(
49 content::BrowserContext
* browser_context
,
50 scoped_ptr
<EventDelegate
> event_delegate
,
51 ExtensionRegistry
* extension_registry
)
52 : browser_context_(browser_context
),
53 registry_observer_(this),
54 event_delegate_(event_delegate
.Pass()),
56 registry_observer_
.Add(extension_registry
);
59 NetworkingConfigService::~NetworkingConfigService() {
62 void NetworkingConfigService::OnExtensionUnloaded(
63 content::BrowserContext
* browser_context
,
64 const Extension
* extension
,
65 UnloadedExtensionInfo::Reason reason
) {
66 UnregisterExtension(extension
->id());
69 std::string
NetworkingConfigService::LookupExtensionIdForHexSsid(
70 std::string hex_ssid
) const {
71 // Transform hex_ssid to uppercase.
72 transform(hex_ssid
.begin(), hex_ssid
.end(), hex_ssid
.begin(), toupper
);
74 const auto it
= hex_ssid_to_extension_id_
.find(hex_ssid
);
75 if (it
== hex_ssid_to_extension_id_
.end())
80 bool NetworkingConfigService::IsRegisteredForCaptivePortalEvent(
81 std::string extension_id
) const {
82 return event_delegate_
->HasExtensionRegisteredForEvent(extension_id
);
85 bool NetworkingConfigService::RegisterHexSsid(std::string hex_ssid
,
86 const std::string
& extension_id
) {
87 if (!IsValidNonEmptyHexString(hex_ssid
)) {
88 LOG(ERROR
) << "\'" << hex_ssid
<< "\' is not a valid hex encoded string.";
92 // Transform hex_ssid to uppercase.
93 transform(hex_ssid
.begin(), hex_ssid
.end(), hex_ssid
.begin(), toupper
);
95 return hex_ssid_to_extension_id_
.insert(make_pair(hex_ssid
, extension_id
))
99 void NetworkingConfigService::UnregisterExtension(
100 const std::string
& extension_id
) {
101 for (auto it
= hex_ssid_to_extension_id_
.begin();
102 it
!= hex_ssid_to_extension_id_
.end();) {
103 if (it
->second
== extension_id
)
104 hex_ssid_to_extension_id_
.erase(it
++);
110 const NetworkingConfigService::AuthenticationResult
&
111 NetworkingConfigService::GetAuthenticationResult() const {
112 return authentication_result_
;
115 void NetworkingConfigService::ResetAuthenticationResult() {
116 authentication_result_
= AuthenticationResult();
117 authentication_callback_
.Reset();
120 void NetworkingConfigService::SetAuthenticationResult(
121 const AuthenticationResult
& authentication_result
) {
122 authentication_result_
= authentication_result
;
123 if (authentication_result
.authentication_state
!= SUCCESS
) {
124 LOG(WARNING
) << "Captive Portal Authentication failed.";
128 if (!authentication_callback_
.is_null()) {
129 authentication_callback_
.Run();
130 authentication_callback_
.Reset();
134 void NetworkingConfigService::OnGotProperties(
135 const std::string
& extension_id
,
136 const std::string
& guid
,
137 const base::Closure
& authentication_callback
,
138 const std::string
& service_path
,
139 const base::DictionaryValue
& onc_network_config
) {
140 authentication_result_
= NetworkingConfigService::AuthenticationResult(
141 std::string(), guid
, NetworkingConfigService::NOTRY
);
142 authentication_callback_
= authentication_callback
;
144 // Try to extract |bssid| field.
145 const base::DictionaryValue
* wifi_with_state
= nullptr;
147 scoped_ptr
<Event
> event
;
148 if (onc_network_config
.GetDictionaryWithoutPathExpansion(
149 ::onc::network_config::kWiFi
, &wifi_with_state
) &&
150 wifi_with_state
->GetStringWithoutPathExpansion(::onc::wifi::kBSSID
,
152 event
= CreatePortalDetectedEventAndDispatch(extension_id
, guid
, &bssid
);
154 event
= CreatePortalDetectedEventAndDispatch(extension_id
, guid
, nullptr);
157 EventRouter::Get(browser_context_
)
158 ->DispatchEventToExtension(extension_id
, event
.Pass());
161 void NetworkingConfigService::OnGetPropertiesFailed(
162 const std::string
& extension_id
,
163 const std::string
& guid
,
164 const std::string
& error_name
,
165 scoped_ptr
<base::DictionaryValue
> error_data
) {
166 LOG(WARNING
) << "Failed to determine BSSID for network with guid " << guid
167 << ": " << error_name
;
168 scoped_ptr
<Event
> event
=
169 CreatePortalDetectedEventAndDispatch(extension_id
, guid
, nullptr);
170 EventRouter::Get(browser_context_
)
171 ->DispatchEventToExtension(extension_id
, event
.Pass());
174 scoped_ptr
<Event
> NetworkingConfigService::CreatePortalDetectedEventAndDispatch(
175 const std::string
& extension_id
,
176 const std::string
& guid
,
177 const std::string
* bssid
) {
178 const chromeos::NetworkState
* network
= chromeos::NetworkHandler::Get()
179 ->network_state_handler()
180 ->GetNetworkStateFromGuid(guid
);
184 // Populate the NetworkInfo object.
185 api::networking_config::NetworkInfo network_info
;
186 network_info
.type
= api::networking_config::NETWORK_TYPE_WIFI
;
187 const std::vector
<uint8_t>& raw_ssid
= network
->raw_ssid();
188 std::string hex_ssid
=
189 base::HexEncode(vector_as_array(&raw_ssid
), raw_ssid
.size());
190 network_info
.hex_ssid
= make_scoped_ptr(new std::string(hex_ssid
));
191 network_info
.ssid
= make_scoped_ptr(new std::string(network
->name()));
192 network_info
.guid
= make_scoped_ptr(new std::string(network
->guid()));
194 network_info
.bssid
.reset(new std::string(*bssid
));
195 scoped_ptr
<base::ListValue
> results
=
196 api::networking_config::OnCaptivePortalDetected::Create(network_info
);
197 scoped_ptr
<Event
> event(
198 new Event(events::NETWORKING_CONFIG_ON_CAPTIVE_PORTAL_DETECTED
,
199 api::networking_config::OnCaptivePortalDetected::kEventName
,
204 void NetworkingConfigService::DispatchPortalDetectedEvent(
205 const std::string
& extension_id
,
206 const std::string
& guid
,
207 const base::Closure
& authentication_callback
) {
208 // This dispatch starts a new cycle of portal detection and authentication.
209 // Ensure that any old |authentication_callback_| is dropped.
210 authentication_callback_
.Reset();
212 // Determine |service_path| of network identified by |guid|.
213 chromeos::NetworkHandler
* network_handler
= chromeos::NetworkHandler::Get();
214 const chromeos::NetworkState
* network
=
215 network_handler
->network_state_handler()->GetNetworkStateFromGuid(guid
);
218 const std::string service_path
= network
->path();
220 network_handler
->managed_network_configuration_handler()->GetProperties(
221 service_path
, base::Bind(&NetworkingConfigService::OnGotProperties
,
222 weak_factory_
.GetWeakPtr(), extension_id
, guid
,
223 authentication_callback
),
224 base::Bind(&NetworkingConfigService::OnGetPropertiesFailed
,
225 weak_factory_
.GetWeakPtr(), extension_id
, guid
));
228 } // namespace extensions