From b34ff556a7902fe52fe17e63c2e05faa616c8380 Mon Sep 17 00:00:00 2001 From: cschuet Date: Tue, 3 Feb 2015 02:23:39 -0800 Subject: [PATCH] Implementation of the NetworkingConfigService Implementation of the NetworkingConfigService and boiler plate code for the networking.config API. Reviewers: Please see 1) https://docs.google.com/document/d/1V8YGouKC477iC11L4PL8H_HU1Ru3R5kMhXppuoIVNeo for the design document. 2) https://docs.google.com/drawings/d/12Hai1LdaPzwtkrQUdCjSpt1s7InRNNBDeWiW5ujfIRg for a flow diagram. Review URL: https://codereview.chromium.org/880073002 Cr-Commit-Position: refs/heads/master@{#314303} --- .../networking_config_chromeos_apitest_chromeos.cc | 27 +++++ chrome/chrome_tests.gypi | 1 + .../extensions/api_test/networking_config/OWNERS | 3 + .../networking_config/api_availability.html | 6 + .../api_test/networking_config/api_availability.js | 11 ++ .../api_test/networking_config/manifest.json | 8 ++ .../networking_config/register_networks.html | 6 + .../networking_config/register_networks.js | 45 ++++++++ extensions/browser/BUILD.gn | 6 + extensions/browser/api/networking_config/OWNERS | 3 + .../api/networking_config/networking_config_api.cc | 128 +++++++++++++++++++++ .../api/networking_config/networking_config_api.h | 55 +++++++++ .../networking_config/networking_config_service.cc | 112 ++++++++++++++++++ .../networking_config/networking_config_service.h | 107 +++++++++++++++++ .../networking_config_service_chromeos_unittest.cc | 71 ++++++++++++ .../networking_config_service_factory.cc | 83 +++++++++++++ .../networking_config_service_factory.h | 41 +++++++ .../browser_context_keyed_service_factories.cc | 4 + .../browser/extension_function_histogram_value.h | 2 + extensions/common/api/_api_features.json | 4 + extensions/common/api/_permission_features.json | 5 + .../common}/api/networking_config.idl | 19 ++- extensions/common/api/schemas.gypi | 1 + extensions/common/permissions/api_permission.h | 1 + .../permissions/extensions_api_permissions.cc | 5 + extensions/common/permissions/permission_message.h | 1 + extensions/extensions.gyp | 6 + extensions/extensions_strings.grd | 3 + extensions/extensions_tests.gyp | 1 + tools/metrics/histograms/histograms.xml | 3 + 30 files changed, 764 insertions(+), 4 deletions(-) create mode 100644 chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc create mode 100644 chrome/test/data/extensions/api_test/networking_config/OWNERS create mode 100644 chrome/test/data/extensions/api_test/networking_config/api_availability.html create mode 100644 chrome/test/data/extensions/api_test/networking_config/api_availability.js create mode 100644 chrome/test/data/extensions/api_test/networking_config/manifest.json create mode 100644 chrome/test/data/extensions/api_test/networking_config/register_networks.html create mode 100644 chrome/test/data/extensions/api_test/networking_config/register_networks.js create mode 100644 extensions/browser/api/networking_config/OWNERS create mode 100644 extensions/browser/api/networking_config/networking_config_api.cc create mode 100644 extensions/browser/api/networking_config/networking_config_api.h create mode 100644 extensions/browser/api/networking_config/networking_config_service.cc create mode 100644 extensions/browser/api/networking_config/networking_config_service.h create mode 100644 extensions/browser/api/networking_config/networking_config_service_chromeos_unittest.cc create mode 100644 extensions/browser/api/networking_config/networking_config_service_factory.cc create mode 100644 extensions/browser/api/networking_config/networking_config_service_factory.h rename {chrome/common/extensions => extensions/common}/api/networking_config.idl (82%) diff --git a/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc b/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc new file mode 100644 index 000000000000..a87ed7b0cff8 --- /dev/null +++ b/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc @@ -0,0 +1,27 @@ +// Copyright 2015 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 + +#include "chrome/browser/extensions/extension_apitest.h" + +namespace { + +class NetworkingConfigTest : public ExtensionApiTest { + public: + NetworkingConfigTest() {} +}; + +} // namespace + +IN_PROC_BROWSER_TEST_F(NetworkingConfigTest, ApiAvailability) { + ASSERT_TRUE(RunExtensionSubtest("networking_config", "api_availability.html")) + << message_; +} + +IN_PROC_BROWSER_TEST_F(NetworkingConfigTest, RegisterNetworks) { + ASSERT_TRUE( + RunExtensionSubtest("networking_config", "register_networks.html")) + << message_; +} diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 711972d9c4f4..4276759f9047 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -263,6 +263,7 @@ 'browser/extensions/lazy_background_page_apitest.cc', 'browser/extensions/lazy_background_page_test_util.h', 'browser/extensions/mutation_observers_apitest.cc', + 'browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc', 'browser/extensions/options_page_apitest.cc', 'browser/extensions/page_action_browsertest.cc', 'browser/extensions/plugin_apitest.cc', diff --git a/chrome/test/data/extensions/api_test/networking_config/OWNERS b/chrome/test/data/extensions/api_test/networking_config/OWNERS new file mode 100644 index 000000000000..5dc3191f1e01 --- /dev/null +++ b/chrome/test/data/extensions/api_test/networking_config/OWNERS @@ -0,0 +1,3 @@ +cschuet@chromium.org +pneubeck@chromium.org +stevenjb@chromium.org diff --git a/chrome/test/data/extensions/api_test/networking_config/api_availability.html b/chrome/test/data/extensions/api_test/networking_config/api_availability.html new file mode 100644 index 000000000000..537a74860cad --- /dev/null +++ b/chrome/test/data/extensions/api_test/networking_config/api_availability.html @@ -0,0 +1,6 @@ + + diff --git a/chrome/test/data/extensions/api_test/networking_config/api_availability.js b/chrome/test/data/extensions/api_test/networking_config/api_availability.js new file mode 100644 index 000000000000..ca2867bf4eb4 --- /dev/null +++ b/chrome/test/data/extensions/api_test/networking_config/api_availability.js @@ -0,0 +1,11 @@ +// Copyright 2015 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. + +chrome.test.assertFalse(!chrome.networking.config, + "No networking_config namespace."); +chrome.test.assertFalse(!chrome.networking.config.setNetworkFilter, + "No setNetworkFilter function."); +chrome.test.assertFalse(!chrome.networking.config.finishAuthentication, + "No finishAuthentication function."); +chrome.test.succeed(); diff --git a/chrome/test/data/extensions/api_test/networking_config/manifest.json b/chrome/test/data/extensions/api_test/networking_config/manifest.json new file mode 100644 index 000000000000..b21977356452 --- /dev/null +++ b/chrome/test/data/extensions/api_test/networking_config/manifest.json @@ -0,0 +1,8 @@ +{ + "name": "networking.config browser tests", + "version": "0.1", + "manifest_version": 2, + "permissions": [ + "networking.config" + ] +} diff --git a/chrome/test/data/extensions/api_test/networking_config/register_networks.html b/chrome/test/data/extensions/api_test/networking_config/register_networks.html new file mode 100644 index 000000000000..7cb5644822d3 --- /dev/null +++ b/chrome/test/data/extensions/api_test/networking_config/register_networks.html @@ -0,0 +1,6 @@ + + diff --git a/chrome/test/data/extensions/api_test/networking_config/register_networks.js b/chrome/test/data/extensions/api_test/networking_config/register_networks.js new file mode 100644 index 000000000000..8436b1cbbd15 --- /dev/null +++ b/chrome/test/data/extensions/api_test/networking_config/register_networks.js @@ -0,0 +1,45 @@ +// Copyright 2015 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. + +'use strict'; + +var assertEq = chrome.test.assertEq; +var assertTrue = chrome.test.assertTrue; +var assertThrows = chrome.test.assertThrows; +var fail = chrome.test.fail; +var succeed = chrome.test.succeed; +var callbackPass = chrome.test.callbackPass; +var callbackFail = chrome.test.callbackFail; + +var testCases = { + neitherHexSsidNorSsid: + {input: [{Type: 'WiFi'}], error: 'Malformed filter description.'}, + ssid: {input: [{Type: 'WiFi', SSID: 'SSID1'}]}, + hexSsid: {input: [{Type: 'WiFi', HexSSID: '5353494431'}]}, + invalidHexSsid1: { + input: [{Type: 'WiFi', HexSSID: '5'}], + error: + 'Malformed filter description. Failed to register network with SSID ' + + '(hex): 5' + }, + invalidHexSsid2: { + input: [{Type: 'WiFi', HexSSID: 'ABCDEFGH'}], + error: + 'Malformed filter description. Failed to register network with SSID ' + + '(hex): ABCDEFGH' + } +}; + +var runTests = function() { + for (var key in testCases) { + var testCase = testCases[key]; + if (testCase.hasOwnProperty('error')) + var callback = callbackFail(testCase.error); + else + var callback = callbackPass(); + chrome.networking.config.setNetworkFilter(testCase.input, callback); + } +}; + +runTests(); diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index aaa703c3d947..b11f1d22485e 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn @@ -580,6 +580,12 @@ source_set("browser") { if (is_chromeos) { sources += [ + "api/networking_config/networking_config_api.cc", + "api/networking_config/networking_config_api.h", + "api/networking_config/networking_config_service.cc", + "api/networking_config/networking_config_service.h", + "api/networking_config/networking_config_service_factory.cc", + "api/networking_config/networking_config_service_factory.h", "api/vpn_provider/vpn_provider_api.cc", "api/vpn_provider/vpn_provider_api.h", "api/vpn_provider/vpn_service.cc", diff --git a/extensions/browser/api/networking_config/OWNERS b/extensions/browser/api/networking_config/OWNERS new file mode 100644 index 000000000000..5dc3191f1e01 --- /dev/null +++ b/extensions/browser/api/networking_config/OWNERS @@ -0,0 +1,3 @@ +cschuet@chromium.org +pneubeck@chromium.org +stevenjb@chromium.org diff --git a/extensions/browser/api/networking_config/networking_config_api.cc b/extensions/browser/api/networking_config/networking_config_api.cc new file mode 100644 index 000000000000..bf3743665d8b --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_api.cc @@ -0,0 +1,128 @@ +// Copyright 2015 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 + +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "extensions/browser/api/networking_config/networking_config_api.h" +#include "extensions/browser/api/networking_config/networking_config_service.h" +#include "extensions/browser/api/networking_config/networking_config_service_factory.h" +#include "ui/base/l10n/l10n_util.h" + +namespace extensions { + +namespace { + +const char kAuthenticationResultFailed[] = + "Failed to set AuthenticationResult."; +const char kMalformedFilterDescription[] = "Malformed filter description."; +const char kMalformedFilterDescriptionWithSSID[] = + "Malformed filter description. Failed to register network with SSID " + "(hex): *"; +const char kUnsupportedNetworkType[] = "Unsupported network type."; + +} // namespace + +NetworkingConfigSetNetworkFilterFunction:: + NetworkingConfigSetNetworkFilterFunction() { +} + +ExtensionFunction::ResponseAction +NetworkingConfigSetNetworkFilterFunction::Run() { + parameters_ = + core_api::networking_config::SetNetworkFilter::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + + NetworkingConfigService* service = + NetworkingConfigServiceFactory::GetForBrowserContext(browser_context()); + DCHECK(service); + + // Remove previously registered networks. + service->UnregisterExtension(extension_id()); + + for (linked_ptr& ni : + parameters_->networks) { + // |Type| field must be set to |WiFi| + if (ni->type != core_api::networking_config::NETWORK_TYPE_WIFI) + return RespondNow(Error(kUnsupportedNetworkType)); + + // Either |ssid| or |hex_ssid| must be set. + if (!ni->ssid.get() && !ni->hex_ssid.get()) + return RespondNow(Error(kMalformedFilterDescription)); + + std::string hex_ssid; + if (ni->ssid.get()) { + auto ssid_field = ni->ssid.get(); + hex_ssid = base::HexEncode(ssid_field->c_str(), ssid_field->size()); + } + if (ni->hex_ssid.get()) + hex_ssid = *ni->hex_ssid.get(); + + if (!service->RegisterHexSsid(hex_ssid, extension_id())) + return RespondNow(Error(kMalformedFilterDescriptionWithSSID, hex_ssid)); + } + + return RespondNow(NoArguments()); +} + +NetworkingConfigSetNetworkFilterFunction:: + ~NetworkingConfigSetNetworkFilterFunction() { +} + +NetworkingConfigFinishAuthenticationFunction:: + NetworkingConfigFinishAuthenticationFunction() { +} + +ExtensionFunction::ResponseAction +NetworkingConfigFinishAuthenticationFunction::Run() { + parameters_ = + core_api::networking_config::FinishAuthentication::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + + NetworkingConfigService* service = + NetworkingConfigServiceFactory::GetForBrowserContext(browser_context()); + DCHECK(service); + + const NetworkingConfigService::AuthenticationResult& last_result = + service->GetAuthenticationResult(); + if (last_result.authentication_state != NetworkingConfigService::NOTRY || + last_result.guid != parameters_->guid) { + RespondNow(Error(kAuthenticationResultFailed)); + } + + // Populate NetworkingCaptivePortalAPI::AuthenticationResult. + NetworkingConfigService::AuthenticationResult authentication_result = { + extension_id(), parameters_->guid, NetworkingConfigService::FAILED, + }; + switch (parameters_->result) { + case core_api::networking_config::AUTHENTICATION_RESULT_NONE: + NOTREACHED(); + break; + case core_api::networking_config::AUTHENTICATION_RESULT_UNHANDLED: + authentication_result.authentication_state = + NetworkingConfigService::FAILED; + break; + case core_api::networking_config::AUTHENTICATION_RESULT_REJECTED: + authentication_result.authentication_state = + NetworkingConfigService::REJECTED; + break; + case core_api::networking_config::AUTHENTICATION_RESULT_FAILED: + authentication_result.authentication_state = + NetworkingConfigService::FAILED; + break; + case core_api::networking_config::AUTHENTICATION_RESULT_SUCCEEDED: + authentication_result.authentication_state = + NetworkingConfigService::SUCCESS; + break; + } + service->SetAuthenticationResult(authentication_result); + return RespondNow(NoArguments()); +} + +NetworkingConfigFinishAuthenticationFunction:: + ~NetworkingConfigFinishAuthenticationFunction() { +} + +} // namespace extensions diff --git a/extensions/browser/api/networking_config/networking_config_api.h b/extensions/browser/api/networking_config/networking_config_api.h new file mode 100644 index 000000000000..863fb08a2627 --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_api.h @@ -0,0 +1,55 @@ +// Copyright 2015 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. + +#ifndef EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_API_H_ +#define EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_API_H_ + +#include "extensions/common/api/networking_config.h" +#include "extensions/browser/extension_function.h" + +namespace extensions { + +class NetworkingConfigSetNetworkFilterFunction + : public UIThreadExtensionFunction { + public: + NetworkingConfigSetNetworkFilterFunction(); + + ResponseAction Run() override; + + DECLARE_EXTENSION_FUNCTION("networking.config.setNetworkFilter", + NETWORKING_CONFIG_SETNETWORKFILTER); + + protected: + ~NetworkingConfigSetNetworkFilterFunction() override; + + scoped_ptr + parameters_; + + private: + DISALLOW_COPY_AND_ASSIGN(NetworkingConfigSetNetworkFilterFunction); +}; + +class NetworkingConfigFinishAuthenticationFunction + : public UIThreadExtensionFunction { + public: + NetworkingConfigFinishAuthenticationFunction(); + + ResponseAction Run() override; + + DECLARE_EXTENSION_FUNCTION("networking.config.finishAuthenticationFunction", + NETWORKING_CONFIG_FINISHAUTHENTICATION); + + protected: + ~NetworkingConfigFinishAuthenticationFunction() override; + + scoped_ptr + parameters_; + + private: + DISALLOW_COPY_AND_ASSIGN(NetworkingConfigFinishAuthenticationFunction); +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_API_H_ diff --git a/extensions/browser/api/networking_config/networking_config_service.cc b/extensions/browser/api/networking_config/networking_config_service.cc new file mode 100644 index 000000000000..54a8ecd80758 --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_service.cc @@ -0,0 +1,112 @@ +// Copyright 2015 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 + +#include "base/lazy_instance.h" +#include "base/strings/string_util.h" +#include "extensions/browser/api/networking_config/networking_config_service.h" + +namespace extensions { + +namespace { + +bool IsValidNonEmptyHexString(const std::string& input) { + size_t count = input.size(); + if (count == 0 || (count % 2) != 0) + return false; + for (const char& c : input) + if (!IsHexDigit(c)) + return false; + return true; +} + +} // namespace + +NetworkingConfigService::AuthenticationResult::AuthenticationResult() + : authentication_state(NetworkingConfigService::NOTRY) { +} + +NetworkingConfigService::AuthenticationResult::AuthenticationResult( + ExtensionId extension_id, + std::string guid, + AuthenticationState authentication_state) + : extension_id(extension_id), + guid(guid), + authentication_state(authentication_state) { +} + +NetworkingConfigService::NetworkingConfigService( + scoped_ptr event_delegate, + ExtensionRegistry* extension_registry) + : registry_observer_(this), event_delegate_(event_delegate.Pass()) { + registry_observer_.Add(extension_registry); +} + +NetworkingConfigService::~NetworkingConfigService() { +} + +void NetworkingConfigService::OnExtensionUnloaded( + content::BrowserContext* browser_context, + const Extension* extension, + UnloadedExtensionInfo::Reason reason) { + UnregisterExtension(extension->id()); +} + +std::string NetworkingConfigService::LookupExtensionIdForHexSsid( + std::string hex_ssid) const { + // Transform hex_ssid to uppercase. + transform(hex_ssid.begin(), hex_ssid.end(), hex_ssid.begin(), toupper); + + const auto it = hex_ssid_to_extension_id_.find(hex_ssid); + if (it == hex_ssid_to_extension_id_.end()) + return std::string(); + return it->second; +} + +bool NetworkingConfigService::IsRegisteredForCaptivePortalEvent( + std::string extension_id) const { + return event_delegate_->HasExtensionRegisteredForEvent(extension_id); +} + +bool NetworkingConfigService::RegisterHexSsid(std::string hex_ssid, + const std::string& extension_id) { + if (!IsValidNonEmptyHexString(hex_ssid)) { + LOG(ERROR) << "\'" << hex_ssid << "\' is not a valid hex encoded string."; + return false; + } + + // Transform hex_ssid to uppercase. + transform(hex_ssid.begin(), hex_ssid.end(), hex_ssid.begin(), toupper); + + return hex_ssid_to_extension_id_.insert(make_pair(hex_ssid, extension_id)) + .second; +} + +void NetworkingConfigService::UnregisterExtension( + const std::string& extension_id) { + for (auto it = hex_ssid_to_extension_id_.begin(); + it != hex_ssid_to_extension_id_.end();) { + if (it->second == extension_id) + hex_ssid_to_extension_id_.erase(it++); + else + ++it; + } +} + +const NetworkingConfigService::AuthenticationResult& +NetworkingConfigService::GetAuthenticationResult() const { + return authentication_result_; +} + +void NetworkingConfigService::ResetAuthenticationResult() { + authentication_result_ = AuthenticationResult(); +} + +void NetworkingConfigService::SetAuthenticationResult( + const AuthenticationResult& authentication_result) { + authentication_result_ = authentication_result; +} + +} // namespace extensions diff --git a/extensions/browser/api/networking_config/networking_config_service.h b/extensions/browser/api/networking_config/networking_config_service.h new file mode 100644 index 000000000000..236b992d8714 --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_service.h @@ -0,0 +1,107 @@ +// Copyright 2015 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. + +#ifndef EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_H_ +#define EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_H_ + +#include +#include + +#include "base/memory/scoped_ptr.h" +#include "base/scoped_observer.h" +#include "components/keyed_service/core/keyed_service.h" +#include "extensions/browser/event_router.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_registry_observer.h" + +namespace extensions { + +// This class provides the session-scoped storage backing the networking config +// extension API. Currently only the parts relevant for captive portal handling +// are implemented. +class NetworkingConfigService : public ExtensionRegistryObserver, + public KeyedService { + public: + class EventDelegate { + public: + EventDelegate() {} + virtual ~EventDelegate() {} + virtual bool HasExtensionRegisteredForEvent( + const std::string& extension_id) const = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(EventDelegate); + }; + + // Indicates the authentication state of the portal. + enum AuthenticationState { NOTRY, TRYING, SUCCESS, REJECTED, FAILED }; + + // Provides information about the current authentication state of the portal. + struct AuthenticationResult { + AuthenticationResult(); + AuthenticationResult(ExtensionId extension_id, + std::string guid, + AuthenticationState authentication_state); + ExtensionId extension_id; + std::string guid; + AuthenticationState authentication_state; + }; + + // Note: |extension_registry| must outlive this class. + NetworkingConfigService(scoped_ptr event_delegate, + ExtensionRegistry* extension_registry); + ~NetworkingConfigService() override; + + // ExtensionRegistryObserver + void OnExtensionUnloaded(content::BrowserContext* browser_context, + const Extension* extension, + UnloadedExtensionInfo::Reason reason) override; + + // Returns the extension id registered for |hex_ssid|. If no extension is + // registered for this |hex_ssid|, the function returns an empty string. + // |hex_ssid|: SSID in hex encoding. + std::string LookupExtensionIdForHexSsid(std::string hex_ssid) const; + + // Returns true if the extension with id |extension_id| registered for + // |onCaptivePortalDetected| events, otherwise false. + bool IsRegisteredForCaptivePortalEvent(std::string extension_id) const; + + // Registers |hex_ssid| as being handled by the extension with extension ID + // |extension_id|. Returns true on success and false if another extension + // already registered for |hex_ssid|. + // |hex_ssid|: SSID in hex encoding of the network to be registered. + // |extension_id|: Extension ID of the extension handling the network + // configuration for this network. + bool RegisterHexSsid(std::string hex_ssid, const std::string& extension_id); + + // Unregisters extension with the ID |extension_id| removing all associated + // HexSSIDs from the map. + // |extension_id|: ID identifying the extenion to be removed + void UnregisterExtension(const std::string& extensionId); + + // Returns the current AuthenticationResult. + const AuthenticationResult& GetAuthenticationResult() const; + + // Sets the authentication_state to NOTRY and clears all other fields. + void ResetAuthenticationResult(); + + // Sets the current AuthenticationResult. + void SetAuthenticationResult( + const AuthenticationResult& authentication_result); + + private: + AuthenticationResult authentication_result_; + + ScopedObserver + registry_observer_; + + scoped_ptr event_delegate_; + + // This map associates a given hex encoded SSID to an extension entry. + std::map hex_ssid_to_extension_id_; +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_H_ diff --git a/extensions/browser/api/networking_config/networking_config_service_chromeos_unittest.cc b/extensions/browser/api/networking_config/networking_config_service_chromeos_unittest.cc new file mode 100644 index 000000000000..9990d74b2504 --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_service_chromeos_unittest.cc @@ -0,0 +1,71 @@ +// Copyright 2014 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 "extensions/browser/api/networking_config/networking_config_service.h" +#include "extensions/browser/api_unittest.h" +#include "extensions/browser/extension_registry.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +namespace { + +const char kExtensionId[] = "necdpnkfgondfageiompbacibhgmfebg"; +const char kHexSsid[] = "54657374535349445F5A5A5A5A"; +const char kHexSsidLower[] = "54657374535349445f5a5a5a5a"; + +class MockEventDelegate : public NetworkingConfigService::EventDelegate { + public: + MockEventDelegate() : extension_registered_(false) {} + ~MockEventDelegate() override {} + + bool HasExtensionRegisteredForEvent( + const std::string& extension_id) const override { + return extension_registered_; + } + + void SetExtensionRegisteredForEvent(bool extension_registered) { + extension_registered_ = extension_registered; + } + + private: + bool extension_registered_; +}; + +} // namespace + +class NetworkingConfigServiceTest : public ApiUnitTest { + public: + NetworkingConfigServiceTest() {} + ~NetworkingConfigServiceTest() override {} + + void SetUp() override { + ApiUnitTest::SetUp(); + extension_registry_ = scoped_ptr( + new ExtensionRegistry(browser_context())); + scoped_ptr mock_event_delegate = + scoped_ptr(new MockEventDelegate()); + service_ = scoped_ptr(new NetworkingConfigService( + mock_event_delegate.Pass(), extension_registry_.get())); + DCHECK(service_); + } + + protected: + scoped_ptr extension_registry_; + scoped_ptr service_; +}; + +TEST_F(NetworkingConfigServiceTest, BasicRegisterHexSsid) { + EXPECT_TRUE(service_->RegisterHexSsid(kHexSsid, kExtensionId)); + EXPECT_EQ(kExtensionId, service_->LookupExtensionIdForHexSsid(kHexSsid)); + EXPECT_EQ(kExtensionId, service_->LookupExtensionIdForHexSsid(kHexSsidLower)); +} + +TEST_F(NetworkingConfigServiceTest, BasicRegisterHexSsidLower) { + EXPECT_TRUE(service_->RegisterHexSsid(kHexSsidLower, kExtensionId)); + EXPECT_EQ(kExtensionId, service_->LookupExtensionIdForHexSsid(kHexSsid)); + EXPECT_EQ(kExtensionId, service_->LookupExtensionIdForHexSsid(kHexSsidLower)); +} + +} // namespace extensions diff --git a/extensions/browser/api/networking_config/networking_config_service_factory.cc b/extensions/browser/api/networking_config/networking_config_service_factory.cc new file mode 100644 index 000000000000..62bc8f17a5b5 --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_service_factory.cc @@ -0,0 +1,83 @@ +// Copyright 2015 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 "extensions/browser/api/networking_config/networking_config_service_factory.h" + +#include + +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "extensions/browser/api/networking_config/networking_config_service.h" +#include "extensions/browser/extension_registry_factory.h" +#include "extensions/browser/extension_system_provider.h" +#include "extensions/browser/extensions_browser_client.h" +#include "extensions/common/api/networking_config.h" + +namespace extensions { + +namespace { + +class DefaultEventDelegate : public NetworkingConfigService::EventDelegate { + public: + explicit DefaultEventDelegate(content::BrowserContext* context); + ~DefaultEventDelegate() override; + + bool HasExtensionRegisteredForEvent( + const std::string& extension_id) const override; + + private: + content::BrowserContext* const context_; +}; + +DefaultEventDelegate::DefaultEventDelegate(content::BrowserContext* context) + : context_(context) { +} + +DefaultEventDelegate::~DefaultEventDelegate() { +} + +bool DefaultEventDelegate::HasExtensionRegisteredForEvent( + const std::string& extension_id) const { + return EventRouter::Get(context_)->ExtensionHasEventListener( + extension_id, + core_api::networking_config::OnCaptivePortalDetected::kEventName); +} + +} // namespace + +// static +NetworkingConfigService* NetworkingConfigServiceFactory::GetForBrowserContext( + content::BrowserContext* context) { + return static_cast( + GetInstance()->GetServiceForBrowserContext(context, true)); +} + +// static +NetworkingConfigServiceFactory* NetworkingConfigServiceFactory::GetInstance() { + return Singleton::get(); +} + +NetworkingConfigServiceFactory::NetworkingConfigServiceFactory() + : BrowserContextKeyedServiceFactory( + "NetworkingConfigService", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); + DependsOn(extensions::ExtensionRegistryFactory::GetInstance()); +} + +NetworkingConfigServiceFactory::~NetworkingConfigServiceFactory() { +} + +KeyedService* NetworkingConfigServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new NetworkingConfigService( + make_scoped_ptr(new DefaultEventDelegate(context)), + ExtensionRegistry::Get(context)); +} + +content::BrowserContext* NetworkingConfigServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return ExtensionsBrowserClient::Get()->GetOriginalContext(context); +} + +} // namespace extensions diff --git a/extensions/browser/api/networking_config/networking_config_service_factory.h b/extensions/browser/api/networking_config/networking_config_service_factory.h new file mode 100644 index 000000000000..58e56323b1ea --- /dev/null +++ b/extensions/browser/api/networking_config/networking_config_service_factory.h @@ -0,0 +1,41 @@ +// Copyright 2015 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. + +#ifndef EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_FACTORY_H_ +#define EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace extensions { +class NetworkingConfigService; + +class NetworkingConfigServiceFactory + : public BrowserContextKeyedServiceFactory { + public: + static NetworkingConfigService* GetForBrowserContext( + content::BrowserContext* context); + + static NetworkingConfigServiceFactory* GetInstance(); + + private: + friend struct DefaultSingletonTraits; + + NetworkingConfigServiceFactory(); + ~NetworkingConfigServiceFactory() override; + + // BrowserContextKeyedBaseFactory + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_FACTORY_H_ diff --git a/extensions/browser/browser_context_keyed_service_factories.cc b/extensions/browser/browser_context_keyed_service_factories.cc index b997ebfad999..9ed54d11d369 100644 --- a/extensions/browser/browser_context_keyed_service_factories.cc +++ b/extensions/browser/browser_context_keyed_service_factories.cc @@ -10,6 +10,7 @@ #include "extensions/browser/api/hid/hid_device_manager.h" #include "extensions/browser/api/idle/idle_manager_factory.h" #include "extensions/browser/api/management/management_api.h" +#include "extensions/browser/api/networking_config/networking_config_service_factory.h" #include "extensions/browser/api/networking_private/networking_private_event_router_factory.h" #include "extensions/browser/api/runtime/runtime_api.h" #include "extensions/browser/api/serial/serial_connection.h" @@ -47,6 +48,9 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { HidDeviceManager::GetFactoryInstance(); IdleManagerFactory::GetInstance(); ManagementAPI::GetFactoryInstance(); +#if defined(OS_CHROMEOS) + NetworkingConfigServiceFactory::GetInstance(); +#endif #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX) NetworkingPrivateEventRouterFactory::GetInstance(); #endif diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index e94c934e679d..ae8e2cd36473 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -1013,6 +1013,8 @@ enum HistogramValue { FILEMANAGERPRIVATE_SEARCHFILESBYHASHES, EASYUNLOCKPRIVATE_SHOWERRORBUBBLE, EXTENSIONVIEWINTERNAL_NAVIGATE, + NETWORKING_CONFIG_SETNETWORKFILTER, + NETWORKING_CONFIG_FINISHAUTHENTICATION, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms.xml. ENUM_BOUNDARY diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index e83908589cb9..68e3fa3b6d36 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json @@ -199,6 +199,10 @@ "63ED55E43214C211F82122ED56407FF1A807F2A3" // http://crbug.com/448569 ] }, + "networking.config": { + "dependencies": ["permission:networking.config"], + "contexts": ["blessed_extension"] + }, "networkingPrivate": { "dependencies": ["permission:networkingPrivate"], "contexts": ["blessed_extension"] diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json index 137176f2ba3e..9f24ab963c87 100644 --- a/extensions/common/api/_permission_features.json +++ b/extensions/common/api/_permission_features.json @@ -201,6 +201,11 @@ "channel": "stable", "extension_types": ["extension", "legacy_packaged_app", "platform_app"] }, + "networking.config": { + "channel": "dev", + "platforms": ["chromeos"], + "extension_types": ["extension"] + }, "networkingPrivate": { "channel": "stable", "extension_types": ["extension", "legacy_packaged_app", "platform_app"], diff --git a/chrome/common/extensions/api/networking_config.idl b/extensions/common/api/networking_config.idl similarity index 82% rename from chrome/common/extensions/api/networking_config.idl rename to extensions/common/api/networking_config.idl index ea4c4321b764..2ba289ccaf4e 100644 --- a/chrome/common/extensions/api/networking_config.idl +++ b/extensions/common/api/networking_config.idl @@ -49,6 +49,13 @@ namespace networking.config { failed }; + // Invoked by $(setNetworkFilter) when the respective operation is finished. + callback SetNetworkFilterCallback = void(); + + // Invoked by $(finishAuthentication) when the respective operation is + // finished. + callback FinishAuthenticationCallback = void(); + interface Functions { // Allows an extension to define network filters for the networks it can // handle. A call to this function will remove all filters previously @@ -56,16 +63,20 @@ namespace networking.config { // |networks|: Network filters to set. Every NetworkInfo must // either have the SSID or HexSSID // set. Other fields will be ignored. - void setNetworkFilter(NetworkInfo[] networks); + // |callback|: Called back when this operation is finished. + void setNetworkFilter(NetworkInfo[] networks, + SetNetworkFilterCallback callback); // Called by the extension to notify the network config API that it finished // a captive portal authentication attempt and hand over the result of the // attempt. This function must only be called with the GUID of the latest // $(onCaptivePortalDetected) event. - // |GUID|: unique network identifier obtained from + // |GUID|: Unique network identifier obtained from // $(onCaptivePortalDetected). - // |result|: the result of the authentication attempt - void finishAuthentication(DOMString GUID, AuthenticationResult result); + // |result|: The result of the authentication attempt. + // |callback|: Called back when this operation is finished. + void finishAuthentication(DOMString GUID, AuthenticationResult result, + FinishAuthenticationCallback callback); }; interface Events { diff --git a/extensions/common/api/schemas.gypi b/extensions/common/api/schemas.gypi index 137e52ced8f6..ab8f8806d7d7 100644 --- a/extensions/common/api/schemas.gypi +++ b/extensions/common/api/schemas.gypi @@ -59,6 +59,7 @@ ], # ChromeOS-specific schemas. 'chromeos_schema_files': [ + 'networking_config.idl', 'vpn_provider.idl', 'webcam_private.idl', ], diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h index 89697a0c40be..caa28af35b8e 100644 --- a/extensions/common/permissions/api_permission.h +++ b/extensions/common/permissions/api_permission.h @@ -143,6 +143,7 @@ class APIPermission { kMDns, kMusicManagerPrivate, kNativeMessaging, + kNetworkingConfig, kNetworkingPrivate, kNotificationProvider, kNotifications, diff --git a/extensions/common/permissions/extensions_api_permissions.cc b/extensions/common/permissions/extensions_api_permissions.cc index ef2aaba5159a..825ccf24fb66 100644 --- a/extensions/common/permissions/extensions_api_permissions.cc +++ b/extensions/common/permissions/extensions_api_permissions.cc @@ -73,6 +73,11 @@ std::vector ExtensionsAPIPermissions::GetAllPermissions() {APIPermission::kOverrideEscFullscreen, "app.window.fullscreen.overrideEsc"}, {APIPermission::kIdle, "idle"}, + {APIPermission::kNetworkingConfig, + "networking.config", + APIPermissionInfo::kFlagNone, + IDS_EXTENSION_PROMPT_WARNING_NETWORKING_CONFIG, + PermissionMessage::kNetworkingConfig}, {APIPermission::kNetworkingPrivate, "networkingPrivate", APIPermissionInfo::kFlagCannotBeOptional, diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h index 04570bcbec92..aa3239e18de4 100644 --- a/extensions/common/permissions/permission_message.h +++ b/extensions/common/permissions/permission_message.h @@ -100,6 +100,7 @@ class PermissionMessage { kHosts4OrMoreReadOnly, kHostsAllReadOnly, kInterceptAllKeys, + kNetworkingConfig, // Last entry: Add new entries above and ensure to update the // "ExtensionPermission2" enum in tools/metrics/histograms/histograms.xml. kEnumBoundary, diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 75adde7abcbe..a0e437026a7f 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -890,6 +890,12 @@ '../chromeos/chromeos.gyp:chromeos', ], 'sources': [ + 'browser/api/networking_config/networking_config_api.cc', + 'browser/api/networking_config/networking_config_api.h', + 'browser/api/networking_config/networking_config_service.cc', + 'browser/api/networking_config/networking_config_service.h', + 'browser/api/networking_config/networking_config_service_factory.cc', + 'browser/api/networking_config/networking_config_service_factory.h', 'browser/api/vpn_provider/vpn_provider_api.cc', 'browser/api/vpn_provider/vpn_provider_api.h', 'browser/api/vpn_provider/vpn_service.cc', diff --git a/extensions/extensions_strings.grd b/extensions/extensions_strings.grd index c6931776153f..0bcf8d9e72a7 100644 --- a/extensions/extensions_strings.grd +++ b/extensions/extensions_strings.grd @@ -359,6 +359,9 @@ Vendor $10x1234 + + Configure network connections + Manage network connections diff --git a/extensions/extensions_tests.gyp b/extensions/extensions_tests.gyp index 9e7f05d1e6cb..9652719a8393 100644 --- a/extensions/extensions_tests.gyp +++ b/extensions/extensions_tests.gyp @@ -61,6 +61,7 @@ 'browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc', 'browser/api/idle/idle_api_unittest.cc', 'browser/api/mime_handler_private/mime_handler_private_unittest.cc', + 'browser/api/networking_config/networking_config_service_chromeos_unittest.cc', 'browser/api/power/power_api_unittest.cc', 'browser/api/sockets_tcp/sockets_tcp_api_unittest.cc', 'browser/api/sockets_udp/sockets_udp_api_unittest.cc', diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index cfdf80ebc0be..8d2b76c45a84 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -47268,6 +47268,8 @@ Therefore, the affected-histogram name has to have at least one dot in it. + + @@ -47455,6 +47457,7 @@ Therefore, the affected-histogram name has to have at least one dot in it. + -- 2.11.4.GIT