0

Delete chrome.networking.config

This API is unused and is being deprecated. See issue for details.

BUG=1124419

Change-Id: I4083be1d76c61a95f76c744c26621b14eb9ee651
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2423749
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: Devlin <rdevlin.cronin@chromium.org>
Reviewed-by: Erik Staab <estaab@chromium.org>
Reviewed-by: Azeem Arshad <azeemarshad@chromium.org>
Reviewed-by: Ben Wells <benwells@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816271}
This commit is contained in:
Steven Bennetts
2020-10-12 20:09:39 +00:00
committed by Commit Bot
parent e96c7cae01
commit ab1c69b181
47 changed files with 24 additions and 1590 deletions

1
.gn

@ -119,7 +119,6 @@ no_check_targets = [
"//extensions/browser/api/messaging:*", # 1 error
"//extensions/browser/api/metrics_private:*", # 3 errors
"//extensions/browser/api/mime_handler_private:*", # 1 error
"//extensions/browser/api/networking_config:*", # 7 errors
"//extensions/browser/api/networking_private:*", # 14 errors
"//extensions/browser/api/power:*", # 3 errors
"//extensions/browser/api/printer_provider:*", # 7 errors

@ -90,7 +90,6 @@ content/public/common/gpu_stream_constants.h
content/renderer/external_popup_menu.h
content/shell/android/shell_descriptors.h
extensions/browser/api/clipboard/clipboard_api.h
extensions/browser/api/networking_config/networking_config_service_factory.h
extensions/browser/api/webcam_private/webcam.h
extensions/browser/api/webcam_private/webcam_private_api.h
extensions/browser/entry_info.h

@ -4036,9 +4036,6 @@ are declared in tools/grit/grit_rule.gni.
<message name="IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE" desc="Permission string for network list access.">
Access list of network connections
</message>
<message name="IDS_EXTENSION_PROMPT_WARNING_NETWORKING_CONFIG" desc="Permission string for Networking Config API.">
Configure network connections
</message>
<message name="IDS_EXTENSION_PROMPT_WARNING_NETWORKING_PRIVATE" desc="Permission string for Networking Private API.">
Manage network connections
</message>

@ -459,9 +459,6 @@ const char* const kSafePermissionStrings[] = {
// Probably doesn't work on Chrome OS anyways.
"nativeMessaging",
// Admin controls network connectivity anyways.
"networking.config",
// Status quo considers this risky due to the ability to fake system UI -
// low risk IMHO however since notifications are already badged with app
// icon and won't extract any data.

@ -28,8 +28,6 @@
#include "content/public/browser/notification_registrar.h"
#include "url/gurl.h"
class NetworkingConfigTest;
namespace base {
class Value;
}
@ -58,7 +56,6 @@ class NetworkPortalDetectorImpl : public NetworkPortalDetector,
~NetworkPortalDetectorImpl() override;
private:
friend class ::NetworkingConfigTest;
friend class NetworkPortalDetectorImplTest;
friend class NetworkPortalDetectorImplBrowserTest;

@ -1,173 +0,0 @@
// 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 <memory>
#include <string>
#include "base/location.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/ui/ash/network/network_portal_notification_controller.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill/shill_device_client.h"
#include "chromeos/dbus/shill/shill_profile_client.h"
#include "chromeos/dbus/shill/shill_service_client.h"
#include "components/captive_portal/core/captive_portal_testing_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "extensions/test/result_catcher.h"
#include "net/base/net_errors.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_delegate.h"
using chromeos::DBusThreadManager;
using chromeos::NetworkPortalDetector;
using chromeos::NetworkPortalDetectorImpl;
using chromeos::NetworkPortalNotificationController;
using chromeos::ShillDeviceClient;
using chromeos::ShillProfileClient;
using chromeos::ShillServiceClient;
namespace {
const char kWifiDevicePath[] = "/device/stub_wifi_device1";
const char kWifi1ServicePath[] = "stub_wifi1";
const char kWifi1ServiceGUID[] = "wifi1_guid";
} // namespace
class NetworkingConfigTest
: public extensions::ExtensionApiTest,
public captive_portal::CaptivePortalDetectorTestBase {
public:
NetworkingConfigTest() : network_portal_detector_(nullptr) {}
~NetworkingConfigTest() override = default;
void SetUpOnMainThread() override {
extensions::ExtensionApiTest::SetUpOnMainThread();
content::RunAllPendingInMessageLoop();
display_service_ = std::make_unique<NotificationDisplayServiceTester>(
nullptr /* profile */);
DBusThreadManager* const dbus_manager = DBusThreadManager::Get();
ShillServiceClient::TestInterface* const service_test =
dbus_manager->GetShillServiceClient()->GetTestInterface();
ShillDeviceClient::TestInterface* const device_test =
dbus_manager->GetShillDeviceClient()->GetTestInterface();
ShillProfileClient::TestInterface* const profile_test =
dbus_manager->GetShillProfileClient()->GetTestInterface();
device_test->ClearDevices();
service_test->ClearServices();
device_test->AddDevice(kWifiDevicePath, shill::kTypeWifi,
"stub_wifi_device1");
service_test->AddService(kWifi1ServicePath, kWifi1ServiceGUID, "wifi1",
shill::kTypeWifi, shill::kStateOnline,
true /* add_to_visible */);
service_test->SetServiceProperty(kWifi1ServicePath, shill::kWifiBSsid,
base::Value("01:02:ab:7f:90:00"));
service_test->SetServiceProperty(
kWifi1ServicePath, shill::kSignalStrengthProperty, base::Value(40));
profile_test->AddService(ShillProfileClient::GetSharedProfilePath(),
kWifi1ServicePath);
content::RunAllPendingInMessageLoop();
network_portal_detector_ =
new NetworkPortalDetectorImpl(test_loader_factory());
// Takes ownership of |network_portal_detector_|:
chromeos::network_portal_detector::InitializeForTesting(
network_portal_detector_);
network_portal_detector_->Enable(false /* start_detection */);
set_detector(network_portal_detector_->captive_portal_detector_.get());
network_portal_notification_controller_ =
std::make_unique<NetworkPortalNotificationController>(
network_portal_detector_);
}
void TearDownOnMainThread() override {
network_portal_notification_controller_.reset();
}
void LoadTestExtension() {
extension_ = LoadExtension(test_data_dir_.AppendASCII("networking_config"));
}
bool RunExtensionTest(const std::string& path) {
return RunExtensionSubtest("networking_config",
extension_->GetResourceURL(path).spec());
}
void SimulateCaptivePortal() {
network_portal_detector_->StartDetection();
content::RunAllPendingInMessageLoop();
// Simulate a captive portal reply.
CompleteURLFetch(net::OK, 200, nullptr);
}
void SimulateSuccessfulCaptivePortalAuth() {
content::RunAllPendingInMessageLoop();
CompleteURLFetch(net::OK, 204, nullptr);
}
NetworkPortalDetector::CaptivePortalStatus GetCaptivePortalStatus(
const std::string& guid) {
return network_portal_detector_->GetCaptivePortalState(kWifi1ServiceGUID)
.status;
}
protected:
NetworkPortalDetectorImpl* network_portal_detector_;
std::unique_ptr<NetworkPortalNotificationController>
network_portal_notification_controller_;
const extensions::Extension* extension_ = nullptr;
std::unique_ptr<NotificationDisplayServiceTester> display_service_;
};
IN_PROC_BROWSER_TEST_F(NetworkingConfigTest, ApiAvailability) {
ASSERT_TRUE(RunExtensionSubtest("networking_config", "api_availability.html"))
<< message_;
}
// Test the full, positive flow starting with the extension registration and
// ending with the captive portal being authenticated.
IN_PROC_BROWSER_TEST_F(NetworkingConfigTest, FullTest) {
LoadTestExtension();
// This will cause the extension to register for wifi1.
ASSERT_TRUE(RunExtensionTest("full_test.html")) << message_;
SimulateCaptivePortal();
// Wait until a captive portal notification is displayed and verify that it is
// the expected captive portal notification.
auto notification = display_service_->GetNotification(
NetworkPortalNotificationController::kNotificationId);
ASSERT_TRUE(notification);
// Simulate the user click which leads to the extension being notified.
notification->delegate()->Click(
NetworkPortalNotificationController::kUseExtensionButtonIndex,
base::nullopt);
extensions::ResultCatcher catcher;
EXPECT_TRUE(catcher.GetNextResult());
// Simulate the captive portal vanishing.
SimulateSuccessfulCaptivePortalAuth();
ASSERT_EQ(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE,
GetCaptivePortalStatus(kWifi1ServiceGUID));
}

@ -15,10 +15,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/chromeos/mobile/mobile_activator.h"
#include "chrome/browser/chromeos/net/network_portal_web_dialog.h"
@ -33,14 +30,11 @@
#include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_type_pattern.h"
#include "components/captive_portal/core/captive_portal_detector.h"
#include "components/prefs/pref_service.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/user_manager.h"
#include "extensions/browser/api/networking_config/networking_config_service.h"
#include "extensions/browser/api/networking_config/networking_config_service_factory.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/message_center/public/cpp/notification.h"
@ -54,57 +48,18 @@ namespace {
const char kNotifierNetworkPortalDetector[] = "ash.network.portal-detector";
Profile* GetProfileForPrimaryUser() {
const user_manager::User* primary_user =
user_manager::UserManager::Get()->GetPrimaryUser();
if (!primary_user)
return nullptr;
return ProfileHelper::Get()->GetProfileByUser(primary_user);
}
void CloseNotification() {
SystemNotificationHelper::GetInstance()->Close(
NetworkPortalNotificationController::kNotificationId);
}
// Note that NetworkingConfigService may change after login as the profile
// switches from the login to the user's profile.
extensions::NetworkingConfigService* GetNetworkingConfigService(
Profile* profile) {
if (!profile)
return nullptr;
return extensions::NetworkingConfigServiceFactory::GetForBrowserContext(
profile);
}
const extensions::Extension* LookupExtensionForRawSsid(
extensions::NetworkingConfigService* networking_config_service,
const std::vector<uint8_t>& raw_ssid) {
DCHECK(networking_config_service);
Profile* profile = GetProfileForPrimaryUser();
if (!profile || !networking_config_service)
return nullptr;
std::string extension_id;
std::string hex_ssid = base::HexEncode(raw_ssid.data(), raw_ssid.size());
extension_id =
networking_config_service->LookupExtensionIdForHexSsid(hex_ssid);
if (extension_id.empty())
return nullptr;
return extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
extension_id, extensions::ExtensionRegistry::ENABLED);
}
class NetworkPortalNotificationControllerDelegate
: public message_center::NotificationDelegate {
public:
explicit NetworkPortalNotificationControllerDelegate(
const std::string& extension_id,
const std::string& guid,
base::WeakPtr<NetworkPortalNotificationController> controller)
: extension_id_(extension_id),
guid_(guid),
clicked_(false),
controller_(controller) {}
: guid_(guid), clicked_(false), controller_(controller) {}
// Overridden from message_center::NotificationDelegate:
void Click(const base::Optional<int>& button_index,
@ -113,10 +68,6 @@ class NetworkPortalNotificationControllerDelegate
private:
~NetworkPortalNotificationControllerDelegate() override {}
// ID of the extension responsible for network configuration of the network
// that this notification is generated for. Empty if none.
std::string extension_id_;
// GUID of the network this notification is generated for.
std::string guid_;
@ -130,27 +81,6 @@ class NetworkPortalNotificationControllerDelegate
void NetworkPortalNotificationControllerDelegate::Click(
const base::Optional<int>& button_index,
const base::Optional<base::string16>& reply) {
if (button_index &&
*button_index ==
NetworkPortalNotificationController::kUseExtensionButtonIndex) {
Profile* profile = GetProfileForPrimaryUser();
// The user decided to notify the extension to authenticate to the captive
// portal. Notify the NetworkingConfigService, which in turn will notify the
// extension. OnExtensionFinsihedAuthentication will be called back if the
// authentication succeeded.
extensions::NetworkingConfigServiceFactory::GetForBrowserContext(profile)
->DispatchPortalDetectedEvent(
extension_id_, guid_,
base::BindRepeating(&NetworkPortalNotificationController::
OnExtensionFinishedAuthentication,
controller_));
return;
}
DCHECK(!button_index ||
*button_index ==
NetworkPortalNotificationController::kOpenPortalButtonIndex);
clicked_ = true;
Profile* profile = ProfileManager::GetActiveUserProfile();
@ -174,27 +104,13 @@ void NetworkPortalNotificationControllerDelegate::Click(
} // namespace
// static
const int NetworkPortalNotificationController::kUseExtensionButtonIndex = 0;
// static
const int NetworkPortalNotificationController::kOpenPortalButtonIndex = 1;
// static
const char NetworkPortalNotificationController::kNotificationId[] =
"chrome://net/network_portal_detector";
// static
const char NetworkPortalNotificationController::kNotificationMetric[] =
"CaptivePortal.Notification.Status";
NetworkPortalNotificationController::NetworkPortalNotificationController(
NetworkPortalDetector* network_portal_detector)
: network_portal_detector_(network_portal_detector) {
if (NetworkHandler::IsInitialized()) { // May be false in tests.
NetworkHandler::Get()->network_state_handler()->AddObserver(this,
FROM_HERE);
}
if (network_portal_detector_) { // May be null in tests.
network_portal_detector_->AddObserver(this);
DCHECK(session_manager::SessionManager::Get());
@ -208,22 +124,6 @@ NetworkPortalNotificationController::~NetworkPortalNotificationController() {
session_manager::SessionManager::Get()->RemoveObserver(this);
network_portal_detector_->RemoveObserver(this);
}
if (NetworkHandler::IsInitialized()) {
NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
FROM_HERE);
}
}
void NetworkPortalNotificationController::DefaultNetworkChanged(
const NetworkState* network) {
if (!network)
return;
Profile* profile = GetProfileForPrimaryUser();
extensions::NetworkingConfigService* networking_config_service =
GetNetworkingConfigService(profile);
if (!networking_config_service)
return;
networking_config_service->ResetAuthenticationResult();
}
void NetworkPortalNotificationController::OnPortalDetectionCompleted(
@ -256,8 +156,9 @@ void NetworkPortalNotificationController::OnPortalDetectionCompleted(
return;
last_network_guid_ = network->guid();
SystemNotificationHelper::GetInstance()->Display(
*GetNotification(network, state));
std::unique_ptr<message_center::Notification> notification =
CreateDefaultCaptivePortalNotification(network);
SystemNotificationHelper::GetInstance()->Display(*notification);
}
void NetworkPortalNotificationController::OnShutdown() {
@ -294,10 +195,9 @@ void NetworkPortalNotificationController::OnDialogDestroyed(
std::unique_ptr<message_center::Notification>
NetworkPortalNotificationController::CreateDefaultCaptivePortalNotification(
const NetworkState* network) {
message_center::RichNotificationData data;
auto delegate =
base::MakeRefCounted<NetworkPortalNotificationControllerDelegate>(
std::string(), network->guid(), weak_factory_.GetWeakPtr());
network->guid(), weak_factory_.GetWeakPtr());
message_center::NotifierId notifier_id(
message_center::NotifierType::SYSTEM_COMPONENT,
kNotifierNetworkPortalDetector);
@ -312,91 +212,13 @@ NetworkPortalNotificationController::CreateDefaultCaptivePortalNotification(
is_wifi ? IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_WIFI
: IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_WIRED,
base::UTF8ToUTF16(network->name())),
base::string16(), GURL(), notifier_id, data, std::move(delegate),
kNotificationCaptivePortalIcon,
/*display_source=*/base::string16(), /*origin_url=*/GURL(),
notifier_id, message_center::RichNotificationData(),
std::move(delegate), kNotificationCaptivePortalIcon,
message_center::SystemNotificationWarningLevel::WARNING);
return notification;
}
std::unique_ptr<message_center::Notification>
NetworkPortalNotificationController::
CreateCaptivePortalNotificationForExtension(
const NetworkState* network,
extensions::NetworkingConfigService* networking_config_service,
const extensions::Extension* extension) {
message_center::RichNotificationData data;
auto delegate =
base::MakeRefCounted<NetworkPortalNotificationControllerDelegate>(
extension->id(), network->guid(), weak_factory_.GetWeakPtr());
message_center::NotifierId notifier_id(
message_center::NotifierType::SYSTEM_COMPONENT,
kNotifierNetworkPortalDetector);
extensions::NetworkingConfigService::AuthenticationResult
authentication_result =
networking_config_service->GetAuthenticationResult();
base::string16 notification_text;
if (authentication_result.authentication_state ==
extensions::NetworkingConfigService::NOTRY ||
network->guid() != authentication_result.guid) {
notification_text = l10n_util::GetStringFUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_ASK_WIFI,
base::UTF8ToUTF16(network->name()));
data.buttons.push_back(
message_center::ButtonInfo(l10n_util::GetStringFUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_BUTTON_EXTENSION,
base::UTF8ToUTF16(extension->name()))));
data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_BUTTON_PORTAL)));
} else {
notification_text = l10n_util::GetStringFUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE_FAILED_WIFI,
base::UTF8ToUTF16(network->name()));
data.buttons.push_back(
message_center::ButtonInfo(l10n_util::GetStringFUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_BUTTON_EXTENSION_RETRY,
base::UTF8ToUTF16(extension->name()))));
data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_BUTTON_PORTAL)));
}
std::unique_ptr<message_center::Notification> notification =
ash::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE, kNotificationId,
l10n_util::GetStringUTF16(
IDS_PORTAL_DETECTION_NOTIFICATION_TITLE_WIFI),
notification_text, base::string16() /* display_source */, GURL(),
notifier_id, data, std::move(delegate),
kNotificationCaptivePortalIcon,
message_center::SystemNotificationWarningLevel::WARNING);
return notification;
}
std::unique_ptr<message_center::Notification>
NetworkPortalNotificationController::GetNotification(
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalState& state) {
Profile* profile = GetProfileForPrimaryUser();
extensions::NetworkingConfigService* networking_config_service =
GetNetworkingConfigService(profile);
std::string extension_id;
const extensions::Extension* extension = nullptr;
if (networking_config_service) {
extension = LookupExtensionForRawSsid(networking_config_service,
network->raw_ssid());
}
if (extension) {
return CreateCaptivePortalNotificationForExtension(
network, networking_config_service, extension);
} else {
return CreateDefaultCaptivePortalNotification(network);
}
}
void NetworkPortalNotificationController::OnExtensionFinishedAuthentication() {
if (network_portal_detector_)
network_portal_detector_->StartPortalDetection(true /* force */);
}
void NetworkPortalNotificationController::SetIgnoreNoNetworkForTesting() {
ignore_no_network_for_testing_ = true;
}

@ -9,16 +9,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "chromeos/network/portal_detector/network_portal_detector.h"
#include "components/session_manager/core/session_manager_observer.h"
#include "ui/message_center/public/cpp/notification.h"
namespace extensions {
class Extension;
class NetworkingConfigService;
} // namespace extensions
namespace chromeos {
class NetworkState;
@ -28,8 +22,7 @@ class NetworkPortalNotificationControllerTest;
// Shows a message center notification when the networking stack detects a
// captive portal.
class NetworkPortalNotificationController
: public NetworkStateHandlerObserver,
public NetworkPortalDetector::Observer,
: public NetworkPortalDetector::Observer,
public session_manager::SessionManagerObserver {
public:
// The values of these metrics are being used for UMA gathering, so it is
@ -41,13 +34,8 @@ class NetworkPortalNotificationController
USER_ACTION_METRIC_COUNT
};
static const int kUseExtensionButtonIndex;
static const int kOpenPortalButtonIndex;
static const char kNotificationId[];
static const char kNotificationMetric[];
explicit NetworkPortalNotificationController(
NetworkPortalDetector* network_portal_dectector);
~NetworkPortalNotificationController() override;
@ -61,10 +49,6 @@ class NetworkPortalNotificationController
// NULLifies reference to the active dialog.
void OnDialogDestroyed(const NetworkPortalWebDialog* dialog);
// Called if an extension has successfully finished authentication to the
// previously detected captive portal.
void OnExtensionFinishedAuthentication();
// Ignores "No network" errors in browser tests.
void SetIgnoreNoNetworkForTesting();
@ -81,26 +65,12 @@ class NetworkPortalNotificationController
std::unique_ptr<message_center::Notification>
CreateDefaultCaptivePortalNotification(const NetworkState* network);
// Creates an advanced captive portal notification informing the user that a
// captive portal has been detected and an extension has registered to perform
// captive portal authentication for that network. Gives the user the choice
// to either authenticate using that extension or open the captive portal
// login page in the browser.
std::unique_ptr<message_center::Notification>
CreateCaptivePortalNotificationForExtension(
const NetworkState* network,
extensions::NetworkingConfigService* networking_config_service,
const extensions::Extension* extension);
// Constructs a notification to inform the user that a captive portal has been
// detected.
std::unique_ptr<message_center::Notification> GetNotification(
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalState& state);
// NetworkStateHandlerObserver:
void DefaultNetworkChanged(const NetworkState* network) override;
// NetworkPortalDetector::Observer:
void OnPortalDetectionCompleted(
const NetworkState* network,

Binary file not shown.

Before

(image error) Size: 28 KiB

Binary file not shown.

Before

(image error) Size: 14 KiB

@ -0,0 +1,5 @@
<h1>chrome.networking.config</h1>
<p>
The <code>chrome.networking.config</code> API is no longer supported.
</p>

@ -1,83 +0,0 @@
<h2 id="usage">Implementing a Captive Portal Authenticator</h2>
This API allows an Extension to implement an authenticator for captive portals.
The interaction between Extension, Chrome, and the user will be:
<ol>
<li>Using $(ref:setNetworkFilter), the Extension registers for a list of Wi-Fi
networks that it wants to handle captive portals on.</li>
<li>If one of these networks is detected by Chrome, it will appear in the
network list, badged with an icon to indicate that a captive portal handler is
available.
<p>
<img src="{{static}}/images/networking_config_badge.png"
align="middle" width="301" height="305" alt="Badge icon in tray network list" />
</li>
<li>If the user selects such a network, but a captive portal is not detected,
Chrome will connect as usual - the Extension will never be involved.</li>
<li>Otherwise, if a captive portal is detected, the user is notified and asked
to authenticate using the registered Extension or whether to visit the captive
portal page.
<p>
<img src="{{static}}/images/networking_config_notification.png"
align="middle" width="367" height="224" alt="Captive portal notification" />
</li>
<li>If the user selects the Extension, Chrome notifies the Extension through
the $(ref:onCaptivePortalDetected) event.</li>
<li>The Extension should now interact with the user if necessary and
authenticate at the captive portal.</li>
<li>Once the Extension finished the authentication, it notifies the API using
$(ref:finishAuthentication) about its success or failure.</li>
</ol>
<p>
In the Extension, this can look similar to the following snippet:
</p>
<pre data-filename="background.js">
var myNetworks = [
{ Type: 'WiFi', SSID: 'MyHotSpot-1' },
{ Type: 'WiFi', SSID: 'MyHotSpot-2' }
];
chrome.networking.config.setNetworkFilter(myNetworks, function() {
if (chrome.runtime.lastError) {
// Handle Error
}
});
chrome.networking.config.onCaptivePortalDetected.addListener(
function(networkInfo) {
var guid = networkInfo.GUID;
// Check at first whether we really care about this network.
// This can look at additional network properties like BSSID that are not
// supported in the filter.
if (isBadNetwork(networkInfo)) {
chrome.networking.config.finishAuthentication(guid, 'unhandled');
return;
}
checkForMyCaptivePortalServer(function(serverStatus) {
if (serverStatus == 'not-detected') {
chrome.networking.config.finishAuthentication(guid, 'unhandled');
return;
}
if (serverStatus == 'error') {
chrome.networking.config.finishAuthentication(guid, 'failed');
return;
}
// If required, interact with the user, e.g. for registration on first
// usage. Credentials can be cached for subsequent authentications.
ShowUIToRegisterUser(continueAuthentication.bind(null, guid));
});
});
function continueAuthentication(guid, credentials) {
if (!credentials) {
chrome.networking.config.finishAuthentication(guid, 'failed');
}
AuthenticateToMyCaptivePortalServer(credentials, function(success) {
chrome.networking.config.finishAuthentication(
guid, success ? 'succeeded' : 'rejected');
});
}
</pre>

@ -1 +1 @@
{{+partials.standard_extensions_api api:apis.extensions.networking_config intro:intros.networking_config chrome_os_only:true/}}
{{+partials.standard_extensions_article article:articles.networking_config/}}

@ -564,9 +564,6 @@ ChromePermissionMessageRule::GetAllRules() {
{IDS_EXTENSION_PROMPT_WARNING_NETWORKING_PRIVATE,
{APIPermission::kNetworkingPrivate},
{}},
{IDS_EXTENSION_PROMPT_WARNING_NETWORKING_CONFIG,
{APIPermission::kNetworkingConfig},
{}},
{IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE,
{APIPermission::kNetworkState},
{}},

@ -2087,7 +2087,6 @@ if (!is_android) {
"../browser/extensions/api/force_installed_affiliated_extension_apitest.cc",
"../browser/extensions/api/force_installed_affiliated_extension_apitest.h",
"../browser/extensions/api/input_ime/input_ime_apitest_chromeos.cc",
"../browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc",
"../browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc",
"../browser/extensions/api/platform_keys/platform_keys_test_base.cc",
"../browser/extensions/api/platform_keys/platform_keys_test_base.h",

@ -1,4 +0,0 @@
stevenjb@chromium.org
emaxx@chromium.org
# COMPONENT: OS>Systems>Network

@ -1,6 +0,0 @@
<!--
* 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.
-->
<script src="api_availability.js"></script>

@ -1,11 +0,0 @@
// 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();

@ -1,7 +0,0 @@
<!--
* 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.
-->
<script src="full_test.js"></script>

@ -1,46 +0,0 @@
// 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 fail = chrome.test.fail;
var succeed = chrome.test.succeed;
var callbackPass = chrome.test.callbackPass;
chrome.networking.config.onCaptivePortalDetected.addListener(
function(networkInfo) {
function onDetectionTest() {
assertTrue(!chrome.runtime.lastError);
var expectedInfo = {
Type: 'WiFi',
GUID: 'wifi1_guid',
SSID: 'wifi1',
HexSSID: '7769666931',
BSSID: '01:02:ab:7f:90:00'
};
assertEq(expectedInfo, networkInfo);
chrome.networking.config.finishAuthentication(
networkInfo.GUID, 'succeeded', function() {
if (chrome.runtime.lastError) {
fail(chrome.runtime.lastError.message);
}
});
// This hands control back to C++.
succeed();
}
chrome.test.runTests([onDetectionTest]);
});
function initialSetupTest() {
// |callbackPass()| will hand control back to the test in C++, which will
// trigger an |onCaptivePortalDetected| event that is handled by the listener
// above.
chrome.networking.config.setNetworkFilter([{Type: 'WiFi', SSID: 'wifi1'}],
callbackPass());
}
chrome.test.runTests([initialSetupTest]);

@ -1,8 +0,0 @@
{
"name": "networking.config browser tests",
"version": "0.1",
"manifest_version": 2,
"permissions": [
"networking.config"
]
}

@ -1,6 +0,0 @@
<!--
* 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.
-->
<script src="register_networks.js"></script>

@ -1,45 +0,0 @@
// 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();

@ -1,9 +0,0 @@
// Copyright 2016 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.
// Register this extension as the network handler for wifi1.
chrome.networking.config.setNetworkFilter([{Type: 'WiFi', SSID: 'wifi1'}],
function() {
chrome.test.sendMessage('done');
});

@ -1,11 +0,0 @@
{
"name": "NetworkingConfig test extension",
"version": "0.1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"permissions": [
"networking.config"
]
}

@ -759,7 +759,6 @@ source_set("unit_tests") {
"api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc",
"api/media_perception_private/conversion_utils_unittest.cc",
"api/media_perception_private/media_perception_api_manager_unittest.cc",
"api/networking_config/networking_config_service_chromeos_unittest.cc",
"api/networking_private/networking_private_chromeos_unittest.cc",
"api/system_power_source/system_power_source_api_unittest.cc",
"api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc",

@ -132,7 +132,6 @@ source_set("api") {
"//extensions/browser/api/clipboard",
"//extensions/browser/api/crash_report_private",
"//extensions/browser/api/diagnostics",
"//extensions/browser/api/networking_config",
"//extensions/browser/api/system_power_source",
"//extensions/browser/api/virtual_keyboard",
"//extensions/browser/api/vpn_provider",

@ -1,25 +0,0 @@
# Copyright 2016 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.
import("//extensions/buildflags/buildflags.gni")
assert(enable_extensions,
"Cannot depend on extensions because enable_extensions=false.")
assert(is_chromeos)
source_set("networking_config") {
sources = [
"networking_config_api.cc",
"networking_config_api.h",
"networking_config_service.cc",
"networking_config_service.h",
"networking_config_service_factory.cc",
"networking_config_service_factory.h",
]
deps = [ "//extensions/common/api" ]
public_deps = [ "//extensions/browser:browser_sources" ]
}

@ -1,4 +0,0 @@
stevenjb@chromium.org
emaxx@chromium.org
# COMPONENT: OS>Systems>Network

@ -1,127 +0,0 @@
// 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 <string>
#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_ =
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 (const api::networking_config::NetworkInfo& ni : parameters_->networks) {
// |Type| field must be set to |WiFi|
if (ni.type != 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_ =
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) {
return RespondNow(Error(kAuthenticationResultFailed));
}
// Populate NetworkingCaptivePortalAPI::AuthenticationResult.
NetworkingConfigService::AuthenticationResult authentication_result = {
extension_id(), parameters_->guid, NetworkingConfigService::FAILED,
};
switch (parameters_->result) {
case api::networking_config::AUTHENTICATION_RESULT_NONE:
NOTREACHED();
break;
case api::networking_config::AUTHENTICATION_RESULT_UNHANDLED:
authentication_result.authentication_state =
NetworkingConfigService::FAILED;
break;
case api::networking_config::AUTHENTICATION_RESULT_REJECTED:
authentication_result.authentication_state =
NetworkingConfigService::REJECTED;
break;
case api::networking_config::AUTHENTICATION_RESULT_FAILED:
authentication_result.authentication_state =
NetworkingConfigService::FAILED;
break;
case api::networking_config::AUTHENTICATION_RESULT_SUCCEEDED:
authentication_result.authentication_state =
NetworkingConfigService::SUCCESS;
break;
}
service->SetAuthenticationResult(authentication_result);
return RespondNow(NoArguments());
}
NetworkingConfigFinishAuthenticationFunction::
~NetworkingConfigFinishAuthenticationFunction() {
}
} // namespace extensions

@ -1,53 +0,0 @@
// 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 "base/macros.h"
#include "extensions/browser/extension_function.h"
#include "extensions/common/api/networking_config.h"
namespace extensions {
class NetworkingConfigSetNetworkFilterFunction : public ExtensionFunction {
public:
NetworkingConfigSetNetworkFilterFunction();
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("networking.config.setNetworkFilter",
NETWORKING_CONFIG_SETNETWORKFILTER)
protected:
~NetworkingConfigSetNetworkFilterFunction() override;
std::unique_ptr<api::networking_config::SetNetworkFilter::Params> parameters_;
private:
DISALLOW_COPY_AND_ASSIGN(NetworkingConfigSetNetworkFilterFunction);
};
class NetworkingConfigFinishAuthenticationFunction : public ExtensionFunction {
public:
NetworkingConfigFinishAuthenticationFunction();
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("networking.config.finishAuthentication",
NETWORKING_CONFIG_FINISHAUTHENTICATION)
protected:
~NetworkingConfigFinishAuthenticationFunction() override;
std::unique_ptr<api::networking_config::FinishAuthentication::Params>
parameters_;
private:
DISALLOW_COPY_AND_ASSIGN(NetworkingConfigFinishAuthenticationFunction);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_API_H_

@ -1,27 +0,0 @@
// 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 <string>
#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_;
}

@ -1,229 +0,0 @@
// 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.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "extensions/common/api/networking_config.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 (!base::IsHexDigit<char>(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(
content::BrowserContext* browser_context,
std::unique_ptr<EventDelegate> event_delegate,
ExtensionRegistry* extension_registry)
: browser_context_(browser_context),
event_delegate_(std::move(event_delegate)) {
registry_observer_.Add(extension_registry);
}
NetworkingConfigService::~NetworkingConfigService() = default;
void NetworkingConfigService::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason 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(
const 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);
// If |hex_ssid| is already in the map, i.e. if a hex ssid is already
// registered, this call should fail. TODO(stevenjb): Return an error code so
// that the extension API can respond with a better error.
if (!hex_ssid_to_extension_id_.insert(make_pair(hex_ssid, extension_id))
.second) {
LOG(ERROR) << "\'" << hex_ssid << "\' is already registered.";
return false;
}
// This method no longer actually does anything. TODO(1124419) Remove the
// networking.config API entirely in a follow-up.
return true;
}
void NetworkingConfigService::UnregisterExtension(
const std::string& extension_id) {
// This method no longer actually does anything. TODO(1124419) Remove the
// networking.config API entirely in a follow-up.
}
const NetworkingConfigService::AuthenticationResult&
NetworkingConfigService::GetAuthenticationResult() const {
return authentication_result_;
}
void NetworkingConfigService::ResetAuthenticationResult() {
authentication_result_ = AuthenticationResult();
authentication_callback_.Reset();
}
void NetworkingConfigService::SetAuthenticationResult(
const AuthenticationResult& authentication_result) {
authentication_result_ = authentication_result;
if (authentication_result.authentication_state != SUCCESS) {
LOG(WARNING) << "Captive Portal Authentication failed.";
return;
}
if (!authentication_callback_.is_null()) {
authentication_callback_.Run();
authentication_callback_.Reset();
}
}
void NetworkingConfigService::OnGetProperties(
const std::string& extension_id,
const std::string& guid,
const base::Closure& authentication_callback,
const std::string& service_path,
base::Optional<base::Value> onc_network_config,
base::Optional<std::string> error) {
if (!onc_network_config) {
LOG(WARNING) << "Failed to determine BSSID for network with guid " << guid
<< ": " << error.value_or("Failed");
std::unique_ptr<Event> event =
CreatePortalDetectedEventAndDispatch(extension_id, guid, nullptr);
EventRouter::Get(browser_context_)
->DispatchEventToExtension(extension_id, std::move(event));
return;
}
authentication_result_ = NetworkingConfigService::AuthenticationResult(
std::string(), guid, NetworkingConfigService::NOTRY);
authentication_callback_ = authentication_callback;
// Try to extract |bssid| field.
const base::Value* wifi_with_state =
onc_network_config->FindDictKey(::onc::network_config::kWiFi);
const std::string* bssid =
wifi_with_state ? wifi_with_state->FindStringKey(::onc::wifi::kBSSID)
: nullptr;
std::unique_ptr<Event> event =
CreatePortalDetectedEventAndDispatch(extension_id, guid, bssid);
EventRouter::Get(browser_context_)
->DispatchEventToExtension(extension_id, std::move(event));
}
std::unique_ptr<Event>
NetworkingConfigService::CreatePortalDetectedEventAndDispatch(
const std::string& extension_id,
const std::string& guid,
const std::string* bssid) {
const chromeos::NetworkState* network = chromeos::NetworkHandler::Get()
->network_state_handler()
->GetNetworkStateFromGuid(guid);
if (!network)
return nullptr;
// Populate the NetworkInfo object.
api::networking_config::NetworkInfo network_info;
network_info.type = api::networking_config::NETWORK_TYPE_WIFI;
const std::vector<uint8_t>& raw_ssid = network->raw_ssid();
std::string hex_ssid = base::HexEncode(raw_ssid.data(), raw_ssid.size());
network_info.hex_ssid = std::make_unique<std::string>(hex_ssid);
network_info.ssid = std::make_unique<std::string>(network->name());
network_info.guid = std::make_unique<std::string>(network->guid());
if (bssid)
network_info.bssid.reset(new std::string(*bssid));
std::unique_ptr<base::ListValue> results =
api::networking_config::OnCaptivePortalDetected::Create(network_info);
std::unique_ptr<Event> event(
new Event(events::NETWORKING_CONFIG_ON_CAPTIVE_PORTAL_DETECTED,
api::networking_config::OnCaptivePortalDetected::kEventName,
std::move(results)));
return event;
}
void NetworkingConfigService::DispatchPortalDetectedEvent(
const std::string& extension_id,
const std::string& guid,
const base::Closure& authentication_callback) {
// This dispatch starts a new cycle of portal detection and authentication.
// Ensure that any old |authentication_callback_| is dropped.
authentication_callback_.Reset();
// Determine |service_path| of network identified by |guid|.
chromeos::NetworkHandler* network_handler = chromeos::NetworkHandler::Get();
const chromeos::NetworkState* network =
network_handler->network_state_handler()->GetNetworkStateFromGuid(guid);
if (!network)
return;
const std::string service_path = network->path();
// We do not provide |userhash| here because we only care about properties
// that are not affected by policy, i.e BSSID.
network_handler->managed_network_configuration_handler()->GetProperties(
"" /* empty userhash */, service_path,
base::BindOnce(&NetworkingConfigService::OnGetProperties,
weak_factory_.GetWeakPtr(), extension_id, guid,
authentication_callback));
}
} // namespace extensions

@ -1,144 +0,0 @@
// 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 <map>
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "base/values.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/browser_context.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(content::BrowserContext* browser_context,
std::unique_ptr<EventDelegate> event_delegate,
ExtensionRegistry* extension_registry);
~NetworkingConfigService() override;
// ExtensionRegistryObserver
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason 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(const 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 extension 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);
// Sends a PortalDetected event for the network with |guid| to the extension
// with |extension_id|.
// |authentication_callback| is stored and called if the extension finishes
// authentication succesfully. This Service handles at most one portal
// detection at a time, i.e. another call to this function or a not successful
// authentication will drop a previously provided |authentication_callback|.
void DispatchPortalDetectedEvent(
const std::string& extension_id,
const std::string& guid,
const base::Closure& authentication_callback);
private:
void OnGetProperties(const std::string& extension_id,
const std::string& guid,
const base::Closure& authentication_callback,
const std::string& service_path,
base::Optional<base::Value> onc_network_config,
base::Optional<std::string> error);
// Creates the captive portal event about the network with guid |guid| that is
// to be dispatched to the extension identified by |extension_id|. |bssid|
// contains a human readable, hex-encoded version of the BSSID with bytes
// separated by colons, e.g. 45:67:89:ab:cd:ef.
std::unique_ptr<Event> CreatePortalDetectedEventAndDispatch(
const std::string& extension_id,
const std::string& guid,
const std::string* bssid);
content::BrowserContext* const browser_context_;
AuthenticationResult authentication_result_;
base::Closure authentication_callback_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
registry_observer_{this};
std::unique_ptr<EventDelegate> event_delegate_;
// This map associates a given hex encoded SSID to an extension entry.
std::map<std::string, std::string> hex_ssid_to_extension_id_;
base::WeakPtrFactory<NetworkingConfigService> weak_factory_{this};
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_NETWORKING_CONFIG_NETWORKING_CONFIG_SERVICE_H_

@ -1,86 +0,0 @@
// 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 <utility>
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/network/network_handler.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();
chromeos::DBusThreadManager::Initialize();
chromeos::NetworkHandler::Initialize();
extension_registry_ = std::unique_ptr<ExtensionRegistry>(
new ExtensionRegistry(browser_context()));
std::unique_ptr<MockEventDelegate> mock_event_delegate =
std::unique_ptr<MockEventDelegate>(new MockEventDelegate());
service_ =
std::unique_ptr<NetworkingConfigService>(new NetworkingConfigService(
browser_context(), std::move(mock_event_delegate),
extension_registry_.get()));
DCHECK(service_);
}
void TearDown() override {
chromeos::NetworkHandler::Shutdown();
chromeos::DBusThreadManager::Shutdown();
ApiUnitTest::TearDown();
}
protected:
std::unique_ptr<ExtensionRegistry> extension_registry_;
std::unique_ptr<NetworkingConfigService> 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

@ -1,83 +0,0 @@
// 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 <string>
#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,
api::networking_config::OnCaptivePortalDetected::kEventName);
}
} // namespace
// static
NetworkingConfigService* NetworkingConfigServiceFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<NetworkingConfigService*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
// static
NetworkingConfigServiceFactory* NetworkingConfigServiceFactory::GetInstance() {
return base::Singleton<NetworkingConfigServiceFactory>::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(
context, std::make_unique<DefaultEventDelegate>(context),
ExtensionRegistry::Get(context));
}
content::BrowserContext* NetworkingConfigServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
}
} // namespace extensions

@ -1,41 +0,0 @@
// 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 base::DefaultSingletonTraits<NetworkingConfigServiceFactory>;
NetworkingConfigServiceFactory();
~NetworkingConfigServiceFactory() override;
// BrowserContextKeyedServiceFactory
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_

@ -47,7 +47,6 @@
#if defined(OS_CHROMEOS)
#include "extensions/browser/api/clipboard/clipboard_api.h"
#include "extensions/browser/api/networking_config/networking_config_service_factory.h"
#include "extensions/browser/api/system_power_source/system_power_source_api.h"
#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h"
#include "extensions/browser/api/vpn_provider/vpn_service_factory.h"
@ -93,9 +92,6 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
HidDeviceManager::GetFactoryInstance();
IdleManagerFactory::GetInstance();
ManagementAPI::GetFactoryInstance();
#if defined(OS_CHROMEOS)
NetworkingConfigServiceFactory::GetInstance();
#endif
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) || \
defined(OS_MAC)
NetworkingPrivateEventRouterFactory::GetInstance();

@ -203,7 +203,7 @@ enum HistogramValue {
MEDIA_PLAYER_PRIVATE_ON_NEXT_TRACK = 182,
MEDIA_PLAYER_PRIVATE_ON_PREV_TRACK = 183,
MEDIA_PLAYER_PRIVATE_ON_TOGGLE_PLAY_STATE = 184,
NETWORKING_CONFIG_ON_CAPTIVE_PORTAL_DETECTED = 185,
DELETED_NETWORKING_CONFIG_ON_CAPTIVE_PORTAL_DETECTED = 185,
NETWORKING_PRIVATE_ON_DEVICE_STATE_LIST_CHANGED = 186,
NETWORKING_PRIVATE_ON_NETWORK_LIST_CHANGED = 187,
NETWORKING_PRIVATE_ON_NETWORKS_CHANGED = 188,

@ -1013,8 +1013,8 @@ enum HistogramValue {
FILEMANAGERPRIVATE_SEARCHFILESBYHASHES = 952,
DELETED_EASYUNLOCKPRIVATE_SHOWERRORBUBBLE = 953,
DELETED_EXTENSIONVIEWINTERNAL_NAVIGATE = 954, // Obsolete: crbug.com/982858
NETWORKING_CONFIG_SETNETWORKFILTER = 955,
NETWORKING_CONFIG_FINISHAUTHENTICATION = 956,
DELETED_NETWORKING_CONFIG_SETNETWORKFILTER = 955,
DELETED_NETWORKING_CONFIG_FINISHAUTHENTICATION = 956,
PLATFORMKEYSINTERNAL_SELECTCLIENTCERTIFICATES = 957,
CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID = 958,
DELETED_EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT = 959,

@ -387,10 +387,6 @@
"location": "policy",
"platforms": ["chromeos"]
}],
"networking.config": {
"dependencies": ["permission:networking.config"],
"contexts": ["blessed_extension"]
},
"networking.onc": {
"dependencies": ["permission:networking.onc"],
"contexts": ["blessed_extension"],

@ -460,11 +460,6 @@
"extension", "legacy_packaged_app", "platform_app"
]
},
"networking.config": {
"channel": "stable",
"platforms": ["chromeos"],
"extension_types": ["extension", "platform_app"]
},
"networking.onc": [{
"channel": "stable",
"extension_types": ["platform_app"],

@ -1,103 +0,0 @@
// 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 the <code>networking.config</code> API to authenticate to captive
// portals.
namespace networking.config {
// Indicator for the type of network used in $(ref:NetworkInfo).
enum NetworkType { WiFi };
// A dictionary identifying filtered networks. One of <code>GUID</code>,
// <code>SSID</code> or <code>HexSSID</code> must be set. <code>BSSID</code>
// and <code>Security</code> are ignored when filtering networks.
dictionary NetworkInfo {
// Currently only WiFi supported.
NetworkType Type;
// A unique identifier of the network.
DOMString? GUID;
// A hex-encoded byte sequence.
DOMString? HexSSID;
// The decoded SSID of the network (default encoding is UTF-8). To filter
// for non-UTF-8 SSIDs, use HexSSID instead.
DOMString? SSID;
// The basic service set identification (BSSID) uniquely identifying the
// basic service set. <code>BSSID</code> is represented as a human readable,
// hex-encoded string with bytes separated by colons, e.g.
// 45:67:89:ab:cd:ef.
DOMString? BSSID;
// Identifier indicating the security type of the network. Valid values are
// <code>None</code>, <code>WEP-PSK</code>, <code>WPA-PSK</code> and
// <code>WPA-EAP</code>.
DOMString? Security;
};
// Argument to $(ref:finishAuthentication) indicating the result of the
// captive portal authentication attempt.
enum AuthenticationResult {
// The extension does not handle this network or captive portal (e.g. server
// end-point not found or not compatible).
unhandled,
// The extension handled this network and authenticated successfully.
succeeded,
// The extension handled this network, tried to authenticate, however was
// rejected by the server.
rejected,
// The extension handled this network, tried to authenticate, however failed
// due to an unspecified error.
failed
};
// Invoked by $(ref:setNetworkFilter) when the respective operation is
// finished.
callback SetNetworkFilterCallback = void();
// Invoked by $(ref: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
// installed by the extension before setting the new list.
// |networks|: Network filters to set. Every <code>NetworkInfo</code> must
// either have the <code>SSID</code> or <code>HexSSID</code>
// set. Other fields will be ignored.
// |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
// $(ref:onCaptivePortalDetected) event.
// |GUID|: Unique network identifier obtained from
// $(ref:onCaptivePortalDetected).
// |result|: The result of the authentication attempt.
// |callback|: Called back when this operation is finished.
void finishAuthentication(DOMString GUID, AuthenticationResult result,
optional FinishAuthenticationCallback callback);
};
interface Events {
// This event fires everytime a captive portal is detected on a network
// matching any of the currently registered network filters and the user
// consents to use the extension for authentication. Network filters may be
// set using the $(ref:setNetworkFilter).
// Upon receiving this event the extension should start its authentication
// attempt with the captive portal. When the extension finishes its attempt,
// it must call $(ref:finishAuthentication) with the <code>GUID</code>
// received with this event and the appropriate authentication result.
// |networkInfo|: Information about the network on which a captive portal
// was detected.
static void onCaptivePortalDetected(NetworkInfo networkInfo);
};
};

@ -70,7 +70,6 @@ if (is_chromeos) {
"diagnostics.idl",
"lock_screen_data.idl",
"media_perception_private.idl",
"networking_config.idl",
"vpn_provider.idl",
"webcam_private.idl",
]

@ -147,7 +147,7 @@ class APIPermission {
kMDns = 103,
kMusicManagerPrivate = 104,
kNativeMessaging = 105,
kNetworkingConfig = 106,
kDeleted_NetworkingConfig = 106,
kNetworkingPrivate = 107,
kDeleted_NotificationProvider = 108,
kNotifications = 109,

@ -100,8 +100,6 @@ constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
APIPermissionInfo::kFlagCannotBeOptional},
{APIPermission::kNativeMessaging, "nativeMessaging",
APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning},
{APIPermission::kNetworkingConfig, "networking.config",
APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning},
{APIPermission::kNetworkingOnc, "networking.onc"},
{APIPermission::kNetworkingPrivate, "networkingPrivate",
APIPermissionInfo::kFlagCannotBeOptional},

@ -23152,7 +23152,8 @@ Called by update_extension_histograms.py.-->
<int value="182" label="MEDIA_PLAYER_PRIVATE_ON_NEXT_TRACK"/>
<int value="183" label="MEDIA_PLAYER_PRIVATE_ON_PREV_TRACK"/>
<int value="184" label="MEDIA_PLAYER_PRIVATE_ON_TOGGLE_PLAY_STATE"/>
<int value="185" label="NETWORKING_CONFIG_ON_CAPTIVE_PORTAL_DETECTED"/>
<int value="185"
label="DELETED_NETWORKING_CONFIG_ON_CAPTIVE_PORTAL_DETECTED"/>
<int value="186" label="NETWORKING_PRIVATE_ON_DEVICE_STATE_LIST_CHANGED"/>
<int value="187" label="NETWORKING_PRIVATE_ON_NETWORK_LIST_CHANGED"/>
<int value="188" label="NETWORKING_PRIVATE_ON_NETWORKS_CHANGED"/>
@ -24452,8 +24453,8 @@ Called by update_extension_histograms.py.-->
<int value="952" label="FILEMANAGERPRIVATE_SEARCHFILESBYHASHES"/>
<int value="953" label="DELETED_EASYUNLOCKPRIVATE_SHOWERRORBUBBLE"/>
<int value="954" label="DELETED_EXTENSIONVIEWINTERNAL_NAVIGATE"/>
<int value="955" label="NETWORKING_CONFIG_SETNETWORKFILTER"/>
<int value="956" label="NETWORKING_CONFIG_FINISHAUTHENTICATION"/>
<int value="955" label="DELETED_NETWORKING_CONFIG_SETNETWORKFILTER"/>
<int value="956" label="DELETED_NETWORKING_CONFIG_FINISHAUTHENTICATION"/>
<int value="957" label="PLATFORMKEYSINTERNAL_SELECTCLIENTCERTIFICATES"/>
<int value="958" label="CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID"/>
<int value="959" label="DELETED_EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT"/>
@ -25523,7 +25524,7 @@ Called by update_extension_permission.py.-->
<int value="103" label="kMDns"/>
<int value="104" label="kMusicManagerPrivate"/>
<int value="105" label="kNativeMessaging"/>
<int value="106" label="kNetworkingConfig"/>
<int value="106" label="kDeleted_NetworkingConfig"/>
<int value="107" label="kNetworkingPrivate"/>
<int value="108" label="kDeleted_NotificationProvider"/>
<int value="109" label="kNotifications"/>