Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 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 "chrome/browser/chromeos/extensions/networking_private_api.h" | |
| 6 | |
| 7 #include "base/bind_helpers.h" | |
| 8 #include "chrome/browser/chromeos/extensions/networking_private_api_factory.h" | |
| 9 #include "chrome/browser/extensions/extension_function_registry.h" | |
| 10 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 11 #include "chromeos/dbus/shill_manager_client.h" | |
| 12 #include "chromeos/dbus/shill_service_client.h" | |
| 13 #include "chromeos/network/onc/onc_constants.h" | |
| 14 #include "chromeos/network/onc/onc_signature.h" | |
| 15 #include "chromeos/network/onc/onc_translation_tables.h" | |
| 16 #include "chromeos/network/onc/onc_translator.h" | |
| 17 #include "dbus/object_path.h" | |
| 18 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 19 | |
| 20 namespace chromeos { | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 // An error returned when no valid services were found. | |
| 25 const char kInvalidResponseError[] = "Error.invalidResponse"; | |
| 26 | |
| 27 // This creates a new ONC dictionary that only contains the information we're | |
| 28 // interested in passing on to JavaScript. | |
| 29 base::DictionaryValue* CreateFilteredResult( | |
| 30 const base::DictionaryValue& properties) { | |
| 31 scoped_ptr<base::DictionaryValue> onc_properties( | |
| 32 onc::TranslateShillServiceToONCPart( | |
| 33 properties, | |
| 34 &onc::kNetworkConfigurationSignature)); | |
| 35 | |
| 36 // Now we filter it so we only include properties that we care about for this | |
| 37 // interface. | |
| 38 static const char* const desired_fields[] = { | |
| 39 onc::network_config::kWiFi, | |
| 40 onc::network_config::kName, | |
| 41 onc::network_config::kGUID, | |
| 42 onc::network_config::kType, | |
| 43 onc::network_config::kConnectionState, | |
| 44 }; | |
| 45 | |
| 46 scoped_ptr<base::DictionaryValue> filtered_result(new base::DictionaryValue); | |
| 47 for (size_t i = 0; i < arraysize(desired_fields); ++i) { | |
| 48 base::Value* value; | |
| 49 if (onc_properties->Get(desired_fields[i], &value)) | |
| 50 filtered_result->Set(desired_fields[i], value->DeepCopy()); | |
| 51 } | |
| 52 return filtered_result.release(); | |
| 53 } | |
| 54 | |
| 55 } // namespace | |
| 56 | |
| 57 //////////////////////////////////////////////////////////////////////////////// | |
| 58 // NetworkingGetPropertiesFunction | |
| 59 | |
| 60 NetworkingGetPropertiesFunction::~NetworkingGetPropertiesFunction() { | |
| 61 } | |
| 62 | |
| 63 bool NetworkingGetPropertiesFunction::RunImpl() { | |
| 64 std::string service_path; | |
| 65 if (!args_->GetString(0, &service_path)) | |
|
not at google - send to devlin
2013/01/23 22:37:52
Do you know about the JSON schema compiler? Ideall
Greg Spencer (Chromium)
2013/01/31 16:40:36
Well, I didn't know about it until I had already c
not at google - send to devlin
2013/02/01 19:09:42
NOTE(chrome-extensions-team): we need to update th
| |
| 66 return false; | |
| 67 | |
| 68 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( | |
| 69 dbus::ObjectPath(service_path), base::Bind( | |
| 70 &NetworkingGetPropertiesFunction::ResultCallback, this)); | |
|
not at google - send to devlin
2013/01/23 22:37:52
nit: line arguments vertically (like above)
Greg Spencer (Chromium)
2013/01/31 16:40:36
Done.
| |
| 71 return true; | |
| 72 } | |
| 73 | |
| 74 void NetworkingGetPropertiesFunction::ResultCallback( | |
| 75 DBusMethodCallStatus call_status, | |
| 76 const base::DictionaryValue& result) { | |
| 77 scoped_ptr<base::DictionaryValue> filtered_result( | |
| 78 CreateFilteredResult(result)); | |
| 79 | |
| 80 SetResult(filtered_result.release()); | |
|
not at google - send to devlin
2013/01/23 22:37:52
And here, you'd make CreateFilteredResult return t
| |
| 81 SendResponse(true); | |
| 82 } | |
| 83 | |
| 84 //////////////////////////////////////////////////////////////////////////////// | |
| 85 // NetworkingGetVisibleNetworksFunction::ResultList | |
| 86 class NetworkingGetVisibleNetworksFunction::ResultList | |
| 87 : public base::RefCounted<ResultList> { | |
|
not at google - send to devlin
2013/01/23 22:37:52
does this really need to be refcounted?
Greg Spencer (Chromium)
2013/01/31 16:40:36
Yes, it's kind of the reason this class exists: it
not at google - send to devlin
2013/02/01 19:09:42
Ok, cool, you're right. However I think I asked th
Greg Spencer (Chromium)
2013/02/01 23:35:55
OK, I like this a little better: at least we can g
not at google - send to devlin
2013/02/02 00:11:32
Well the reason is like I said, at the moment it's
Greg Spencer (Chromium)
2013/02/02 01:06:15
It wasn't too hard to do, so I went ahead and did
| |
| 88 public: | |
| 89 explicit ResultList(int count); | |
| 90 | |
| 91 int count() const { return count_; } | |
| 92 void decrement() { --count_; } | |
| 93 base::ListValue* release() { return list_.release(); } | |
| 94 void Append(base::Value* value); | |
| 95 | |
| 96 private: | |
| 97 friend class base::RefCounted<ResultList>; | |
| 98 ~ResultList(); | |
| 99 | |
| 100 scoped_ptr<base::ListValue> list_; | |
| 101 int count_; | |
| 102 | |
| 103 DISALLOW_COPY_AND_ASSIGN(ResultList); | |
| 104 }; | |
| 105 | |
| 106 NetworkingGetVisibleNetworksFunction::ResultList::ResultList(int count) | |
| 107 : list_(new base::ListValue), count_(count) { | |
| 108 } | |
| 109 | |
| 110 NetworkingGetVisibleNetworksFunction::ResultList::~ResultList() { | |
| 111 } | |
| 112 | |
| 113 void NetworkingGetVisibleNetworksFunction::ResultList::Append( | |
| 114 base::Value* value) { | |
| 115 list_->Append(value); | |
| 116 } | |
| 117 | |
| 118 //////////////////////////////////////////////////////////////////////////////// | |
| 119 // NetworkingGetVisibleNetworksFunction | |
| 120 | |
| 121 NetworkingGetVisibleNetworksFunction::~NetworkingGetVisibleNetworksFunction() { | |
| 122 } | |
| 123 | |
| 124 bool NetworkingGetVisibleNetworksFunction::RunImpl() { | |
| 125 std::string network_type; | |
| 126 if (!args_->GetString(0, &network_type)) | |
| 127 return false; | |
| 128 | |
| 129 DBusThreadManager::Get()->GetShillManagerClient()->GetProperties( | |
| 130 base::Bind( | |
| 131 &NetworkingGetVisibleNetworksFunction::ManagerPropertiesCallback, | |
| 132 this, | |
| 133 network_type)); | |
| 134 return true; | |
| 135 } | |
| 136 | |
| 137 // For each of the available services, fire off a request for its properties. | |
| 138 void NetworkingGetVisibleNetworksFunction::ManagerPropertiesCallback( | |
| 139 const std::string& network_type, | |
| 140 DBusMethodCallStatus call_status, | |
| 141 const base::DictionaryValue& result) { | |
| 142 const base::ListValue* available_services; | |
| 143 if (!result.GetList(flimflam::kServicesProperty, &available_services)) { | |
| 144 LOG(ERROR) | |
| 145 << "ShillManagerClient::GetProperties returned malformed service list."; | |
| 146 error_ = kInvalidResponseError; | |
| 147 SendResponse(false); | |
| 148 return; | |
| 149 } | |
| 150 scoped_refptr<ResultList> result_list( | |
| 151 new ResultList(available_services->GetSize())); | |
| 152 // If there just are no services, return an empty list. | |
| 153 if (available_services->GetSize() == 0) { | |
| 154 SetResult(result_list->release()); | |
| 155 SendResponse(true); | |
| 156 return; | |
| 157 } | |
| 158 for (base::ListValue::const_iterator iter = available_services->begin(); | |
| 159 iter != available_services->end(); ++iter) { | |
| 160 std::string service_path; | |
| 161 if (!(*iter)->GetAsString(&service_path)) { | |
| 162 LOG(ERROR) | |
| 163 << "ShillManagerClient::GetProperties returned malformed service."; | |
| 164 result_list->decrement(); | |
| 165 continue; | |
| 166 } | |
| 167 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( | |
| 168 dbus::ObjectPath(service_path), | |
| 169 base::Bind( | |
| 170 &NetworkingGetVisibleNetworksFunction::ServicePropertiesCallback, | |
| 171 this, | |
| 172 service_path, | |
| 173 network_type, | |
| 174 result_list)); | |
| 175 } | |
| 176 // All of the service paths were malformed, so we fail. | |
| 177 if (result_list->count() == 0) { | |
| 178 error_ = kInvalidResponseError; | |
| 179 SendResponse(false); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 // If this network is of the appropriate type, add it to the results and | |
| 184 // decrement the count. If the count hits zero, then send the result. | |
| 185 void NetworkingGetVisibleNetworksFunction::ServicePropertiesCallback( | |
| 186 const std::string& service_path, | |
| 187 const std::string& network_type, | |
| 188 scoped_refptr<ResultList> result_list, | |
| 189 DBusMethodCallStatus call_status, | |
| 190 const base::DictionaryValue& result) { | |
| 191 if (call_status == DBUS_METHOD_CALL_SUCCESS) { | |
| 192 scoped_ptr<base::DictionaryValue> filtered_result( | |
| 193 CreateFilteredResult(result)); | |
| 194 | |
| 195 std::string onc_type; | |
| 196 if (filtered_result->GetString(onc::network_config::kType, &onc_type) && | |
| 197 (onc_type == network_type || | |
| 198 network_type == onc::network_type::kAllTypes)) { | |
| 199 // TODO(gspencer): For now the "guid" we send back is going to look | |
| 200 // remarkably like the service path. Once this code starts using the | |
| 201 // NetworkStateHandler instead of Shill directly, we should remove | |
| 202 // this line so that we're sending back the actual GUID. The | |
| 203 // JavaScript shouldn't care: this ID is opaque to it, and it | |
| 204 // shouldn't store it anywhere. | |
| 205 filtered_result->SetString(onc::network_config::kGUID, service_path); | |
| 206 | |
| 207 result_list->Append(filtered_result.release()); | |
| 208 } | |
| 209 } | |
| 210 // We must decrement the count each time we get a callback, regardless of the | |
| 211 // outcome, or we'll never send a response. | |
| 212 result_list->decrement(); | |
| 213 if (result_list->count() == 0) { | |
| 214 SetResult(result_list->release()); | |
| 215 SendResponse(true); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 //////////////////////////////////////////////////////////////////////////////// | |
| 220 // NetworkingRequestConnectFunction | |
| 221 | |
| 222 NetworkingRequestConnectFunction::~NetworkingRequestConnectFunction() { | |
| 223 } | |
| 224 | |
| 225 void NetworkingRequestConnectFunction::ConnectRequestSuccess() { | |
| 226 SendResponse(true); | |
| 227 } | |
| 228 | |
| 229 void NetworkingRequestConnectFunction::ConnectRequestFailed( | |
| 230 const std::string& errorName, | |
|
not at google - send to devlin
2013/01/23 22:37:52
error_name not errorName (same below etc)
Greg Spencer (Chromium)
2013/01/31 16:40:36
Done.
| |
| 231 const std::string& errorMessage) { | |
| 232 error_ = errorName; | |
| 233 SendResponse(false); | |
| 234 } | |
| 235 | |
| 236 bool NetworkingRequestConnectFunction::RunImpl() { | |
| 237 std::string guid; | |
| 238 if (!args_->GetString(0, &guid)) | |
| 239 return false; | |
| 240 | |
| 241 // TODO(gspencer): For now, the "guid" we receive from the JavaScript is going | |
| 242 // to be the service path. Fix this so it actually looks up the service path | |
| 243 // from the GUID once we're using the NetworkStateHandler. | |
| 244 std::string service_path = guid; | |
| 245 | |
| 246 DBusThreadManager::Get()->GetShillServiceClient()->Connect( | |
| 247 dbus::ObjectPath(service_path), | |
| 248 base::Bind(&NetworkingRequestConnectFunction::ConnectRequestSuccess, | |
| 249 this), | |
| 250 base::Bind(&NetworkingRequestConnectFunction::ConnectRequestFailed, | |
| 251 this)); | |
| 252 return true; | |
| 253 } | |
| 254 | |
| 255 //////////////////////////////////////////////////////////////////////////////// | |
| 256 // NetworkingRequestDisconnectFunction | |
| 257 | |
| 258 NetworkingRequestDisconnectFunction::~NetworkingRequestDisconnectFunction() { | |
| 259 } | |
| 260 | |
| 261 void NetworkingRequestDisconnectFunction::DisconnectRequestSuccess() { | |
| 262 SendResponse(true); | |
| 263 } | |
| 264 | |
| 265 void NetworkingRequestDisconnectFunction::DisconnectRequestFailed( | |
| 266 const std::string& errorName, | |
| 267 const std::string& errorMessage) { | |
| 268 error_ = errorName; | |
| 269 SendResponse(false); | |
| 270 } | |
| 271 | |
| 272 bool NetworkingRequestDisconnectFunction::RunImpl() { | |
| 273 std::string service_path; | |
| 274 if (!args_->GetString(0, &service_path)) | |
| 275 return false; | |
| 276 | |
| 277 DBusThreadManager::Get()->GetShillServiceClient()->Connect( | |
| 278 dbus::ObjectPath(service_path), | |
| 279 base::Bind(&NetworkingRequestDisconnectFunction::DisconnectRequestSuccess, | |
| 280 this), | |
| 281 base::Bind(&NetworkingRequestDisconnectFunction::DisconnectRequestFailed, | |
| 282 this)); | |
| 283 return true; | |
| 284 } | |
| 285 | |
| 286 //////////////////////////////////////////////////////////////////////////////// | |
| 287 // NetworkingPrivateAPI | |
| 288 | |
| 289 NetworkingPrivateAPI::NetworkingPrivateAPI(Profile* profile) { | |
| 290 ExtensionFunctionRegistry* registry = | |
| 291 ExtensionFunctionRegistry::GetInstance(); | |
| 292 registry->RegisterFunction<NetworkingGetPropertiesFunction>(); | |
| 293 registry->RegisterFunction<NetworkingGetVisibleNetworksFunction>(); | |
| 294 registry->RegisterFunction<NetworkingRequestConnectFunction>(); | |
| 295 registry->RegisterFunction<NetworkingRequestDisconnectFunction>(); | |
| 296 } | |
| 297 | |
| 298 NetworkingPrivateAPI::~NetworkingPrivateAPI() { | |
| 299 } | |
| 300 | |
| 301 void NetworkingPrivateAPI::Shutdown() { | |
| 302 } | |
| 303 | |
| 304 // static | |
| 305 NetworkingPrivateAPI* NetworkingPrivateAPI::Get(Profile* profile) { | |
| 306 return NetworkingPrivateAPIFactory::GetForProfile(profile); | |
| 307 } | |
| 308 | |
| 309 } // namespace chromeos | |
| OLD | NEW |