summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/extensions/networking_private_api.cc303
-rw-r--r--chrome/browser/chromeos/extensions/networking_private_api.h110
-rw-r--r--chrome/browser/chromeos/extensions/networking_private_apitest.cc28
-rw-r--r--chrome/browser/extensions/extension_function_histogram_value.h4
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/extensions/api/_permission_features.json5
-rw-r--r--chrome/common/extensions/api/api.gyp1
-rw-r--r--chrome/common/extensions/api/networking_private.json104
-rw-r--r--chrome/common/extensions/permissions/api_permission.cc2
-rw-r--r--chrome/common/extensions/permissions/api_permission.h1
-rw-r--r--chrome/common/extensions/permissions/permission_set_unittest.cc1
-rw-r--r--chrome/test/data/extensions/api_test/networking/manifest.json13
-rw-r--r--chrome/test/data/extensions/api_test/networking/test.js98
-rw-r--r--chromeos/dbus/shill_service_client.cc5
15 files changed, 678 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/extensions/networking_private_api.cc b/chrome/browser/chromeos/extensions/networking_private_api.cc
new file mode 100644
index 0000000..077619e
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/networking_private_api.cc
@@ -0,0 +1,303 @@
+// Copyright (c) 2013 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 "chrome/browser/chromeos/extensions/networking_private_api.h"
+
+#include "base/bind_helpers.h"
+#include "chrome/browser/extensions/extension_function_registry.h"
+#include "chrome/common/extensions/api/networking_private.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/network/onc/onc_constants.h"
+#include "chromeos/network/onc/onc_signature.h"
+#include "chromeos/network/onc/onc_translation_tables.h"
+#include "chromeos/network/onc/onc_translator.h"
+#include "dbus/object_path.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+using namespace chromeos;
+namespace api = extensions::api::networking_private;
+
+namespace {
+
+// An error returned when no valid services were found.
+const char kInvalidResponseError[] = "Error.invalidResponse";
+
+// This creates a new ONC dictionary that only contains the information we're
+// interested in passing on to JavaScript.
+scoped_ptr<api::NetworkProperties> CreateFilteredResult(
+ const base::DictionaryValue& properties) {
+ scoped_ptr<base::DictionaryValue> onc_properties(
+ onc::TranslateShillServiceToONCPart(
+ properties,
+ &onc::kNetworkConfigurationSignature));
+
+ // Now we filter it so we only include properties that we care about for this
+ // interface.
+ static const char* const desired_fields[] = {
+ onc::network_config::kWiFi,
+ onc::network_config::kName,
+ onc::network_config::kGUID,
+ onc::network_config::kType,
+ onc::network_config::kConnectionState,
+ };
+
+ scoped_ptr<api::NetworkProperties> filtered_result(
+ new api::NetworkProperties);
+ for (size_t i = 0; i < arraysize(desired_fields); ++i) {
+ base::Value* value;
+ if (onc_properties->Get(desired_fields[i], &value))
+ filtered_result->additional_properties.Set(desired_fields[i],
+ value->DeepCopy());
+ }
+
+ return filtered_result.Pass();
+}
+
+class ResultList : public base::RefCounted<ResultList> {
+ public:
+ typedef base::Callback<void(const std::string& error,
+ scoped_ptr<base::ListValue>)> ResultCallback;
+
+ ResultList(const std::string& type, const ResultCallback& callback)
+ : callback_(callback) {
+ DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
+ base::Bind(&ResultList::ManagerPropertiesCallback, this, type));
+ }
+
+ scoped_ptr<base::ListValue> GetResults() {
+ return api::GetVisibleNetworks::Results::Create(list_);
+ }
+
+ private:
+ friend class base::RefCounted<ResultList>;
+
+ ~ResultList() {
+ callback_.Run(std::string(), GetResults());
+ }
+
+ void Append(api::NetworkProperties* value) {
+ list_.push_back(linked_ptr<api::NetworkProperties>(value));
+ }
+
+ // Receives the result of a call to GetProperties on the Shill Manager API.
+ void ManagerPropertiesCallback(const std::string& network_type,
+ chromeos::DBusMethodCallStatus call_status,
+ const base::DictionaryValue& result);
+
+ // Receives the result of a call to GetProperties on the Shill Service API.
+ void ServicePropertiesCallback(const std::string& service_path,
+ const std::string& network_type,
+ chromeos::DBusMethodCallStatus call_status,
+ const base::DictionaryValue& result);
+
+ std::vector<linked_ptr<api::NetworkProperties> > list_;
+ ResultCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResultList);
+};
+
+// For each of the available services, fire off a request for its properties.
+void ResultList::ManagerPropertiesCallback(
+ const std::string& network_type,
+ DBusMethodCallStatus call_status,
+ const base::DictionaryValue& result) {
+ const base::ListValue* available_services;
+ if (!result.GetList(flimflam::kServicesProperty, &available_services)) {
+ LOG(ERROR)
+ << "ShillManagerClient::GetProperties returned malformed service list.";
+ callback_.Run(kInvalidResponseError, make_scoped_ptr(new base::ListValue));
+ return;
+ }
+ // If there just are no services, return an empty list.
+ if (available_services->GetSize() == 0) {
+ callback_.Run(std::string(), make_scoped_ptr(new base::ListValue));
+ return;
+ }
+ for (base::ListValue::const_iterator iter = available_services->begin();
+ iter != available_services->end(); ++iter) {
+ std::string service_path;
+ if (!(*iter)->GetAsString(&service_path)) {
+ LOG(ERROR)
+ << "ShillManagerClient::GetProperties returned malformed service.";
+ continue;
+ }
+
+ DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
+ dbus::ObjectPath(service_path),
+ base::Bind(
+ &ResultList::ServicePropertiesCallback,
+ this,
+ service_path,
+ network_type));
+ }
+}
+
+void ResultList::ServicePropertiesCallback(
+ const std::string& service_path,
+ const std::string& network_type,
+ DBusMethodCallStatus call_status,
+ const base::DictionaryValue& result) {
+ if (call_status == DBUS_METHOD_CALL_SUCCESS) {
+ scoped_ptr<api::NetworkProperties> filtered_result(
+ CreateFilteredResult(result));
+
+ std::string onc_type;
+ if (filtered_result->additional_properties.GetString(
+ onc::network_config::kType, &onc_type) &&
+ (onc_type == network_type ||
+ network_type == onc::network_type::kAllTypes)) {
+ // TODO(gspencer): For now the "GUID" we send back is going to look
+ // remarkably like the service path. Once this code starts using the
+ // NetworkStateHandler instead of Shill directly, we should remove
+ // this line so that we're sending back the actual GUID. The
+ // JavaScript shouldn't care: this ID is opaque to it, and it
+ // shouldn't store it anywhere.
+ filtered_result->additional_properties.SetString(
+ onc::network_config::kGUID, service_path);
+
+ Append(filtered_result.release());
+ }
+ }
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateGetPropertiesFunction
+
+NetworkingPrivateGetPropertiesFunction::
+ ~NetworkingPrivateGetPropertiesFunction() {
+}
+
+bool NetworkingPrivateGetPropertiesFunction::RunImpl() {
+ scoped_ptr<api::GetProperties::Params> params =
+ api::GetProperties::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ // TODO(gspencer): Currently we're using the service path as the
+ // |network_guid|. Eventually this should be using the real GUID.
+ DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
+ dbus::ObjectPath(params->network_guid),
+ base::Bind(&NetworkingPrivateGetPropertiesFunction::ResultCallback,
+ this));
+ return true;
+}
+
+void NetworkingPrivateGetPropertiesFunction::ResultCallback(
+ DBusMethodCallStatus call_status,
+ const base::DictionaryValue& result) {
+ scoped_ptr<api::NetworkProperties> filtered_result(
+ CreateFilteredResult(result));
+ results_ = api::GetProperties::Results::Create(*filtered_result);
+ SendResponse(true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateGetVisibleNetworksFunction
+
+NetworkingPrivateGetVisibleNetworksFunction::
+~NetworkingPrivateGetVisibleNetworksFunction() {
+}
+
+bool NetworkingPrivateGetVisibleNetworksFunction::RunImpl() {
+ scoped_ptr<api::GetVisibleNetworks::Params> params =
+ api::GetVisibleNetworks::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ scoped_refptr<ResultList> result_list(new ResultList(
+ api::GetVisibleNetworks::Params::ToString(params->type),
+ base::Bind(
+ &NetworkingPrivateGetVisibleNetworksFunction::SendResultCallback,
+ this)));
+ return true;
+}
+
+void NetworkingPrivateGetVisibleNetworksFunction::SendResultCallback(
+ const std::string& error,
+ scoped_ptr<base::ListValue> result_list) {
+ if (!error.empty()) {
+ error_ = error;
+ SendResponse(false);
+ } else {
+ results_.reset(result_list.release());
+ SendResponse(true);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateStartConnectFunction
+
+NetworkingPrivateStartConnectFunction::
+ ~NetworkingPrivateStartConnectFunction() {
+}
+
+void NetworkingPrivateStartConnectFunction::ConnectionStartSuccess() {
+ SendResponse(true);
+}
+
+void NetworkingPrivateStartConnectFunction::ConnectionStartFailed(
+ const std::string& error_name,
+ const std::string& error_message) {
+ error_ = error_name;
+ SendResponse(false);
+}
+
+bool NetworkingPrivateStartConnectFunction::RunImpl() {
+ scoped_ptr<api::StartConnect::Params> params =
+ api::StartConnect::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ // TODO(gspencer): For now, the "GUID" we receive from the JavaScript is going
+ // to be the service path. Fix this so it actually looks up the service path
+ // from the GUID once we're using the NetworkStateHandler.
+ std::string service_path = params->network_guid;
+
+ DBusThreadManager::Get()->GetShillServiceClient()->Connect(
+ dbus::ObjectPath(service_path),
+ base::Bind(
+ &NetworkingPrivateStartConnectFunction::ConnectionStartSuccess,
+ this),
+ base::Bind(&NetworkingPrivateStartConnectFunction::ConnectionStartFailed,
+ this));
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NetworkingPrivateStartDisconnectFunction
+
+NetworkingPrivateStartDisconnectFunction::
+ ~NetworkingPrivateStartDisconnectFunction() {
+}
+
+void NetworkingPrivateStartDisconnectFunction::DisconnectionStartSuccess() {
+ SendResponse(true);
+}
+
+void NetworkingPrivateStartDisconnectFunction::DisconnectionStartFailed(
+ const std::string& error_name,
+ const std::string& error_message) {
+ error_ = error_name;
+ SendResponse(false);
+}
+
+bool NetworkingPrivateStartDisconnectFunction::RunImpl() {
+ scoped_ptr<api::StartDisconnect::Params> params =
+ api::StartDisconnect::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ // TODO(gspencer): Currently the |network_guid| parameter is storing the
+ // service path. Convert to using the actual GUID when we start using
+ // the NetworkStateHandler.
+ DBusThreadManager::Get()->GetShillServiceClient()->Connect(
+ dbus::ObjectPath(params->network_guid),
+ base::Bind(
+ &NetworkingPrivateStartDisconnectFunction::DisconnectionStartSuccess,
+ this),
+ base::Bind(
+ &NetworkingPrivateStartDisconnectFunction::DisconnectionStartFailed,
+ this));
+ return true;
+}
diff --git a/chrome/browser/chromeos/extensions/networking_private_api.h b/chrome/browser/chromeos/extensions/networking_private_api.h
new file mode 100644
index 0000000..df4d567
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/networking_private_api.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2013 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.
+
+// These classes implement the chrome.networkingPrivate JavaScript extension
+// API.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_API_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_API_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "chromeos/dbus/dbus_method_call_status.h"
+
+// Implements the chrome.networkingPrivate.getProperties method.
+class NetworkingPrivateGetPropertiesFunction : public AsyncExtensionFunction {
+ public:
+ NetworkingPrivateGetPropertiesFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networkingPrivate.getProperties",
+ NETWORKINGPRIVATE_GETPROPERTIES);
+
+ protected:
+ virtual ~NetworkingPrivateGetPropertiesFunction();
+
+ // AsyncExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ void ResultCallback(chromeos::DBusMethodCallStatus call_status,
+ const base::DictionaryValue& result);
+ DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateGetPropertiesFunction);
+};
+
+// Implements the chrome.networkingPrivate.getVisibleNetworks method.
+class NetworkingPrivateGetVisibleNetworksFunction
+ : public AsyncExtensionFunction {
+ public:
+ NetworkingPrivateGetVisibleNetworksFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networkingPrivate.getVisibleNetworks",
+ NETWORKINGPRIVATE_GETVISIBLENETWORKS);
+
+ protected:
+ virtual ~NetworkingPrivateGetVisibleNetworksFunction();
+
+ // AsyncExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ // Gets called when all the results are in.
+ void SendResultCallback(const std::string& error,
+ scoped_ptr<base::ListValue> result_list);
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateGetVisibleNetworksFunction);
+};
+
+// Implements the chrome.networkingPrivate.startConnect method.
+class NetworkingPrivateStartConnectFunction : public AsyncExtensionFunction {
+ public:
+ NetworkingPrivateStartConnectFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networkingPrivate.startConnect",
+ NETWORKINGPRIVATE_STARTCONNECT);
+
+ protected:
+ virtual ~NetworkingPrivateStartConnectFunction();
+
+ // AsyncExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ // Called when the request to connect succeeds. Doesn't mean that the connect
+ // itself succeeded, just that the request did.
+ void ConnectionStartSuccess();
+
+ void ConnectionStartFailed(const std::string& error_name,
+ const std::string& error_message);
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateStartConnectFunction);
+};
+
+// Implements the chrome.networkingPrivate.startDisconnect method.
+class NetworkingPrivateStartDisconnectFunction
+ : public AsyncExtensionFunction {
+ public:
+ NetworkingPrivateStartDisconnectFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networkingPrivate.startDisconnect",
+ NETWORKINGPRIVATE_STARTDISCONNECT);
+
+ protected:
+ virtual ~NetworkingPrivateStartDisconnectFunction();
+
+ // AsyncExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ // Called when the request to disconnect succeeds. Doesn't mean that the
+ // disconnect itself succeeded, just that the request did.
+ void DisconnectionStartSuccess();
+
+ void DisconnectionStartFailed(const std::string& error_name,
+ const std::string& error_message);
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateStartDisconnectFunction);
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_NETWORKING_PRIVATE_API_H_
diff --git a/chrome/browser/chromeos/extensions/networking_private_apitest.cc b/chrome/browser/chromeos/extensions/networking_private_apitest.cc
new file mode 100644
index 0000000..d911ff9
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/networking_private_apitest.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 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 <stdio.h>
+
+#include "base/stl_util.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/ui_test_utils.h"
+
+namespace chromeos {
+
+class ExtensionNetworkingPrivateApiTest : public ExtensionApiTest {
+ public:
+ // Whitelist the extension ID of the test extension.
+ virtual void SetUpCommandLine(CommandLine* command_line) {
+ ExtensionApiTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(
+ switches::kWhitelistedExtensionID, "epcifkihnkjgphfkloaaleeakhpmgdmn");
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(ExtensionNetworkingPrivateApiTest, BasicFunctions) {
+ ASSERT_TRUE(RunComponentExtensionTest("networking")) << message_;
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h
index 76f0f92..831aabd 100644
--- a/chrome/browser/extensions/extension_function_histogram_value.h
+++ b/chrome/browser/extensions/extension_function_histogram_value.h
@@ -466,6 +466,10 @@ enum HistogramValue {
FILEBROWSERPRIVATE_VALIDATEPATHNAMELENGTH,
BROWSINGDATA_SETTINGS,
WEBSTOREPRIVATE_GETISLAUNCHERENABLED,
+ NETWORKINGPRIVATE_GETPROPERTIES,
+ NETWORKINGPRIVATE_GETVISIBLENETWORKS,
+ NETWORKINGPRIVATE_STARTCONNECT,
+ NETWORKINGPRIVATE_STARTDISCONNECT,
ENUM_BOUNDARY // Last entry: Add new entries above.
};
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 90f6dfa..7667702 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -681,6 +681,8 @@
'browser/chromeos/extensions/input_method_api.h',
'browser/chromeos/extensions/media_player_api.cc',
'browser/chromeos/extensions/media_player_api.h',
+ 'browser/chromeos/extensions/networking_private_api.cc',
+ 'browser/chromeos/extensions/networking_private_api.h',
'browser/chromeos/extensions/wallpaper_manager_util.cc',
'browser/chromeos/extensions/wallpaper_manager_util.h',
'browser/chromeos/extensions/wallpaper_private_api.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 3c77ec9..932371f 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -995,6 +995,7 @@
'browser/chromeos/extensions/file_browser_resource_throttle_browsertest.cc',
'browser/chromeos/extensions/info_private_apitest.cc',
'browser/chromeos/extensions/input_method_apitest_chromeos.cc',
+ 'browser/chromeos/extensions/networking_private_apitest.cc',
'browser/chromeos/extensions/power/power_api_browsertest.cc',
'browser/chromeos/extensions/wallpaper_private_apitest.cc',
'browser/chromeos/kiosk_mode/mock_kiosk_mode_settings.cc',
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 3a48fe7..2bc79bd 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -252,6 +252,11 @@
"ionpfmkccalenbmnddpbmocokhaknphg" // Quickoffice dev
]
},
+ "networkingPrivate": {
+ "channel": "dev",
+ "extension_types": ["extension", "packaged_app"],
+ "location": "component"
+ },
"notifications": {
"channel": "stable",
"extension_types": [
diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp
index 3215b1b..a2c7457 100644
--- a/chrome/common/extensions/api/api.gyp
+++ b/chrome/common/extensions/api/api.gyp
@@ -54,6 +54,7 @@
'management.json',
'media_galleries.idl',
'media_galleries_private.idl',
+ 'networking_private.json',
'page_capture.json',
'permissions.json',
'push_messaging.idl',
diff --git a/chrome/common/extensions/api/networking_private.json b/chrome/common/extensions/api/networking_private.json
new file mode 100644
index 0000000..a567709
--- /dev/null
+++ b/chrome/common/extensions/api/networking_private.json
@@ -0,0 +1,104 @@
+// Copyright (c) 2013 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.
+
+[
+ {
+ "namespace":"networkingPrivate",
+ "compiler_options": {
+ "implemented_in": "chrome/browser/chromeos/extensions/networking_private_api.h"
+ },
+ "platforms": ["chromeos"],
+ "types" : [
+ {
+ "id": "NetworkProperties",
+ "type": "object",
+ "additionalProperties": { "type": "any" }
+ }
+ ],
+ "functions": [
+ {
+ "name": "getProperties",
+ "description": "Gets the properties of the network with id networkGuid.",
+ "parameters": [
+ {
+ "name": "networkGuid",
+ "type": "string",
+ "description": "The unique identifier of the network to get properties from."
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "parameters": [
+ {
+ "name": "properties",
+ "$ref": "NetworkProperties",
+ "description": "Results of the query for network properties."
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "getVisibleNetworks",
+ "description": "Gets the list of visible networks.",
+ "parameters": [
+ {
+ "name": "type",
+ "type": "string",
+ "enum": ["Ethernet", "WiFi", "Bluetooth", "Cellular", "VPN", "All"],
+ "description": "The type of networks to return."
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": [
+ {
+ "name": "networkList",
+ "type": "array",
+ "items": { "$ref": "NetworkProperties" }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "startConnect",
+ "description": "Starts a connection to the network with networkGuid.",
+ "parameters": [
+ {
+ "name": "networkGuid",
+ "type": "string",
+ "description": "The unique identifier of the network to connect to."
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": [],
+ "description": "A callback function that indicates that a connection has been initiated."
+ }
+ ]
+ },
+ {
+ "name": "startDisconnect",
+ "description": "Starts a disconnect from the network with networkGuid.",
+ "parameters": [
+ {
+ "name": "networkGuid",
+ "type": "string",
+ "description": "The unique identifier of the network to disconnect from."
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": [],
+ "description": "A callback function that indicates that a disconnect has been initiated."
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/chrome/common/extensions/permissions/api_permission.cc b/chrome/common/extensions/permissions/api_permission.cc
index d5ca037..22ac180 100644
--- a/chrome/common/extensions/permissions/api_permission.cc
+++ b/chrome/common/extensions/permissions/api_permission.cc
@@ -256,6 +256,8 @@ void APIPermissionInfo::RegisterAllPermissions(
kFlagCannotBeOptional },
{ APIPermission::kFileBrowserPrivate, "fileBrowserPrivate",
kFlagCannotBeOptional },
+ { APIPermission::kNetworkingPrivate, "networkingPrivate",
+ kFlagCannotBeOptional },
{ APIPermission::kManagedModePrivate, "managedModePrivate",
kFlagCannotBeOptional },
{ APIPermission::kMediaPlayerPrivate, "mediaPlayerPrivate",
diff --git a/chrome/common/extensions/permissions/api_permission.h b/chrome/common/extensions/permissions/api_permission.h
index 3336de7..f0cc58c 100644
--- a/chrome/common/extensions/permissions/api_permission.h
+++ b/chrome/common/extensions/permissions/api_permission.h
@@ -86,6 +86,7 @@ class APIPermission {
kMediaGalleriesPrivate,
kMediaPlayerPrivate,
kMetricsPrivate,
+ kNetworkingPrivate,
kNotification,
kPageCapture,
kPointerLock,
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 77fe843..836f090 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -721,6 +721,7 @@ TEST(PermissionsTest, PermissionMessages) {
skip.insert(APIPermission::kMediaGalleriesPrivate);
skip.insert(APIPermission::kMediaPlayerPrivate);
skip.insert(APIPermission::kMetricsPrivate);
+ skip.insert(APIPermission::kNetworkingPrivate);
skip.insert(APIPermission::kRtcPrivate);
skip.insert(APIPermission::kSystemPrivate);
skip.insert(APIPermission::kTerminalPrivate);
diff --git a/chrome/test/data/extensions/api_test/networking/manifest.json b/chrome/test/data/extensions/api_test/networking/manifest.json
new file mode 100644
index 0000000..0847c01
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/networking/manifest.json
@@ -0,0 +1,13 @@
+{
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC74Vbx3EbhPc/FOvn6+HxCjMSml0HdPMiuRjj5a3b+MnRML1iJ9OAgbKUYJ/u3s25/cGq8pNB0NbyupHGEqvqAE7TcNr1mdgs0PWxh2IOI1GKrxlzxpqzQuFmxq5WHKr5RrwZ4/Xq0t/+e8JkvhZdW0jarz/28Jom0gkM5lorsewIDAQAB",
+ "name": "ChromeOS networking private extension API test",
+ "version": "0.1",
+ "manifest_version": 2,
+ "description": "Test of chrome.networkingPrivate methods",
+ "background": {
+ "scripts": ["test.js"]
+ },
+ "permissions": [
+ "networkingPrivate"
+ ]
+}
diff --git a/chrome/test/data/extensions/api_test/networking/test.js b/chrome/test/data/extensions/api_test/networking/test.js
new file mode 100644
index 0000000..5503ced
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/networking/test.js
@@ -0,0 +1,98 @@
+// Copyright (c) 2013 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.
+
+var callbackPass = chrome.test.callbackPass;
+var callbackFail = chrome.test.callbackFail;
+var assertTrue = chrome.test.assertTrue;
+var assertEq = chrome.test.assertEq;
+
+chrome.test.runTests([
+ function getVisibleNetworks() {
+ chrome.networkingPrivate.getVisibleNetworks(
+ "All",
+ callbackPass(function(result) {
+ assertTrue(!!result);
+ assertEq(4, result.length);
+ assertEq([{ "Name": "eth0",
+ "GUID": "stub_ethernet",
+ "ConnectionState": "Connected",
+ "Type": "Ethernet"
+ },
+ { "Name": "wifi1",
+ "GUID": "stub_wifi1",
+ "ConnectionState": "Connected",
+ "Type": "WiFi",
+ "WiFi": {
+ "SSID": "stub_wifi1",
+ "Type": "WiFi"
+ }
+ },
+ { "Name": "wifi2_PSK",
+ "GUID": "stub_wifi2",
+ "ConnectionState": "NotConnected",
+ "Type": "WiFi",
+ "WiFi": {
+ "SSID": "stub_wifi2",
+ "Type": "WiFi"
+ }
+ },
+ { "Name": "cellular1",
+ "GUID": "stub_cellular1",
+ "ConnectionState": "NotConnected",
+ "Type": "Cellular"
+ }], result);
+ }));
+ },
+ function getVisibleNetworksWifi() {
+ chrome.networkingPrivate.getVisibleNetworks(
+ "WiFi",
+ callbackPass(function(result) {
+ assertTrue(!!result);
+ assertEq(2, result.length);
+ assertEq([{ "Name": "wifi1",
+ "GUID": "stub_wifi1",
+ "ConnectionState": "Connected",
+ "Type": "WiFi",
+ "WiFi": {
+ "SSID": "stub_wifi1",
+ "Type":"WiFi"
+ }
+ },
+ { "Name": "wifi2_PSK",
+ "GUID": "stub_wifi2",
+ "ConnectionState": "NotConnected",
+ "Type": "WiFi",
+ "WiFi": {
+ "SSID": "stub_wifi2",
+ "Type": "WiFi"
+ }
+ }], result);
+ }));
+ },
+ function getProperties() {
+ chrome.networkingPrivate.getProperties(
+ "stub_wifi2",
+ callbackPass(function(result) {
+ assertTrue(!!result);
+ assertEq("wifi2_PSK", result.Name);
+ assertEq("NotConnected", result.ConnectionState);
+ assertEq("WiFi", result.Type);
+ }));
+ },
+ function startConnect() {
+ chrome.networkingPrivate.startConnect("stub_wifi2",
+ callbackPass(function() {}));
+ },
+ function startDisconnect() {
+ chrome.networkingPrivate.startDisconnect("stub_wifi2",
+ callbackPass(function() {}));
+ },
+ function startConnectNonexistent() {
+ // Make sure we get an error when we try to connect to a nonexistent
+ // network.
+ chrome.networkingPrivate.startConnect(
+ "nonexistent_path",
+ callbackFail("Error.InvalidService", function() {}));
+ }
+]);
diff --git a/chromeos/dbus/shill_service_client.cc b/chromeos/dbus/shill_service_client.cc
index 16d7767..8e0ede0 100644
--- a/chromeos/dbus/shill_service_client.cc
+++ b/chromeos/dbus/shill_service_client.cc
@@ -312,6 +312,11 @@ class ShillServiceClientStubImpl : public ShillServiceClient,
virtual void Connect(const dbus::ObjectPath& service_path,
const base::Closure& callback,
const ErrorCallback& error_callback) OVERRIDE {
+ base::Value* service;
+ if (!stub_services_.Get(service_path.value(), &service)) {
+ error_callback.Run("Error.InvalidService", "Invalid Service");
+ return;
+ }
// Set Associating
base::StringValue associating_value(flimflam::kStateAssociation);
SetServiceProperty(service_path.value(),