summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos
diff options
context:
space:
mode:
authorkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-02 19:07:27 +0000
committerkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-02 19:07:27 +0000
commit73cea4cc34d7b5244800cf0517aec65f8ab14fa7 (patch)
tree62149d627c1c366aa909b347df4270082f21a555 /chrome/browser/chromeos
parentc9c5e7617ee239d6e694a829627fbc8bc2eb7b12 (diff)
downloadchromium_src-73cea4cc34d7b5244800cf0517aec65f8ab14fa7.zip
chromium_src-73cea4cc34d7b5244800cf0517aec65f8ab14fa7.tar.gz
chromium_src-73cea4cc34d7b5244800cf0517aec65f8ab14fa7.tar.bz2
Implements chrome as a dbus service that exposes chrome functionalities, in
addition to its client role that listens to signals from other chromeos dbus services. For now, it exposes the functionality of resolving network proxies for specified urls from chromeos clients. Implements read-write access APIs for proxy settings, will be used by UI to check if current user can read or write proxy settings. BUG=chromium-os:8890,chromium-os:6839 TEST=none Review URL: http://codereview.chromium.org/5054001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73487 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
-rw-r--r--chrome/browser/chromeos/cros/cros_library.cc3
-rw-r--r--chrome/browser/chromeos/cros/cros_library.h4
-rw-r--r--chrome/browser/chromeos/cros/libcros_service_library.cc335
-rw-r--r--chrome/browser/chromeos/cros/libcros_service_library.h30
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.cc52
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.h10
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl_unittest.cc203
7 files changed, 582 insertions, 55 deletions
diff --git a/chrome/browser/chromeos/cros/cros_library.cc b/chrome/browser/chromeos/cros/cros_library.cc
index af6e426..5d22643 100644
--- a/chrome/browser/chromeos/cros/cros_library.cc
+++ b/chrome/browser/chromeos/cros/cros_library.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/cros/keyboard_library.h"
+#include "chrome/browser/chromeos/cros/libcros_service_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/mount_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
@@ -62,6 +63,7 @@ DEFINE_GET_LIBRARY_METHOD(Burn, burn);
DEFINE_GET_LIBRARY_METHOD(Cryptohome, crypto);
DEFINE_GET_LIBRARY_METHOD(Keyboard, keyboard);
DEFINE_GET_LIBRARY_METHOD(InputMethod, input_method);
+DEFINE_GET_LIBRARY_METHOD(LibCrosService, libcros_service);
DEFINE_GET_LIBRARY_METHOD(Login, login);
DEFINE_GET_LIBRARY_METHOD(Mount, mount);
DEFINE_GET_LIBRARY_METHOD(Network, network);
@@ -120,6 +122,7 @@ DEFINE_SET_LIBRARY_METHOD(Burn, burn);
DEFINE_SET_LIBRARY_METHOD(Cryptohome, crypto);
DEFINE_SET_LIBRARY_METHOD(Keyboard, keyboard);
DEFINE_SET_LIBRARY_METHOD(InputMethod, input_method);
+DEFINE_SET_LIBRARY_METHOD(LibCrosService, libcros_service);
DEFINE_SET_LIBRARY_METHOD(Login, login);
DEFINE_SET_LIBRARY_METHOD(Mount, mount);
DEFINE_SET_LIBRARY_METHOD(Network, network);
diff --git a/chrome/browser/chromeos/cros/cros_library.h b/chrome/browser/chromeos/cros/cros_library.h
index 9c5810c..1781d2b 100644
--- a/chrome/browser/chromeos/cros/cros_library.h
+++ b/chrome/browser/chromeos/cros/cros_library.h
@@ -23,6 +23,7 @@ class BurnLibrary;
class CryptohomeLibrary;
class InputMethodLibrary;
class KeyboardLibrary;
+class LibCrosServiceLibrary;
class LibraryLoader;
class LoginLibrary;
class MountLibrary;
@@ -62,6 +63,7 @@ class CrosLibrary {
void SetCryptohomeLibrary(CryptohomeLibrary* library, bool own);
void SetKeyboardLibrary(KeyboardLibrary* library, bool own);
void SetInputMethodLibrary(InputMethodLibrary* library, bool own);
+ void SetLibCrosServiceLibrary(LibCrosServiceLibrary* library, bool own);
void SetLoginLibrary(LoginLibrary* library, bool own);
void SetMountLibrary(MountLibrary* library, bool own);
void SetNetworkLibrary(NetworkLibrary* library, bool own);
@@ -86,6 +88,7 @@ class CrosLibrary {
BurnLibrary* GetBurnLibrary();
CryptohomeLibrary* GetCryptohomeLibrary();
InputMethodLibrary* GetInputMethodLibrary();
+ LibCrosServiceLibrary* GetLibCrosServiceLibrary();
KeyboardLibrary* GetKeyboardLibrary();
LoginLibrary* GetLoginLibrary();
MountLibrary* GetMountLibrary();
@@ -163,6 +166,7 @@ class CrosLibrary {
Library<CryptohomeLibrary> crypto_lib_;
Library<KeyboardLibrary> keyboard_lib_;
Library<InputMethodLibrary> input_method_lib_;
+ Library<LibCrosServiceLibrary> libcros_service_lib_;
Library<LoginLibrary> login_lib_;
Library<MountLibrary> mount_lib_;
Library<NetworkLibrary> network_lib_;
diff --git a/chrome/browser/chromeos/cros/libcros_service_library.cc b/chrome/browser/chromeos/cros/libcros_service_library.cc
new file mode 100644
index 0000000..9e095b4
--- /dev/null
+++ b/chrome/browser/chromeos/cros/libcros_service_library.cc
@@ -0,0 +1,335 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/cros/libcros_service_library.h"
+
+#include "base/synchronization/lock.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "cros/chromeos_libcros_service.h"
+#include "net/base/net_errors.h"
+#include "net/proxy/proxy_service.h"
+
+namespace chromeos {
+
+class LibCrosServiceLibraryImpl : public LibCrosServiceLibrary {
+ public:
+ // Base class for all services of LibCrosService.
+ // Each subclass should declare DISABLE_RUNNABLE_METHOD_REFCOUNT to disable
+ // refcounting, which is okay since the subclass's object will exist as a
+ // scoped_ptr in Singleton LibCrosServiceLibraryImpl, guaranteeing that its
+ // lifetime is longer than that of any message loop.
+ class ServicingLibrary {
+ public:
+ explicit ServicingLibrary(LibCrosServiceConnection service_connection);
+ virtual ~ServicingLibrary();
+
+ // Clears service_connection_ (which is stored as weak pointer) so that it
+ // can't be used anymore.
+ virtual void ClearServiceConnection();
+
+ protected:
+ LibCrosServiceConnection service_connection_; // Weak pointer.
+ // Lock for data members to synchronize access on multiple threads.
+ base::Lock data_lock_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServicingLibrary);
+ };
+
+ // Library that provides network proxy service for LibCrosService.
+ // For now, it only processes proxy resolution requests for ChromeOS clients.
+ class NetworkProxyLibrary : public ServicingLibrary {
+ public:
+ explicit NetworkProxyLibrary(LibCrosServiceConnection connection);
+ virtual ~NetworkProxyLibrary();
+
+ // Sets the ProxyService that will handle network proxy requests, e.g.
+ // proxy resolution for a url.
+ void SetHandler(net::ProxyService* handler);
+
+ private:
+ // Data being used in one proxy resolution.
+ class Request {
+ public:
+ explicit Request(const std::string& source_url);
+ virtual ~Request() {}
+
+ // Callback on IO thread for when net::ProxyService::ResolveProxy
+ // completes, synchronously or asynchronously.
+ void OnCompletion(int result);
+ net::CompletionCallbackImpl<Request> completion_callback_;
+
+ std::string source_url_; // URL being resolved.
+ int result_; // Result of proxy resolution.
+ net::ProxyInfo proxy_info_; // ProxyInfo resolved for source_url_.
+ std::string error_; // Error from proxy resolution.
+ Task* notify_task_; // Task to notify of resolution result.
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Request);
+ };
+
+ // Static callback passed to LibCrosService to be invoked when ChromeOS
+ // clients send network proxy resolution requests to the service running in
+ // chrome executable. Called on UI thread from dbus request.
+ static void ResolveProxyHandler(void* object,
+ const char* source_url);
+
+ void ResolveProxy(const std::string& source_url);
+
+ // Wrapper on UI thread to call LibCrosService::NotifyNetworkProxyResolved.
+ void NotifyProxyResolved(Request* request);
+
+ // ProxyService to call ResolveProxy on.
+ scoped_refptr<net::ProxyService> proxy_service_;
+
+ std::vector<Request*> all_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkProxyLibrary);
+ };
+
+ LibCrosServiceLibraryImpl();
+ virtual ~LibCrosServiceLibraryImpl();
+
+ // LibCrosServiceLibrary implementation.
+ virtual void RegisterNetworkProxyHandler(net::ProxyService* handler);
+
+ private:
+ // Starts LibCrosService running on dbus if not already started.
+ bool StartService();
+
+ // Connection to LibCrosService.
+ LibCrosServiceConnection service_connection_;
+
+ // Libraries that form LibCrosService.
+ scoped_ptr<NetworkProxyLibrary> network_proxy_lib_;
+
+ DISALLOW_COPY_AND_ASSIGN(LibCrosServiceLibraryImpl);
+};
+
+//---------------- LibCrosServiceLibraryImpl: public ---------------------------
+
+LibCrosServiceLibraryImpl::LibCrosServiceLibraryImpl()
+ : service_connection_(NULL) {
+ if (!CrosLibrary::Get()->EnsureLoaded()) {
+ LOG(ERROR) << "Cros library has not been loaded.";
+ }
+}
+
+LibCrosServiceLibraryImpl::~LibCrosServiceLibraryImpl() {
+ if (service_connection_) {
+ // Clear service connections in servicing libraries which held the former
+ // as weak pointers.
+ if (network_proxy_lib_.get())
+ network_proxy_lib_->ClearServiceConnection();
+
+ StopLibCrosService(service_connection_);
+ VLOG(1) << "LibCrosService stopped.";
+ service_connection_ = NULL;
+ }
+}
+
+// Called on UI thread to register network proxy handler for LibCrosService.
+void LibCrosServiceLibraryImpl::RegisterNetworkProxyHandler(
+ net::ProxyService* handler) {
+ // Make sure we're running on UI thread.
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ scoped_refptr<net::ProxyService> ref_handler(handler);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &LibCrosServiceLibraryImpl::RegisterNetworkProxyHandler,
+ ref_handler));
+ return;
+ }
+ if (StartService()) {
+ if (!network_proxy_lib_.get())
+ network_proxy_lib_.reset(new NetworkProxyLibrary(service_connection_));
+ network_proxy_lib_->SetHandler(handler);
+ }
+}
+
+//---------------- LibCrosServiceLibraryImpl: private --------------------------
+
+bool LibCrosServiceLibraryImpl::StartService() {
+ if (service_connection_) // Service has already been started.
+ return true;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Starts LibCrosService; the returned connection is used for future
+ // interactions with the service.
+ service_connection_ = StartLibCrosService();
+ if (service_connection_) {
+ VLOG(1) << "LibCrosService started.";
+ return true;
+ }
+ LOG(WARNING) << "Error starting LibCrosService";
+ return false;
+}
+
+//------------- LibCrosServiceLibraryImpl::ServicingLibrary: public ------------
+
+LibCrosServiceLibraryImpl::ServicingLibrary::ServicingLibrary(
+ LibCrosServiceConnection connection)
+ : service_connection_(connection) {
+}
+
+LibCrosServiceLibraryImpl::ServicingLibrary::~ServicingLibrary() {
+ ClearServiceConnection();
+}
+
+void LibCrosServiceLibraryImpl::ServicingLibrary::ClearServiceConnection() {
+ base::AutoLock lock(data_lock_);
+ service_connection_ = NULL;
+}
+
+//----------- LibCrosServiceLibraryImpl::NetworkProxyLibrary: public -----------
+
+LibCrosServiceLibraryImpl::NetworkProxyLibrary::NetworkProxyLibrary(
+ LibCrosServiceConnection connection)
+ : ServicingLibrary(connection) {
+ // Register callback for LibCrosService::ResolveNetworkProxy.
+ SetNetworkProxyResolver(&ResolveProxyHandler, this, service_connection_);
+}
+
+LibCrosServiceLibraryImpl::NetworkProxyLibrary::~NetworkProxyLibrary() {
+ base::AutoLock lock(data_lock_);
+ if (!all_requests_.empty()) {
+ for (size_t i = all_requests_.size() - 1; i >= 0; --i) {
+ LOG(WARNING) << "Pending request for " << all_requests_[i]->source_url_;
+ delete all_requests_[i];
+ }
+ all_requests_.clear();
+ }
+}
+
+// Called on UI thread to register handler for LibCrosService's network proxy
+// requests.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::SetHandler(
+ net::ProxyService* handler) {
+ base::AutoLock lock(data_lock_);
+ DCHECK(service_connection_);
+ proxy_service_ = handler;
+}
+
+//----------- LibCrosServiceLibraryImpl::NetworkProxyLibrary: private ----------
+
+// Static, called on UI thread from LibCrosService::ResolveProxy via dbus.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::ResolveProxyHandler(
+ void* object, const char* source_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ NetworkProxyLibrary* lib = static_cast<NetworkProxyLibrary*>(object);
+ // source_url will be freed when this function returns, so make a copy of it.
+ std::string url(source_url);
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(lib, &NetworkProxyLibrary::ResolveProxy, url));
+}
+
+// Called on IO thread as task posted from ResolveProxyHandler on UI thread.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::ResolveProxy(
+ const std::string& source_url) {
+ // Make sure we're running on IO thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ Request* request = new Request(source_url);
+ request->notify_task_ = NewRunnableMethod(this,
+ &NetworkProxyLibrary::NotifyProxyResolved, request);
+ {
+ base::AutoLock lock(data_lock_);
+ all_requests_.push_back(request);
+ if (!service_connection_)
+ request->error_ = "LibCrosService not started";
+ else if (!proxy_service_)
+ request->error_ = "Network proxy resolver not registered";
+ }
+ if (request->error_ != "") {
+ LOG(ERROR) << request->error_;
+ request->result_ = net::OK; // Set to OK since error string is set.
+ } else {
+ VLOG(1) << "Starting networy proxy resolution for " << request->source_url_;
+ request->result_ = proxy_service_->ResolveProxy(
+ GURL(request->source_url_), &request->proxy_info_,
+ &request->completion_callback_, NULL, net::BoundNetLog());
+ }
+ if (request->result_ != net::ERR_IO_PENDING) {
+ VLOG(1) << "Network proxy resolution completed synchronously.";
+ request->OnCompletion(request->result_);
+ }
+}
+
+// Called on UI thread as task posted from Request::OnCompletion on IO thread.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::NotifyProxyResolved(
+ Request* request) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ base::AutoLock lock(data_lock_);
+ if (service_connection_) {
+ if (!NotifyNetworkProxyResolved(request->source_url_.c_str(),
+ request->proxy_info_.ToPacString().c_str(),
+ request->error_.c_str(),
+ service_connection_)) {
+ LOG(ERROR) << "LibCrosService has error with NotifyNetworkProxyResolved";
+ } else {
+ VLOG(1) << "LibCrosService has notified proxy resoloution for "
+ << request->source_url_;
+ }
+ }
+ std::vector<Request*>::iterator iter =
+ std::find(all_requests_.begin(), all_requests_.end(), request);
+ DCHECK(iter != all_requests_.end());
+ all_requests_.erase(iter);
+ delete request;
+}
+
+//---------- LibCrosServiceLibraryImpl::NetworkProxyLibrary::Request -----------
+
+LibCrosServiceLibraryImpl::NetworkProxyLibrary::Request::Request(
+ const std::string& source_url)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(
+ completion_callback_(this, &Request::OnCompletion)),
+ source_url_(source_url),
+ result_(net::ERR_FAILED),
+ notify_task_(NULL) {
+}
+
+// Called on IO thread when net::ProxyService::ResolveProxy has completed.
+void LibCrosServiceLibraryImpl::NetworkProxyLibrary::Request::OnCompletion(
+ int result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ result_ = result;
+ if (result_ != net::OK)
+ error_ = net::ErrorToString(result_);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, notify_task_);
+ notify_task_ = NULL;
+}
+
+//--------------------- LibCrosServiceLibraryStubImpl --------------------------
+
+class LibCrosServiceLibraryStubImpl : public LibCrosServiceLibrary {
+ public:
+ LibCrosServiceLibraryStubImpl() {}
+ virtual ~LibCrosServiceLibraryStubImpl() {}
+
+ // LibCrosServiceLibrary overrides.
+ virtual void RegisterNetworkProxyHandler(net::ProxyService* handler) {}
+
+ DISALLOW_COPY_AND_ASSIGN(LibCrosServiceLibraryStubImpl);
+};
+
+//--------------------------- LibCrosServiceLibrary ----------------------------
+
+// Static.
+LibCrosServiceLibrary* LibCrosServiceLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new LibCrosServiceLibraryStubImpl();
+ return new LibCrosServiceLibraryImpl();
+}
+
+} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run, so are all its
+// scoped_ptred class members.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::LibCrosServiceLibraryImpl);
+DISABLE_RUNNABLE_METHOD_REFCOUNT(
+ chromeos::LibCrosServiceLibraryImpl::NetworkProxyLibrary);
+
diff --git a/chrome/browser/chromeos/cros/libcros_service_library.h b/chrome/browser/chromeos/cros/libcros_service_library.h
new file mode 100644
index 0000000..d90cf33
--- /dev/null
+++ b/chrome/browser/chromeos/cros/libcros_service_library.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2010 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 CHROME_BROWSER_CHROMEOS_CROS_LIBCROS_SERVICE_LIBRARY_H_
+#define CHROME_BROWSER_CHROMEOS_CROS_LIBCROS_SERVICE_LIBRARY_H_
+#pragma once
+
+namespace net{
+class ProxyService;
+};
+
+namespace chromeos {
+
+class LibCrosServiceLibrary {
+ public:
+ virtual ~LibCrosServiceLibrary() {}
+
+ // Registers the ProxyService that will handle network proxy requests, e.g.
+ // proxy resolution for a url.
+ virtual void RegisterNetworkProxyHandler(net::ProxyService* handler) = 0;
+
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static LibCrosServiceLibrary* GetImpl(bool stub);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_CROS_LIBCROS_SERVICE_LIBRARY_H_
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.cc b/chrome/browser/chromeos/proxy_config_service_impl.cc
index 862459c..1aceb24 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl.cc
@@ -217,6 +217,48 @@ void ProxyConfigServiceImpl::ProxyConfig::ToNetProxyConfig(
}
}
+bool ProxyConfigServiceImpl::ProxyConfig::CanBeWrittenByUser(
+ bool user_is_owner, const std::string& scheme) {
+ // Setting can only be written by user if user is owner and setting is not
+ // from policy.
+ Setting* setting = NULL;
+ switch (mode) {
+ case MODE_DIRECT:
+ case MODE_AUTO_DETECT:
+ case MODE_PAC_SCRIPT:
+ setting = &automatic_proxy;
+ break;
+ case MODE_SINGLE_PROXY:
+ setting = &single_proxy;
+ break;
+ case MODE_PROXY_PER_SCHEME:
+ setting = MapSchemeToProxy(scheme);
+ break;
+ default:
+ break;
+ }
+ if (!setting) {
+ NOTREACHED() << "Unrecognized proxy config mode";
+ return false;
+ }
+ return setting->CanBeWrittenByUser(user_is_owner);
+}
+
+ProxyConfigServiceImpl::ProxyConfig::ManualProxy*
+ ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy(
+ const std::string& scheme) {
+ if (scheme == "http")
+ return &http_proxy;
+ if (scheme == "https")
+ return &https_proxy;
+ if (scheme == "ftp")
+ return &ftp_proxy;
+ if (scheme == "socks")
+ return &socks_proxy;
+ NOTREACHED() << "Invalid scheme: " << scheme;
+ return NULL;
+}
+
bool ProxyConfigServiceImpl::ProxyConfig::Serialize(std::string* output) {
scoped_ptr<DictionaryValue> dict(new DictionaryValue);
dict->SetInteger(kMode, mode);
@@ -428,15 +470,7 @@ bool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme(
const std::string& scheme, const net::ProxyServer& server) {
// Should be called from UI thread.
CheckCurrentlyOnUIThread();
- ProxyConfig::ManualProxy* proxy = NULL;
- if (scheme == "http")
- proxy = &reference_config_.http_proxy;
- else if (scheme == "https")
- proxy = &reference_config_.https_proxy;
- else if (scheme == "ftp")
- proxy = &reference_config_.ftp_proxy;
- else if (scheme == "socks")
- proxy = &reference_config_.socks_proxy;
+ ProxyConfig::ManualProxy* proxy = reference_config_.MapSchemeToProxy(scheme);
if (!proxy) {
NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]";
return false;
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.h b/chrome/browser/chromeos/proxy_config_service_impl.h
index 2e605a8..5f37b44 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.h
+++ b/chrome/browser/chromeos/proxy_config_service_impl.h
@@ -116,6 +116,15 @@ class ProxyConfigServiceImpl
// Converts |this| to net::ProxyConfig.
void ToNetProxyConfig(net::ProxyConfig* net_config);
+ // Returns true if proxy config can be written by user.
+ // If mode is MODE_PROXY_PER_SCHEME, |scheme| is one of "http", "https",
+ // "ftp" or "socks"; otherwise, it should be empty or will be ignored.
+ bool CanBeWrittenByUser(bool user_is_owner, const std::string& scheme);
+
+ // Map |scheme| (one of "http", "https", "ftp" or "socks") to the correct
+ // ManualProxy. Returns NULL if scheme is invalid.
+ ManualProxy* MapSchemeToProxy(const std::string& scheme);
+
// Serializes config into a DictionaryValue and then into std::string
// persisted as property on device.
bool Serialize(std::string* output);
@@ -184,6 +193,7 @@ class ProxyConfigServiceImpl
bool UISetProxyConfigToAutoDetect();
bool UISetProxyConfigToPACScript(const GURL& pac_url);
bool UISetProxyConfigToSingleProxy(const net::ProxyServer& server);
+ // |scheme| is one of "http", "https", "ftp" or "socks".
bool UISetProxyConfigToProxyPerScheme(const std::string& scheme,
const net::ProxyServer& server);
// Only valid for MODE_SINGLE_PROXY or MODE_PROXY_PER_SCHEME.
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index 15a8327..289e5d8 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -51,6 +51,7 @@ const struct {
std::string description;
bool is_valid;
+ bool test_read_write_access;
Input input;
@@ -61,7 +62,9 @@ const struct {
} tests[] = {
{
TEST_DESC("No proxying"),
+
true, // is_valid
+ true, // test_read_write_access
{ // Input.
MK_MODE(DIRECT), // mode
@@ -75,7 +78,9 @@ const struct {
{
TEST_DESC("Auto detect"),
+
true, // is_valid
+ true, // test_read_write_access
{ // Input.
MK_MODE(AUTO_DETECT), // mode
@@ -89,7 +94,9 @@ const struct {
{
TEST_DESC("Valid PAC URL"),
+
true, // is_valid
+ true, // test_read_write_access
{ // Input.
MK_MODE(PAC_SCRIPT), // mode
@@ -104,7 +111,9 @@ const struct {
{
TEST_DESC("Invalid PAC URL"),
+
false, // is_valid
+ false, // test_read_write_access
{ // Input.
MK_MODE(PAC_SCRIPT), // mode
@@ -119,7 +128,9 @@ const struct {
{
TEST_DESC("Single-host in proxy list"),
+
true, // is_valid
+ true, // test_read_write_access
{ // Input.
MK_MODE(SINGLE_PROXY), // mode
@@ -137,7 +148,9 @@ const struct {
{
TEST_DESC("Single-host, different port"),
- true, // is_valid
+
+ true, // is_valid
+ false, // test_read_write_access
{ // Input.
MK_MODE(SINGLE_PROXY), // mode
@@ -155,7 +168,9 @@ const struct {
{
TEST_DESC("Tolerate a scheme"),
- true, // is_valid
+
+ true, // is_valid
+ false, // test_read_write_access
{ // Input.
MK_MODE(SINGLE_PROXY), // mode
@@ -173,7 +188,9 @@ const struct {
{
TEST_DESC("Per-scheme proxy rules"),
+
true, // is_valid
+ true, // test_read_write_access
{ // Input.
MK_MODE(PROXY_PER_SCHEME), // mode
@@ -198,7 +215,9 @@ const struct {
{
TEST_DESC("Bypass rules"),
+
true, // is_valid
+ true, // test_read_write_access
{ // Input.
MK_MODE(SINGLE_PROXY), // mode
@@ -264,9 +283,8 @@ class ProxyConfigServiceImplTest : public PlatformTest {
}
void InitConfigWithTestInput(
- const Input& input,
+ const Input& input, ProxyConfigServiceImpl::ProxyConfig::Source source,
ProxyConfigServiceImpl::ProxyConfig* init_config) {
- ProxyConfigServiceImpl::ProxyConfig::Source source = MK_SRC(OWNER);
switch (input.mode) {
case MK_MODE(DIRECT):
case MK_MODE(AUTO_DETECT):
@@ -295,6 +313,90 @@ class ProxyConfigServiceImplTest : public PlatformTest {
}
}
+ void TestReadWriteAccessForMode(const Input& input,
+ ProxyConfigServiceImpl::ProxyConfig::Source source) {
+ // Init config from |source|.
+ ProxyConfigServiceImpl::ProxyConfig init_config;
+ InitConfigWithTestInput(input, source, &init_config);
+ CreateConfigService(init_config);
+
+ ProxyConfigServiceImpl::ProxyConfig config;
+ config_service()->UIGetProxyConfig(&config);
+
+ // For owner, write access to config should be equal CanBeWrittenByOwner().
+ // For non-owner, config is never writeable.
+ bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
+ if (config.mode == MK_MODE(PROXY_PER_SCHEME)) {
+ if (input.http_uri) {
+ EXPECT_EQ(expected_writeable_by_owner,
+ config.CanBeWrittenByUser(true, "http"));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, "http"));
+ }
+ if (input.https_uri) {
+ EXPECT_EQ(expected_writeable_by_owner,
+ config.CanBeWrittenByUser(true, "http"));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, "https"));
+ }
+ if (input.ftp_uri) {
+ EXPECT_EQ(expected_writeable_by_owner,
+ config.CanBeWrittenByUser(true, "http"));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, "ftp"));
+ }
+ if (input.socks_uri) {
+ EXPECT_EQ(expected_writeable_by_owner,
+ config.CanBeWrittenByUser(true, "http"));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, "socks"));
+ }
+ } else {
+ EXPECT_EQ(expected_writeable_by_owner,
+ config.CanBeWrittenByUser(true, std::string()));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, std::string()));
+ }
+ }
+
+ void TestReadWriteAccessForScheme(
+ ProxyConfigServiceImpl::ProxyConfig::Source source,
+ const char* server_uri,
+ const std::string& scheme) {
+ // Init with manual |scheme| proxy.
+ ProxyConfigServiceImpl::ProxyConfig init_config;
+ ProxyConfigServiceImpl::ProxyConfig::ManualProxy* proxy =
+ init_config.MapSchemeToProxy(scheme);
+ net::ProxyServer::Scheme net_scheme;
+ if (scheme == "http" || scheme == "ftp")
+ net_scheme = MK_SCHM(HTTP);
+ else if (scheme == "https")
+ net_scheme = MK_SCHM(HTTPS);
+ else if (scheme == "socks")
+ net_scheme = MK_SCHM(SOCKS4);
+ SetManualProxy(MK_MODE(PROXY_PER_SCHEME), source, server_uri, net_scheme,
+ &init_config, proxy);
+ CreateConfigService(init_config);
+
+ ProxyConfigServiceImpl::ProxyConfig config;
+ config_service()->UIGetProxyConfig(&config);
+
+ // For owner, write access to config should be equal CanBeWrittenByOwner().
+ // For non-owner, config is never writeable.
+ bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
+ EXPECT_EQ(expected_writeable_by_owner,
+ config.CanBeWrittenByUser(true, scheme));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, scheme));
+
+ const char* all_schemes[] = {
+ "http", "https", "ftp", "socks",
+ };
+
+ // Rest of protos should be writeable by owner, but not writeable by
+ // non-owner.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(all_schemes); ++i) {
+ if (scheme == all_schemes[i])
+ continue;
+ EXPECT_TRUE(config.CanBeWrittenByUser(true, all_schemes[i]));
+ EXPECT_FALSE(config.CanBeWrittenByUser(false, all_schemes[i]));
+ }
+ }
+
// Synchronously gets the latest proxy config.
bool SyncGetLatestProxyConfig(net::ProxyConfig* config) {
// Let message loop process all messages.
@@ -309,6 +411,11 @@ class ProxyConfigServiceImplTest : public PlatformTest {
}
private:
+ bool CanBeWrittenByOwner(
+ ProxyConfigServiceImpl::ProxyConfig::Source source) const {
+ return source == MK_SRC(POLICY) ? false : true;
+ }
+
ScopedStubCrosEnabler stub_cros_enabler_;
MessageLoop message_loop_;
BrowserThread ui_thread_;
@@ -319,11 +426,11 @@ class ProxyConfigServiceImplTest : public PlatformTest {
TEST_F(ProxyConfigServiceImplTest, ChromeosProxyConfigToNetProxyConfig) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
- tests[i].description.c_str()));
+ SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+ tests[i].description.c_str()));
ProxyConfigServiceImpl::ProxyConfig init_config;
- InitConfigWithTestInput(tests[i].input, &init_config);
+ InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &init_config);
CreateConfigService(init_config);
net::ProxyConfig config;
@@ -335,46 +442,10 @@ TEST_F(ProxyConfigServiceImplTest, ChromeosProxyConfigToNetProxyConfig) {
}
}
-TEST_F(ProxyConfigServiceImplTest, ReadWriteAccess) {
- static const char* pac_url = "http://wpad.dat";
-
- { // Init with pac script from policy.
- ProxyConfigServiceImpl::ProxyConfig init_config;
- SetAutomaticProxy(MK_MODE(PAC_SCRIPT), MK_SRC(POLICY), pac_url,
- &init_config, &init_config.automatic_proxy);
- CreateConfigService(init_config);
-
- ProxyConfigServiceImpl::ProxyConfig config;
- config_service()->UIGetProxyConfig(&config);
-
- EXPECT_EQ(MK_SRC(POLICY), config.automatic_proxy.source);
- // Setting should be not be writeable by owner.
- EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(true));
- // Setting should be not be writeable by non-owner.
- EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(false));
- }
-
- { // Init with pac script from owner.
- ProxyConfigServiceImpl::ProxyConfig init_config;
- SetAutomaticProxy(MK_MODE(PAC_SCRIPT), MK_SRC(OWNER), pac_url,
- &init_config, &init_config.automatic_proxy);
- CreateConfigService(init_config);
-
- ProxyConfigServiceImpl::ProxyConfig config;
- config_service()->UIGetProxyConfig(&config);
-
- EXPECT_EQ(MK_SRC(OWNER), config.automatic_proxy.source);
- // Setting should be writeable by owner.
- EXPECT_TRUE(config.automatic_proxy.CanBeWrittenByUser(true));
- // Setting should not be writeable by non-owner.
- EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(false));
- }
-}
-
TEST_F(ProxyConfigServiceImplTest, ModifyFromUI) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
- tests[i].description.c_str()));
+ SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+ tests[i].description.c_str()));
// Init with direct.
ProxyConfigServiceImpl::ProxyConfig init_config;
@@ -512,11 +583,12 @@ TEST_F(ProxyConfigServiceImplTest, SerializeAndDeserialize) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
if (!tests[i].is_valid)
continue;
+
SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
tests[i].description.c_str()));
ProxyConfigServiceImpl::ProxyConfig source_config;
- InitConfigWithTestInput(tests[i].input, &source_config);
+ InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &source_config);
// Serialize source_config into std::string.
std::string serialized_value;
@@ -546,4 +618,43 @@ TEST_F(ProxyConfigServiceImplTest, SerializeAndDeserialize) {
}
}
+TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForPolicySource) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ if (!tests[i].test_read_write_access)
+ continue;
+ SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+ tests[i].description.c_str()));
+ TestReadWriteAccessForMode(tests[i].input, MK_SRC(POLICY));
+ }
+}
+
+TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForOwnerSource) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ if (!tests[i].test_read_write_access)
+ continue;
+ SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
+ tests[i].description.c_str()));
+ TestReadWriteAccessForMode(tests[i].input, MK_SRC(OWNER));
+ }
+}
+
+TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForMixedSchemes) {
+ const char* http_uri = "www.google.com:80";
+ const char* https_uri = "www.foo.com:110";
+ const char* ftp_uri = "ftp.foo.com:121";
+ const char* socks_uri = "socks.com:888";
+
+ // Init with policy source.
+ TestReadWriteAccessForScheme(MK_SRC(POLICY), http_uri, "http");
+ TestReadWriteAccessForScheme(MK_SRC(POLICY), https_uri, "https");
+ TestReadWriteAccessForScheme(MK_SRC(POLICY), ftp_uri, "ftp");
+ TestReadWriteAccessForScheme(MK_SRC(POLICY), socks_uri, "socks");
+
+ // Init with owner source.
+ TestReadWriteAccessForScheme(MK_SRC(OWNER), http_uri, "http");
+ TestReadWriteAccessForScheme(MK_SRC(OWNER), https_uri, "https");
+ TestReadWriteAccessForScheme(MK_SRC(OWNER), ftp_uri, "ftp");
+ TestReadWriteAccessForScheme(MK_SRC(OWNER), socks_uri, "socks");
+}
+
} // namespace chromeos