summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser_main.cc2
-rw-r--r--chrome/browser/browser_process_impl.cc2
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc4
-rw-r--r--chrome/browser/extensions/extension_pref_store.cc181
-rw-r--r--chrome/browser/extensions/extension_pref_store.h65
-rw-r--r--chrome/browser/extensions/extension_pref_store_unittest.cc182
-rw-r--r--chrome/browser/extensions/extension_proxy_api.cc128
-rw-r--r--chrome/browser/extensions/extension_proxy_api.h37
-rw-r--r--chrome/browser/extensions/extension_proxy_apitest.cc50
-rw-r--r--chrome/browser/pref_service.cc15
-rw-r--r--chrome/browser/pref_service.h11
-rw-r--r--chrome/browser/profile_impl.cc3
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/extensions/api/extension_api.json45
-rw-r--r--chrome/common/extensions/docs/experimental.html1
-rw-r--r--chrome/common/extensions/docs/experimental.proxy.html1142
-rw-r--r--chrome/common/extensions/extension.cc6
-rw-r--r--chrome/common/extensions/extension.h1
-rw-r--r--chrome/common/notification_type.h5
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js1
-rw-r--r--chrome/test/data/extensions/api_test/proxy/individual/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/proxy/individual/test.html1
-rw-r--r--chrome/test/data/extensions/api_test/proxy/individual/test.js38
-rw-r--r--chrome/test/data/extensions/api_test/proxy/single/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/proxy/single/test.html1
-rw-r--r--chrome/test/data/extensions/api_test/proxy/single/test.js36
27 files changed, 1819 insertions, 155 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 1c445461..c5117a4 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -521,7 +521,7 @@ PrefService* InitializeLocalState(const CommandLine& parsed_command_line,
FilePath parent_profile =
parsed_command_line.GetSwitchValuePath(switches::kParentProfile);
scoped_ptr<PrefService> parent_local_state(
- PrefService::CreatePrefService(parent_profile));
+ PrefService::CreatePrefService(parent_profile, NULL));
parent_local_state->RegisterStringPref(prefs::kApplicationLocale,
std::string());
// Right now, we only inherit the locale setting from the parent profile.
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 51cd234..6ca9d41 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -602,7 +602,7 @@ void BrowserProcessImpl::CreateLocalState() {
FilePath local_state_path;
PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
- local_state_.reset(PrefService::CreatePrefService(local_state_path));
+ local_state_.reset(PrefService::CreatePrefService(local_state_path, NULL));
}
void BrowserProcessImpl::CreateIconManager() {
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 70b3851..b27d65ee 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -39,6 +39,7 @@
#include "chrome/browser/extensions/extension_popup_api.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_processes_api.h"
+#include "chrome/browser/extensions/extension_proxy_api.h"
#include "chrome/browser/extensions/extension_rlz_module.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extension_tabs_module_constants.h"
@@ -243,6 +244,9 @@ void FactoryRegistry::ResetFunctions() {
// Omnibox.
RegisterFunction<OmniboxSendSuggestionsFunction>();
+
+ // Proxies.
+ RegisterFunction<UseCustomProxySettingsFunction>();
}
void FactoryRegistry::GetAllNames(std::vector<std::string>* names) {
diff --git a/chrome/browser/extensions/extension_pref_store.cc b/chrome/browser/extensions/extension_pref_store.cc
index 7635151..5d20cae 100644
--- a/chrome/browser/extensions/extension_pref_store.cc
+++ b/chrome/browser/extensions/extension_pref_store.cc
@@ -6,28 +6,98 @@
#include "base/logging.h"
#include "base/values.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/pref_service.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/notification_service.h"
-ExtensionPrefStore::ExtensionPrefStore(PrefService* pref_service)
- : pref_service_(pref_service),
- prefs_(new DictionaryValue()) {
+ExtensionPrefStore::ExtensionPrefStore(Profile* profile)
+ : prefs_(new DictionaryValue()),
+ profile_(profile) {
+ RegisterObservers();
}
ExtensionPrefStore::~ExtensionPrefStore() {
STLDeleteElements(&extension_stack_);
+ notification_registrar_.RemoveAll();
+}
+
+void ExtensionPrefStore::InstallExtensionPref(Extension* extension,
+ const wchar_t* new_pref_path,
+ Value* new_pref_value) {
+ ExtensionStack::iterator i;
+ for (i = extension_stack_.begin(); i != extension_stack_.end(); ++i) {
+ if ((*i)->extension == extension)
+ break;
+ }
+
+ // If this extension is not already in the stack, add it. Otherwise, update
+ // or add the value of this preference, but don't change the extension's
+ // position in the stack. We store the extension even if this preference
+ // isn't registered with our PrefService, so that the ordering of extensions
+ // is consistent among all local-state and user ExtensionPrefStores.
+ PrefService* pref_service = GetPrefService();
+ // The pref_service may be NULL in unit testing.
+ bool is_registered_pref = (pref_service == NULL ||
+ pref_service->FindPreference(new_pref_path) != NULL);
+ PrefValueMap* pref_values;
+ if (i == extension_stack_.end()) {
+ pref_values = new PrefValueMap();
+ if (is_registered_pref)
+ (*pref_values)[new_pref_path] = new_pref_value;
+
+ ExtensionPrefs* extension_prefs = new ExtensionPrefs(extension,
+ pref_values);
+ extension_stack_.push_front(extension_prefs);
+ } else if (is_registered_pref) {
+ pref_values = (*i)->pref_values;
+ delete (*pref_values)[new_pref_path];
+ (*pref_values)[new_pref_path] = new_pref_value;
+ }
+
+ // Apply the preference to our local |prefs_| store.
+ UpdateOnePref(new_pref_path);
+}
+
+void ExtensionPrefStore::UninstallExtension(Extension* extension) {
+ // Remove this extension from the stack.
+ for (ExtensionStack::iterator i = extension_stack_.begin();
+ i != extension_stack_.end(); ++i) {
+ if ((*i)->extension == extension) {
+ scoped_ptr<ExtensionPrefs> to_be_deleted(*i);
+ extension_stack_.erase(i);
+ UpdatePrefs(to_be_deleted->pref_values);
+ return;
+ }
+ }
+}
+
+void ExtensionPrefStore::GetExtensionIDs(std::vector<std::string>* result) {
+ for (ExtensionStack::iterator i = extension_stack_.begin();
+ i != extension_stack_.end(); ++i) {
+ (*result).push_back((*i)->extension->id());
+ }
}
// This could be sped up by keeping track of which extension currently controls
-// a given preference, among other optimizations. But we estimate that fewer
-// than 10 installed extensions will be trying to control any preferences, so
-// stick with this simpler algorithm until it causes a problem.
+// a given preference, among other optimizations. But probably fewer than 10
+// installed extensions will be trying to control any preferences, so stick
+// with this simpler algorithm until it causes a problem.
void ExtensionPrefStore::UpdateOnePref(const wchar_t* path) {
- // Query the PrefService to find the current value for this pref.
- // pref_service_ might be null in unit tests.
scoped_ptr<Value> old_value;
- if (pref_service_) {
- old_value.reset(
- pref_service_->FindPreference(path)->GetValue()->DeepCopy());
+ PrefService* pref_service = GetPrefService();
+
+ // There are at least two PrefServices, one for local state and one for
+ // user prefs. (See browser_main.cc.) Different preferences are registered
+ // in each; if this one doesn't have the desired pref registered, we ignore
+ // it and let the other one handle it.
+ // The pref_service may be NULL in unit testing.
+ if (pref_service) {
+ const PrefService::Preference* pref = pref_service->FindPreference(path);
+ if (!pref)
+ return;
+ old_value.reset(pref->GetValue()->DeepCopy());
}
// DictionaryValue::Set complains if a key is overwritten with the same
@@ -43,8 +113,9 @@ void ExtensionPrefStore::UpdateOnePref(const wchar_t* path) {
break;
}
}
- if (pref_service_)
- pref_service_->FireObserversIfChanged(path, old_value.get());
+
+ if (pref_service)
+ pref_service->FireObserversIfChanged(path, old_value.get());
}
void ExtensionPrefStore::UpdatePrefs(const PrefValueMap* pref_values) {
@@ -57,53 +128,55 @@ void ExtensionPrefStore::UpdatePrefs(const PrefValueMap* pref_values) {
}
}
-void ExtensionPrefStore::InstallExtensionPref(std::string extension_id,
- const wchar_t* pref_path,
- Value* pref_value) {
- ExtensionStack::iterator i;
- for (i = extension_stack_.begin(); i != extension_stack_.end(); ++i) {
- if ((*i)->extension_id == extension_id)
- break;
- }
-
- // If this extension is already in the stack, update or add the value of this
- // preference, but don't change the extension's position in the stack.
- // Otherwise, push the new extension onto the stack.
- PrefValueMap* pref_values;
- if (i != extension_stack_.end()) {
- pref_values = (*i)->pref_values;
- delete (*pref_values)[pref_path];
- (*pref_values)[pref_path] = pref_value;
- } else {
- pref_values = new PrefValueMap();
- (*pref_values)[pref_path] = pref_value;
+PrefService* ExtensionPrefStore::GetPrefService() {
+ if (profile_)
+ return profile_->GetPrefs();
+ return g_browser_process->local_state();
+}
- ExtensionPrefs* extension_prefs = new ExtensionPrefs(extension_id,
- pref_values);
- extension_stack_.push_front(extension_prefs);
- }
+void ExtensionPrefStore::RegisterObservers() {
+ notification_registrar_.Add(this,
+ NotificationType::EXTENSION_PREF_CHANGED,
+ NotificationService::AllSources());
- // Look for an old value with the same type as the one we're modifying.
- UpdateOnePref(pref_path);
+ notification_registrar_.Add(this,
+ NotificationType::EXTENSION_UNLOADED,
+ NotificationService::AllSources());
}
-void ExtensionPrefStore::UninstallExtension(std::string extension_id) {
- // Remove this extension from the stack.
- for (ExtensionStack::iterator i = extension_stack_.begin();
- i != extension_stack_.end(); ++i) {
- if ((*i)->extension_id == extension_id) {
- ExtensionPrefs* to_be_deleted = *i;
- extension_stack_.erase(i);
- UpdatePrefs(to_be_deleted->pref_values);
- delete to_be_deleted;
- return;
+void ExtensionPrefStore::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::EXTENSION_PREF_CHANGED: {
+ Profile* extension_profile = Source<Profile>(source).ptr();
+ // The ExtensionPrefStore for the local state watches all profiles.
+ if (!profile_ || profile_ == extension_profile) {
+ ExtensionPrefStore::ExtensionPrefDetails* data =
+ Details<ExtensionPrefStore::ExtensionPrefDetails>(details).ptr();
+ InstallExtensionPref(data->first, data->second.first,
+ data->second.second);
+ }
+ break;
+ }
+ case NotificationType::EXTENSION_UNLOADED: {
+ Profile* extension_profile = Source<Profile>(source).ptr();
+ Extension* extension = Details<Extension>(details).ptr();
+ // The ExtensionPrefStore for the local state watches all profiles.
+ if (profile_ == NULL || profile_ == extension_profile)
+ UninstallExtension(extension);
+ break;
+ }
+ default: {
+ NOTREACHED();
}
}
}
-void ExtensionPrefStore::GetExtensionIDs(std::vector<std::string>* result) {
- for (ExtensionStack::iterator i = extension_stack_.begin();
- i != extension_stack_.end(); ++i) {
- (*result).push_back((*i)->extension_id);
- }
+ExtensionPrefStore::ExtensionPrefs::ExtensionPrefs(Extension* extension,
+ PrefValueMap* values) : extension(extension), pref_values(values) {}
+
+ExtensionPrefStore::ExtensionPrefs::~ExtensionPrefs() {
+ STLDeleteValues(pref_values);
+ delete pref_values;
}
diff --git a/chrome/browser/extensions/extension_pref_store.h b/chrome/browser/extensions/extension_pref_store.h
index 6b597cf..98a2b00 100644
--- a/chrome/browser/extensions/extension_pref_store.h
+++ b/chrome/browser/extensions/extension_pref_store.h
@@ -9,57 +9,65 @@
#include <list>
#include <map>
#include <string>
+#include <utility>
#include <vector>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/stl_util-inl.h"
+#include "chrome/common/notification_registrar.h"
#include "chrome/common/pref_store.h"
class DictionaryValue;
+class Extension;
class PrefService;
+class Profile;
class Value;
// This PrefStore keeps track of preferences set by extensions: for example,
-// proxy settings. A stack of relevant extension IDs is stored in order of
+// proxy settings. A stack of relevant extensions is stored in order of
// their addition to this PrefStore. For each preference, the last-added
// enabled extension that tries to set it overrules any others.
-class ExtensionPrefStore : public PrefStore {
+class ExtensionPrefStore : public PrefStore,
+ public NotificationObserver {
public:
- explicit ExtensionPrefStore(PrefService* pref_service);
+ explicit ExtensionPrefStore(Profile* profile);
virtual ~ExtensionPrefStore();
- // The PrefService creates the ExtensionPrefStore, so we need to be able to
- // defer setting the PrefService here until after construction.
- void SetPrefService(PrefService* pref_service) {
- pref_service_ = pref_service;
- }
-
// Begins tracking the preference and value an extension wishes to set. This
// must be called each time an extension API tries to set a preference.
// The ExtensionPrefStore will take ownership of the |pref_value|.
- virtual void InstallExtensionPref(std::string extension_id,
+ virtual void InstallExtensionPref(Extension* extension,
const wchar_t* pref_path,
Value* pref_value);
// Removes an extension and all its preference settings from this PrefStore.
// This must be called when an extension is uninstalled or disabled.
- virtual void UninstallExtension(std::string extension_id);
+ virtual void UninstallExtension(Extension* extension);
// PrefStore methods:
virtual DictionaryValue* prefs() { return prefs_.get(); }
virtual PrefReadError ReadPrefs() { return PREF_READ_ERROR_NONE; }
+ // The type passed as Details for an EXTENSION_PREF_CHANGED notification.
+ // The nested pairs are <extension, <pref_path, pref_value> >. This is here,
+ // rather than in (say) notification_type.h, to keep the dependency on
+ // std::pair out of the many places that include notification_type.h.
+ typedef std::pair<Extension*, std::pair<const wchar_t*, Value*> >
+ ExtensionPrefDetails;
+
protected:
// Returns a vector of the extension IDs in the extension_stack_.
// This should only be accessed by subclasses for unit-testing.
void GetExtensionIDs(std::vector<std::string>* result);
- private:
- // The pref service referring to this pref store. Weak reference.
- PrefService* pref_service_;
+ // Returns the applicable pref service from the profile (if we have one) or
+ // the browser's local state. This should only be accessed or overridden by
+ // subclasses for unit-testing.
+ virtual PrefService* GetPrefService();
+ private:
// Maps preference paths to their values.
typedef std::map<const wchar_t*, Value*> PrefValueMap;
@@ -71,22 +79,24 @@ class ExtensionPrefStore : public PrefStore {
// Updates each preference in the key set of the |pref_values| map.
void UpdatePrefs(const PrefValueMap* pref_values);
+ // Registers this as an observer for relevant notifications.
+ void RegisterObservers();
+
+ // Responds to observed notifications.
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
// A cache of the highest-priority values for each preference that any
// extension is controlling, for quick read access. Owns the stored values.
scoped_ptr<DictionaryValue> prefs_;
- // Associates an extension ID with the prefs it sets. Owns the pref values.
+ // Associates an extension with the prefs it sets. Owns the pref values.
struct ExtensionPrefs {
- ExtensionPrefs(std::string id, PrefValueMap* values)
- : extension_id(id),
- pref_values(values) {}
-
- ~ExtensionPrefs() {
- STLDeleteValues(pref_values);
- delete pref_values;
- }
+ ExtensionPrefs(Extension* extension, PrefValueMap* values);
+ ~ExtensionPrefs();
- std::string extension_id;
+ Extension* extension;
PrefValueMap* pref_values;
};
@@ -95,6 +105,13 @@ class ExtensionPrefStore : public PrefStore {
typedef std::list<ExtensionPrefs*> ExtensionStack;
ExtensionStack extension_stack_;
+ NotificationRegistrar notification_registrar_;
+
+ // Weak reference to the profile whose extensions we're interested in. May be
+ // NULL (for the local-state preferences), in which case we watch all
+ // extensions.
+ Profile* profile_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionPrefStore);
};
diff --git a/chrome/browser/extensions/extension_pref_store_unittest.cc b/chrome/browser/extensions/extension_pref_store_unittest.cc
index aa16441..b538bc9 100644
--- a/chrome/browser/extensions/extension_pref_store_unittest.cc
+++ b/chrome/browser/extensions/extension_pref_store_unittest.cc
@@ -7,21 +7,72 @@
#include <string>
#include <vector>
+#include "base/scoped_ptr.h"
+#include "base/scoped_temp_dir.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_pref_store.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/pref_value_store.h"
+#include "chrome/common/extensions/extension.h"
namespace {
class TestExtensionPrefStore : public ExtensionPrefStore {
public:
- TestExtensionPrefStore() : ExtensionPrefStore(NULL) {}
+ TestExtensionPrefStore() : ExtensionPrefStore(NULL),
+ ext1(NULL),
+ ext2(NULL),
+ ext3(NULL),
+ pref_service_(NULL) {
+ // Can't use ASSERT_TRUE here because a constructor can't return a value.
+ if (!temp_dir_.CreateUniqueTempDir()) {
+ ADD_FAILURE() << "Failed to create temp dir";
+ return;
+ }
+ DictionaryValue empty_dict;
+ std::string error;
+
+ ext1_scoped_.reset(new Extension(temp_dir_.path().AppendASCII("ext1")));
+ ext2_scoped_.reset(new Extension(temp_dir_.path().AppendASCII("ext2")));
+ ext3_scoped_.reset(new Extension(temp_dir_.path().AppendASCII("ext3")));
+
+ ext1 = ext1_scoped_.get();
+ ext2 = ext2_scoped_.get();
+ ext3 = ext3_scoped_.get();
+
+ EXPECT_FALSE(ext1->InitFromValue(empty_dict, false, &error));
+ EXPECT_FALSE(ext2->InitFromValue(empty_dict, false, &error));
+ EXPECT_FALSE(ext3->InitFromValue(empty_dict, false, &error));
+ }
typedef std::vector<std::string> ExtensionIDs;
void GetExtensionIDList(ExtensionIDs* result) {
GetExtensionIDs(result);
}
+
+ void SetPrefService(PrefService* pref_service) {
+ pref_service_ = pref_service;
+ }
+
+ // Overridden from ExtensionPrefStore.
+ virtual PrefService* GetPrefService() {
+ return pref_service_;
+ }
+
+ // Weak references, for convenience.
+ Extension* ext1;
+ Extension* ext2;
+ Extension* ext3;
+
+ private:
+ ScopedTempDir temp_dir_;
+
+ scoped_ptr<Extension> ext1_scoped_;
+ scoped_ptr<Extension> ext2_scoped_;
+ scoped_ptr<Extension> ext3_scoped_;
+
+ // Weak reference.
+ PrefService* pref_service_;
};
class MockPrefService : public PrefService {
@@ -49,12 +100,13 @@ static const wchar_t* kPref4 = L"path4";
TEST(ExtensionPrefStoreTest, InstallOneExtension) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(1u, ids.size());
- EXPECT_EQ("id1", ids[0]);
+ EXPECT_EQ(eps.ext1->id(), ids[0]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(1u, prefs->size());
@@ -66,16 +118,17 @@ TEST(ExtensionPrefStoreTest, InstallOneExtension) {
// Make sure the last-installed extension wins.
TEST(ExtensionPrefStoreTest, InstallMultipleExtensions) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id2", kPref1, Value::CreateStringValue("val2"));
- eps.InstallExtensionPref("id3", kPref1, Value::CreateStringValue("val3"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext2, kPref1, Value::CreateStringValue("val2"));
+ eps.InstallExtensionPref(eps.ext3, kPref1, Value::CreateStringValue("val3"));
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(3u, ids.size());
- EXPECT_EQ("id3", ids[0]);
- EXPECT_EQ("id2", ids[1]);
- EXPECT_EQ("id1", ids[2]);
+ EXPECT_EQ(eps.ext3->id(), ids[0]);
+ EXPECT_EQ(eps.ext2->id(), ids[1]);
+ EXPECT_EQ(eps.ext1->id(), ids[2]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(1u, prefs->size());
@@ -87,23 +140,24 @@ TEST(ExtensionPrefStoreTest, InstallMultipleExtensions) {
// Make sure the last-installed extension wins for each preference.
TEST(ExtensionPrefStoreTest, InstallOverwrittenExtensions) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id2", kPref1, Value::CreateStringValue("val2"));
- eps.InstallExtensionPref("id3", kPref1, Value::CreateStringValue("val3"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext2, kPref1, Value::CreateStringValue("val2"));
+ eps.InstallExtensionPref(eps.ext3, kPref1, Value::CreateStringValue("val3"));
- eps.InstallExtensionPref("id1", kPref2, Value::CreateStringValue("val4"));
- eps.InstallExtensionPref("id2", kPref2, Value::CreateStringValue("val5"));
+ eps.InstallExtensionPref(eps.ext1, kPref2, Value::CreateStringValue("val4"));
+ eps.InstallExtensionPref(eps.ext2, kPref2, Value::CreateStringValue("val5"));
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val6"));
- eps.InstallExtensionPref("id1", kPref2, Value::CreateStringValue("val7"));
- eps.InstallExtensionPref("id1", kPref3, Value::CreateStringValue("val8"));
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val6"));
+ eps.InstallExtensionPref(eps.ext1, kPref2, Value::CreateStringValue("val7"));
+ eps.InstallExtensionPref(eps.ext1, kPref3, Value::CreateStringValue("val8"));
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(3u, ids.size());
- EXPECT_EQ("id3", ids[0]);
- EXPECT_EQ("id2", ids[1]);
- EXPECT_EQ("id1", ids[2]);
+ EXPECT_EQ(eps.ext3->id(), ids[0]);
+ EXPECT_EQ(eps.ext2->id(), ids[1]);
+ EXPECT_EQ(eps.ext1->id(), ids[2]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(3u, prefs->size());
@@ -120,22 +174,23 @@ TEST(ExtensionPrefStoreTest, InstallOverwrittenExtensions) {
// the same or different preferences later.
TEST(ExtensionPrefStoreTest, InstallInterleavedExtensions) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id2", kPref2, Value::CreateStringValue("val2"));
- eps.InstallExtensionPref("id3", kPref3, Value::CreateStringValue("val3"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext2, kPref2, Value::CreateStringValue("val2"));
+ eps.InstallExtensionPref(eps.ext3, kPref3, Value::CreateStringValue("val3"));
- eps.InstallExtensionPref("id3", kPref3, Value::CreateStringValue("val4"));
- eps.InstallExtensionPref("id2", kPref3, Value::CreateStringValue("val5"));
- eps.InstallExtensionPref("id1", kPref3, Value::CreateStringValue("val6"));
+ eps.InstallExtensionPref(eps.ext3, kPref3, Value::CreateStringValue("val4"));
+ eps.InstallExtensionPref(eps.ext2, kPref3, Value::CreateStringValue("val5"));
+ eps.InstallExtensionPref(eps.ext1, kPref3, Value::CreateStringValue("val6"));
- eps.InstallExtensionPref("id3", kPref1, Value::CreateStringValue("val7"));
+ eps.InstallExtensionPref(eps.ext3, kPref1, Value::CreateStringValue("val7"));
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(3u, ids.size());
- EXPECT_EQ("id3", ids[0]);
- EXPECT_EQ("id2", ids[1]);
- EXPECT_EQ("id1", ids[2]);
+ EXPECT_EQ(eps.ext3->id(), ids[0]);
+ EXPECT_EQ(eps.ext2->id(), ids[1]);
+ EXPECT_EQ(eps.ext1->id(), ids[2]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(3u, prefs->size());
@@ -150,11 +205,12 @@ TEST(ExtensionPrefStoreTest, InstallInterleavedExtensions) {
TEST(ExtensionPrefStoreTest, UninstallOnlyExtension) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id1", kPref2, Value::CreateStringValue("val2"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext1, kPref2, Value::CreateStringValue("val2"));
// No need to check the state here; the Install* tests cover that.
- eps.UninstallExtension("id1");
+ eps.UninstallExtension(eps.ext1);
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
@@ -172,18 +228,19 @@ TEST(ExtensionPrefStoreTest, UninstallOnlyExtension) {
// Tests uninstalling an extension that wasn't winning for any preferences.
TEST(ExtensionPrefStoreTest, UninstallIrrelevantExtension) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id2", kPref1, Value::CreateStringValue("val2"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext2, kPref1, Value::CreateStringValue("val2"));
- eps.InstallExtensionPref("id1", kPref2, Value::CreateStringValue("val3"));
- eps.InstallExtensionPref("id2", kPref2, Value::CreateStringValue("val4"));
+ eps.InstallExtensionPref(eps.ext1, kPref2, Value::CreateStringValue("val3"));
+ eps.InstallExtensionPref(eps.ext2, kPref2, Value::CreateStringValue("val4"));
- eps.UninstallExtension("id1");
+ eps.UninstallExtension(eps.ext1);
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(1u, ids.size());
- EXPECT_EQ("id2", ids[0]);
+ EXPECT_EQ(eps.ext2->id(), ids[0]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(2u, prefs->size());
@@ -197,20 +254,21 @@ TEST(ExtensionPrefStoreTest, UninstallIrrelevantExtension) {
// Tests uninstalling an extension that was winning for all preferences.
TEST(ExtensionPrefStoreTest, UninstallExtensionFromTop) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id2", kPref1, Value::CreateStringValue("val2"));
- eps.InstallExtensionPref("id3", kPref1, Value::CreateStringValue("val3"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext2, kPref1, Value::CreateStringValue("val2"));
+ eps.InstallExtensionPref(eps.ext3, kPref1, Value::CreateStringValue("val3"));
- eps.InstallExtensionPref("id1", kPref2, Value::CreateStringValue("val4"));
- eps.InstallExtensionPref("id3", kPref2, Value::CreateStringValue("val5"));
+ eps.InstallExtensionPref(eps.ext1, kPref2, Value::CreateStringValue("val4"));
+ eps.InstallExtensionPref(eps.ext3, kPref2, Value::CreateStringValue("val5"));
- eps.UninstallExtension("id3");
+ eps.UninstallExtension(eps.ext3);
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(2u, ids.size());
- EXPECT_EQ("id2", ids[0]);
- EXPECT_EQ("id1", ids[1]);
+ EXPECT_EQ(eps.ext2->id(), ids[0]);
+ EXPECT_EQ(eps.ext1->id(), ids[1]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(2u, prefs->size());
@@ -224,24 +282,25 @@ TEST(ExtensionPrefStoreTest, UninstallExtensionFromTop) {
// Tests uninstalling an extension that was winning for only some preferences.
TEST(ExtensionPrefStoreTest, UninstallExtensionFromMiddle) {
TestExtensionPrefStore eps;
- eps.InstallExtensionPref("id1", kPref1, Value::CreateStringValue("val1"));
- eps.InstallExtensionPref("id2", kPref1, Value::CreateStringValue("val2"));
- eps.InstallExtensionPref("id3", kPref1, Value::CreateStringValue("val3"));
+ ASSERT_TRUE(eps.ext1 != NULL);
+ eps.InstallExtensionPref(eps.ext1, kPref1, Value::CreateStringValue("val1"));
+ eps.InstallExtensionPref(eps.ext2, kPref1, Value::CreateStringValue("val2"));
+ eps.InstallExtensionPref(eps.ext3, kPref1, Value::CreateStringValue("val3"));
- eps.InstallExtensionPref("id1", kPref2, Value::CreateStringValue("val4"));
- eps.InstallExtensionPref("id2", kPref2, Value::CreateStringValue("val5"));
+ eps.InstallExtensionPref(eps.ext1, kPref2, Value::CreateStringValue("val4"));
+ eps.InstallExtensionPref(eps.ext2, kPref2, Value::CreateStringValue("val5"));
- eps.InstallExtensionPref("id1", kPref3, Value::CreateStringValue("val6"));
+ eps.InstallExtensionPref(eps.ext1, kPref3, Value::CreateStringValue("val6"));
- eps.InstallExtensionPref("id2", kPref4, Value::CreateStringValue("val7"));
+ eps.InstallExtensionPref(eps.ext2, kPref4, Value::CreateStringValue("val7"));
- eps.UninstallExtension("id2");
+ eps.UninstallExtension(eps.ext2);
TestExtensionPrefStore::ExtensionIDs ids;
eps.GetExtensionIDList(&ids);
EXPECT_EQ(2u, ids.size());
- EXPECT_EQ("id3", ids[0]);
- EXPECT_EQ("id1", ids[1]);
+ EXPECT_EQ(eps.ext3->id(), ids[0]);
+ EXPECT_EQ(eps.ext1->id(), ids[1]);
DictionaryValue* prefs = eps.prefs();
ASSERT_EQ(3u, prefs->size());
@@ -257,6 +316,7 @@ TEST(ExtensionPrefStoreTest, UninstallExtensionFromMiddle) {
TEST(ExtensionPrefStoreTest, NotifyWhenNeeded) {
TestExtensionPrefStore* eps = new TestExtensionPrefStore;
+ ASSERT_TRUE(eps->ext1 != NULL);
// The PrefValueStore takes ownership of the PrefStores; in this case, that's
// only an ExtensionPrefStore. Likewise, the PrefService takes ownership of
@@ -266,16 +326,16 @@ TEST(ExtensionPrefStoreTest, NotifyWhenNeeded) {
eps->SetPrefService(pref_service.get());
pref_service->RegisterStringPref(kPref1, std::string());
- eps->InstallExtensionPref("abc", kPref1,
+ eps->InstallExtensionPref(eps->ext1, kPref1,
Value::CreateStringValue("https://www.chromium.org"));
EXPECT_TRUE(pref_service->fired_observers_);
- eps->InstallExtensionPref("abc", kPref1,
+ eps->InstallExtensionPref(eps->ext1, kPref1,
Value::CreateStringValue("https://www.chromium.org"));
EXPECT_FALSE(pref_service->fired_observers_);
- eps->InstallExtensionPref("abc", kPref1,
+ eps->InstallExtensionPref(eps->ext1, kPref1,
Value::CreateStringValue("chrome://newtab"));
EXPECT_TRUE(pref_service->fired_observers_);
- eps->UninstallExtension("abc");
+ eps->UninstallExtension(eps->ext1);
EXPECT_TRUE(pref_service->fired_observers_);
}
diff --git a/chrome/browser/extensions/extension_proxy_api.cc b/chrome/browser/extensions/extension_proxy_api.cc
new file mode 100644
index 0000000..56d2064
--- /dev/null
+++ b/chrome/browser/extensions/extension_proxy_api.cc
@@ -0,0 +1,128 @@
+// 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/extensions/extension_proxy_api.h"
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_pref_store.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+
+namespace {
+
+// The scheme for which to use the proxy, not of the proxy URI itself.
+typedef enum {
+ SCHEME_ALL = 0,
+ SCHEME_HTTP,
+ SCHEME_HTTPS,
+ SCHEME_FTP,
+ SCHEME_SOCKS,
+ SCHEME_MAX = SCHEME_SOCKS // Keep this value up to date.
+};
+
+// The names of the JavaScript properties to extract from the args_.
+// These must be kept in sync with the SCHEME_* constants.
+static const std::wstring field_name[] = {L"singleProxy",
+ L"proxyForHttp",
+ L"proxyForHttps",
+ L"proxyForFtp",
+ L"socksProxy"};
+
+// The names of the schemes to be used to build the preference value string.
+// These must be kept in sync with the SCHEME_* constants.
+static const std::string scheme_name[] = {"*error*",
+ "http",
+ "https",
+ "ftp",
+ "socks"};
+} // namespace
+
+COMPILE_ASSERT(SCHEME_MAX == SCHEME_SOCKS, SCHEME_MAX_must_equal_SCHEME_SOCKS);
+COMPILE_ASSERT(arraysize(field_name) == SCHEME_MAX + 1,
+ field_name_array_is_wrong_size);
+COMPILE_ASSERT(arraysize(scheme_name) == SCHEME_MAX + 1,
+ scheme_name_array_is_wrong_size);
+
+bool UseCustomProxySettingsFunction::RunImpl() {
+ DictionaryValue* proxy_config;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &proxy_config));
+
+ DictionaryValue* proxy_rules;
+ EXTENSION_FUNCTION_VALIDATE(proxy_config->GetDictionary(L"rules",
+ &proxy_rules));
+
+ // Local data into which the parameters will be parsed. has_proxy describes
+ // whether a setting was found for the scheme; proxy_dict holds the
+ // DictionaryValues which in turn contain proxy server descriptions, and
+ // proxy_server holds ProxyServer structs containing those descriptions.
+ bool has_proxy[SCHEME_MAX + 1];
+ DictionaryValue* proxy_dict[SCHEME_MAX + 1];
+ ProxyServer proxy_server[SCHEME_MAX + 1];
+
+ // Looking for all possible proxy types is inefficient if we have a
+ // singleProxy that will supersede per-URL proxies, but it's worth it to keep
+ // the code simple and extensible.
+ for (size_t i = 0; i <= SCHEME_MAX; ++i) {
+ has_proxy[i] = proxy_rules->GetDictionary(field_name[i], &proxy_dict[i]);
+ if (has_proxy[i]) {
+ if (!GetProxyServer(proxy_dict[i], &proxy_server[i]))
+ return false;
+ }
+ }
+
+ // A single proxy supersedes individual HTTP, HTTPS, and FTP proxies.
+ if (has_proxy[SCHEME_ALL]) {
+ proxy_server[SCHEME_HTTP] = proxy_server[SCHEME_ALL];
+ proxy_server[SCHEME_HTTPS] = proxy_server[SCHEME_ALL];
+ proxy_server[SCHEME_FTP] = proxy_server[SCHEME_ALL];
+ has_proxy[SCHEME_HTTP] = true;
+ has_proxy[SCHEME_HTTPS] = true;
+ has_proxy[SCHEME_FTP] = true;
+ has_proxy[SCHEME_ALL] = false;
+ }
+
+ // TODO(pamg): Ensure that if a value is empty, that means "don't use a proxy
+ // for this scheme".
+
+ // Build the proxy preference string.
+ std::string proxy_pref;
+ for (size_t i = 0; i <= SCHEME_MAX; ++i) {
+ if (has_proxy[i]) {
+ // http=foopy:4010;ftp=socks://foopy2:80
+ if (!proxy_pref.empty())
+ proxy_pref.append(";");
+ proxy_pref.append(scheme_name[i]);
+ proxy_pref.append("=");
+ proxy_pref.append(proxy_server[i].scheme);
+ proxy_pref.append("://");
+ proxy_pref.append(proxy_server[i].host);
+ if (proxy_server[i].port != ProxyServer::INVALID_PORT) {
+ proxy_pref.append(":");
+ proxy_pref.append(StringPrintf("%d", proxy_server[i].port));
+ }
+ }
+ }
+
+ ExtensionPrefStore::ExtensionPrefDetails details =
+ std::make_pair(GetExtension(),
+ std::make_pair(prefs::kProxyServer,
+ Value::CreateStringValue(proxy_pref)));
+
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PREF_CHANGED,
+ Source<Profile>(profile_),
+ Details<ExtensionPrefStore::ExtensionPrefDetails>(&details));
+
+ return true;
+}
+
+bool UseCustomProxySettingsFunction::GetProxyServer(
+ const DictionaryValue* dict, ProxyServer* proxy_server) {
+ dict->GetString(L"scheme", &proxy_server->scheme);
+ EXTENSION_FUNCTION_VALIDATE(dict->GetString(L"host", &proxy_server->host));
+ dict->GetInteger(L"port", &proxy_server->port);
+ return true;
+}
diff --git a/chrome/browser/extensions/extension_proxy_api.h b/chrome/browser/extensions/extension_proxy_api.h
new file mode 100644
index 0000000..1bc7ae3
--- /dev/null
+++ b/chrome/browser/extensions/extension_proxy_api.h
@@ -0,0 +1,37 @@
+// 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_EXTENSIONS_EXTENSION_PROXY_API_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PROXY_API_H_
+
+#include <string>
+
+#include "chrome/browser/extensions/extension_function.h"
+
+class DictionaryValue;
+
+class UseCustomProxySettingsFunction : public SyncExtensionFunction {
+ public:
+ ~UseCustomProxySettingsFunction() {}
+ virtual bool RunImpl();
+
+ DECLARE_EXTENSION_FUNCTION_NAME("experimental.proxy.useCustomProxySettings")
+
+ private:
+ struct ProxyServer {
+ enum {
+ INVALID_PORT = -1
+ };
+ ProxyServer() : scheme("http"), host(""), port(INVALID_PORT) {}
+
+ // The scheme of the proxy URI itself.
+ std::string scheme;
+ std::string host;
+ int port;
+ };
+
+ bool GetProxyServer(const DictionaryValue* dict, ProxyServer* proxy_server);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_PROXY_API_H_
diff --git a/chrome/browser/extensions/extension_proxy_apitest.cc b/chrome/browser/extensions/extension_proxy_apitest.cc
new file mode 100644
index 0000000..cb88131c
--- /dev/null
+++ b/chrome/browser/extensions/extension_proxy_apitest.cc
@@ -0,0 +1,50 @@
+// 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/browser.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/pref_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+
+// Tests setting a single proxy to cover all schemes.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxySingle) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalExtensionApis);
+
+ ASSERT_TRUE(RunExtensionTest("proxy/single")) << message_;
+ Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension);
+
+ PrefService* pref_service = browser()->profile()->GetPrefs();
+
+ // There should be no values superseding the extension-set proxy in this test.
+ std::string proxy_server = pref_service->GetString(prefs::kProxyServer);
+
+ ASSERT_EQ("http=http://127.0.0.1:100;"
+ "https=http://127.0.0.1:100;"
+ "ftp=http://127.0.0.1:100;"
+ "socks=http://9.9.9.9", proxy_server);
+}
+
+// Tests setting separate proxies for each scheme.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ProxyIndividual) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalExtensionApis);
+
+ ASSERT_TRUE(RunExtensionTest("proxy/individual")) << message_;
+ Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension);
+
+ PrefService* pref_service = browser()->profile()->GetPrefs();
+
+ // There should be no values superseding the extension-set proxy in this test.
+ std::string proxy_server = pref_service->GetString(prefs::kProxyServer);
+
+ ASSERT_EQ("http=http://1.1.1.1;"
+ "https=socks://2.2.2.2;"
+ "ftp=http://3.3.3.3:9000;"
+ "socks=socks4://4.4.4.4:9090", proxy_server);
+}
diff --git a/chrome/browser/pref_service.cc b/chrome/browser/pref_service.cc
index e8dd534..1b7c909 100644
--- a/chrome/browser/pref_service.cc
+++ b/chrome/browser/pref_service.cc
@@ -19,6 +19,7 @@
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/command_line_pref_store.h"
#include "chrome/browser/configuration_policy_pref_store.h"
#include "chrome/browser/extensions/extension_pref_store.h"
@@ -80,11 +81,9 @@ void NotifyReadError(PrefService* pref, int message_id) {
} // namespace
// static
-PrefService* PrefService::CreatePrefService(const FilePath& pref_filename) {
- // TODO(pamg): Reinstate extension pref store after Mstone6 branch, when its
- // memory leaks are fixed and any extension API is using it.
- // ExtensionPrefStore* extension_prefs = new ExtensionPrefStore(NULL);
- ExtensionPrefStore* extension_prefs = NULL;
+PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
+ Profile* profile) {
+ ExtensionPrefStore* extension_prefs = new ExtensionPrefStore(profile);
CommandLinePrefStore* command_line_prefs = new CommandLinePrefStore(
CommandLine::ForCurrentProcess());
PrefStore* local_prefs = new JsonPrefStore(
@@ -99,11 +98,7 @@ PrefService* PrefService::CreatePrefService(const FilePath& pref_filename) {
local_prefs,
ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore());
- PrefService* pref_service = new PrefService(value_store);
- // TODO(pamg): Uncomment when ExtensionPrefStore is reinstated.
- // extension_prefs->SetPrefService(pref_service);
-
- return pref_service;
+ return new PrefService(value_store);
}
// static
diff --git a/chrome/browser/pref_service.h b/chrome/browser/pref_service.h
index 62d01f8..1204297 100644
--- a/chrome/browser/pref_service.h
+++ b/chrome/browser/pref_service.h
@@ -21,6 +21,7 @@
class NotificationObserver;
class Preference;
+class Profile;
class ScopedPrefUpdate;
class PrefService : public NonThreadSafe {
@@ -94,8 +95,11 @@ class PrefService : public NonThreadSafe {
// Factory method that creates a new instance of a |PrefService| with
// all platform-applicable PrefStores (managed, extension, user, etc.).
- // This is the usual way to create a new PrefService.
- static PrefService* CreatePrefService(const FilePath& pref_filename);
+ // The |pref_filename| points to the user preference file. The |profile| is
+ // the one to which these preferences apply; it may be NULL if we're dealing
+ // with the local state. This is the usual way to create a new PrefService.
+ static PrefService* CreatePrefService(const FilePath& pref_filename,
+ Profile* profile);
// Convenience factory method for use in unit tests. Creates a new
// PrefService that uses a PrefValueStore with user preferences at the given
@@ -174,7 +178,8 @@ class PrefService : public NonThreadSafe {
// Removes a user pref and restores the pref to its default value.
void ClearPref(const wchar_t* path);
- // If the path is valid (i.e., registered), update the pref value.
+ // If the path is valid (i.e., registered), update the pref value in the user
+ // prefs.
void Set(const wchar_t* path, const Value& value);
void SetBoolean(const wchar_t* path, bool value);
void SetInteger(const wchar_t* path, int value);
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index 156a2c5..8d84001 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -598,7 +598,8 @@ net::TransportSecurityState*
PrefService* ProfileImpl::GetPrefs() {
if (!prefs_.get()) {
- prefs_.reset(PrefService::CreatePrefService(GetPrefFilePath()));
+ prefs_.reset(PrefService::CreatePrefService(GetPrefFilePath(),
+ GetOriginalProfile()));
// The Profile class and ProfileManager class may read some prefs so
// register known prefs as soon as possible.
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 48ae26f..468dc3d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1343,6 +1343,8 @@
'browser/extensions/extension_processes_api_constants.h',
'browser/extensions/extension_protocols.cc',
'browser/extensions/extension_protocols.h',
+ 'browser/extensions/extension_proxy_api.cc',
+ 'browser/extensions/extension_proxy_api.h',
'browser/extensions/extension_rlz_module.cc',
'browser/extensions/extension_rlz_module.h',
'browser/extensions/extension_shelf_model.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index da131ca..afe2ed2 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1578,6 +1578,7 @@
'browser/extensions/extension_omnibox_apitest.cc',
'browser/extensions/extension_override_apitest.cc',
'browser/extensions/extension_popup_apitest.cc',
+ 'browser/extensions/extension_proxy_apitest.cc',
'browser/extensions/extension_processes_apitest.cc',
'browser/extensions/extension_rlz_apitest.cc',
'browser/extensions/extension_shelf_model_browsertest.cc',
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 663d314..a143e8c 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -3285,6 +3285,51 @@
]
},
{
+ "namespace": "experimental.proxy",
+ "types": [
+ {
+ "id": "ProxyServer",
+ "type": "object",
+ "description": "An object encapsulating a single proxy server's specification.",
+ "properties": {
+ "scheme": {"type": "string", "optional": true, "enum": ["http", "socks", "socks4", "socks5"], "description": "The scheme (protocol) of the proxy server itself."},
+ "host": {"type": "string", "description": "The URI of the proxy server."},
+ "port": {"type": "integer", "optional": true, "description": "The port of the proxy server."}
+ }
+ },
+ {
+ "id": "ProxyRules",
+ "type": "object",
+ "description": "An object encapsulating the set of proxy rules for all protocols.",
+ "properties": {
+ "singleProxy": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for all per-URL requests (i.e., http, https, and ftp)."},
+ "proxyForHttp": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for HTTP requests."},
+ "proxyForHttps": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for HTTPS requests."},
+ "proxyForFtp": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for FTP requests."},
+ "socksProxy": {"$ref": "ProxyServer", "optional": true, "description": "The proxy server to be used for SOCKS requests."}
+ }
+ },
+ {
+ "id": "ProxyConfig",
+ "type": "object",
+ "description": "An object encapsulating a complete proxy configuration.",
+ "properties": {
+ "rules": {"$ref": "ProxyRules", "description": "The proxy rules describing this configuration."}
+ }
+ }
+ ],
+ "functions": [
+ {
+ "name": "useCustomProxySettings",
+ "type": "function",
+ "description": "Apply the given proxy configuration.",
+ "parameters": [
+ {"name": "config", "$ref": "ProxyConfig"}
+ ]
+ }
+ ]
+ },
+ {
"namespace": "experimental.clipboard",
"types": [],
"functions": [
diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html
index 5cca644..be21cc1 100644
--- a/chrome/common/extensions/docs/experimental.html
+++ b/chrome/common/extensions/docs/experimental.html
@@ -285,6 +285,7 @@ on the following experimental APIs:
<a href="experimental.infobars.html">experimental.infobars</a></li><li>
<a href="experimental.omnibox.html">experimental.omnibox</a></li><li>
<a href="experimental.processes.html">experimental.processes</a></li><li>
+ <a href="experimental.proxy.html">experimental.proxy</a></li><li>
<a href="experimental.webNavigation.html">experimental.webNavigation</a></li><li>
<a href="experimental.webRequest.html">experimental.webRequest</a></li>
</ul>
diff --git a/chrome/common/extensions/docs/experimental.proxy.html b/chrome/common/extensions/docs/experimental.proxy.html
new file mode 100644
index 0000000..13371c1
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.proxy.html
@@ -0,0 +1,1142 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+ 1) The <head> information in this page is significant, should be uniform
+ across api docs and should be edited only with knowledge of the
+ templating mechanism.
+ 3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+ browser, it will be re-generated from the template, json schema and
+ authored overview content.
+ 4) The <body>.innerHTML is also generated by an offline step so that this
+ page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+ <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+ <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+ </script>
+ <script type="text/javascript" src="js/api_page_generator.js"></script>
+ <script type="text/javascript" src="js/bootstrap.js"></script>
+ <title>chrome.experimental.proxy - Google Chrome Extensions - Google Code</title></head>
+ <body> <div id="gc-container" class="labs">
+ <div id="devModeWarning">
+ You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+ </div>
+ <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+ <!-- In particular, sub-templates that recurse, must be used by allowing
+ jstemplate to make a copy of the template in this section which
+ are not operated on by way of the jsskip="true" -->
+ <div style="display:none">
+
+ <!-- VALUE -->
+ <div id="valueTemplate">
+ <dt>
+ <var>paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd>
+ Description of this parameter from the json schema.
+ </dd>
+ <dd>
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div> <!-- /VALUE -->
+
+ </div> <!-- /SUBTEMPLATES -->
+
+ <a id="top"></a>
+ <div id="skipto">
+ <a href="#gc-pagecontent">Skip to page content</a>
+ <a href="#gc-toc">Skip to main navigation</a>
+ </div>
+ <!-- API HEADER -->
+ <table id="header" width="100%" cellspacing="0" border="0">
+ <tbody><tr>
+ <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+ <td valign="middle" width="100%" style="padding-left:0.6em;">
+ <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+ <div id="gsc-search-box">
+ <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+ <input type="hidden" name="ie" value="UTF-8">
+ <input type="text" name="q" value="" size="55">
+ <input class="gsc-search-button" type="submit" name="sa" value="Search">
+ <br>
+ <span class="greytext">e.g. "page action" or "tabs"</span>
+ </div>
+ </form>
+
+ <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+ <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+ </td>
+ </tr>
+ </tbody></table>
+
+ <div id="codesiteContent" class="">
+
+ <a id="gc-topnav-anchor"></a>
+ <div id="gc-topnav">
+ <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+ <ul id="home" class="gc-topnav-tabs">
+ <li id="home_link">
+ <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+ </li>
+ <li id="docs_link">
+ <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+ </li>
+ <li id="faq_link">
+ <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+ </li>
+ <li id="samples_link">
+ <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+ </li>
+ <li id="group_link">
+ <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+ </li>
+ </ul>
+ </div> <!-- end gc-topnav -->
+
+ <div class="g-section g-tpl-170">
+ <!-- SIDENAV -->
+ <div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li><a href="getstarted.html">Getting Started</a></li>
+ <li><a href="overview.html">Overview</a></li>
+ <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+ <ul>
+ <li>Browser UI
+ <ul>
+ <li><a href="browserAction.html">Browser Actions</a></li>
+ <li><a href="contextMenus.html">Context Menus</a></li>
+ <li><a href="notifications.html">Desktop Notifications</a></li>
+ <li><a href="options.html">Options Pages</a></li>
+ <li><a href="override.html">Override Pages</a></li>
+ <li><a href="pageAction.html">Page Actions</a></li>
+ <li><a href="themes.html">Themes</a></li>
+ </ul>
+ </li>
+ <li>Browser Interaction
+ <ul>
+ <li><a href="bookmarks.html">Bookmarks</a></li>
+ <li><a href="cookies.html">Cookies</a></li>
+ <li><a href="events.html">Events</a></li>
+ <li><a href="history.html">History</a></li>
+ <li><a href="tabs.html">Tabs</a></li>
+ <li><a href="windows.html">Windows</a></li>
+ </ul>
+ </li>
+ <li>Implementation
+ <ul>
+ <li><a href="a11y.html">Accessibility</a></li>
+ <li><a href="background_pages.html">Background Pages</a></li>
+ <li><a href="content_scripts.html">Content Scripts</a></li>
+ <li><a href="xhr.html">Cross-Origin XHR</a></li>
+ <li><a href="idle.html">Idle</a></li>
+ <li><a href="i18n.html">Internationalization</a></li>
+ <li><a href="messaging.html">Message Passing</a></li>
+ <li><a href="npapi.html">NPAPI Plugins</a></li>
+ </ul>
+ </li>
+ <li>Finishing
+ <ul>
+ <li><a href="hosting.html">Hosting</a></li>
+ <li><a href="external_extensions.html">Other Deployment Options</a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li><h2><a href="tutorials.html">Tutorials</a></h2>
+ <ul>
+ <li><a href="tut_debugging.html">Debugging</a></li>
+ <li><a href="tut_analytics.html">Google Analytics</a></li>
+ <li><a href="tut_oauth.html">OAuth</a></li>
+ </ul>
+ </li>
+ <li><h2>Reference</h2>
+ <ul>
+ <li>Formats
+ <ul>
+ <li><a href="manifest.html">Manifest Files</a></li>
+ <li><a href="match_patterns.html">Match Patterns</a></li>
+ <!-- <li>Packages (.crx)</li> -->
+ </ul>
+ </li>
+ <li><a href="api_index.html">chrome.* APIs</a></li>
+ <li><a href="api_other.html">Other APIs</a></li>
+ </ul>
+ </li>
+ <li><h2><a href="samples.html">Samples</a></h2></li>
+ </ul>
+ </div>
+
+ <div class="g-unit" id="gc-pagecontent">
+ <div id="pageTitle">
+ <h1 class="page_title">chrome.experimental.proxy</h1>
+ </div>
+ <!-- TABLE OF CONTENTS -->
+ <div id="toc">
+ <h2>Contents</h2>
+ <ol>
+ <li style="display: none; ">
+ <a>h2Name</a>
+ <ol>
+ <li>
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#apiReference">API reference: chrome.experimental.proxy</a>
+ <ol>
+ <li style="display: none; ">
+ <a href="#properties">Properties</a>
+ <ol>
+ <li>
+ <a href="#property-anchor">propertyName</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#methods">Methods</a>
+ <ol>
+ <li>
+ <a href="#method-useCustomProxySettings">useCustomProxySettings</a>
+ </li>
+ </ol>
+ </li>
+ <li style="display: none; ">
+ <a href="#events">Events</a>
+ <ol>
+ <li>
+ <a href="#event-anchor">eventName</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#types">Types</a>
+ <ol>
+ <li>
+ <a href="#type-ProxyServer">ProxyServer</a>
+ </li><li>
+ <a href="#type-ProxyRules">ProxyRules</a>
+ </li><li>
+ <a href="#type-ProxyConfig">ProxyConfig</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </div>
+ <!-- /TABLE OF CONTENTS -->
+
+ <!-- Standard content lead-in for experimental API pages -->
+ <p id="classSummary">
+ For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+ </p>
+
+ <!-- STATIC CONTENT PLACEHOLDER -->
+ <div id="static"></div>
+
+ <!-- API PAGE -->
+ <div class="apiPage">
+ <a name="apiReference"></a>
+ <h2>API reference: chrome.experimental.proxy</h2>
+
+ <!-- PROPERTIES -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="properties"></a>
+ <h3 id="properties">Properties</h3>
+
+ <div>
+ <a></a>
+ <h4>getLastError</h4>
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.extension</span><span>lastError</span>
+ </div>
+ <div>
+ </div>
+ </div>
+
+ </div> <!-- /apiGroup -->
+
+ <!-- METHODS -->
+ <div class="apiGroup" id="methods">
+ <a name="methods"></a>
+ <h3>Methods</h3>
+
+ <!-- iterates over all functions -->
+ <div class="apiItem">
+ <a name="method-useCustomProxySettings"></a> <!-- method-anchor -->
+ <h4>useCustomProxySettings</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.proxy.useCustomProxySettings</span>(<span class="null"><span style="display: none; ">, </span><span>ProxyConfig</span>
+ <var><span>config</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Apply the given proxy configuration.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>config</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyConfig">ProxyConfig</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- EVENTS -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="events"></a>
+ <h3 id="events">Events</h3>
+
+ <!-- iterates over all events -->
+ <div class="apiItem">
+ <a></a>
+ <h4>event name</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);
+ </div>
+
+ <div class="description">
+ <p class="todo">Undocumented.</p>
+ <p>
+ A description from the json schema def of the event goes here.
+ </p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /decription -->
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- TYPES -->
+ <div class="apiGroup">
+ <a name="types"></a>
+ <h3 id="types">Types</h3>
+
+ <!-- iterates over all types -->
+ <div class="apiItem">
+ <a name="type-ProxyServer"></a>
+ <h4>ProxyServer</h4>
+
+ <div>
+ <dt>
+ <var style="display: none; ">paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>An object encapsulating a single proxy server's specification.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>scheme</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span>["http", "socks", "socks4", "socks5"]</span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The scheme (protocol) of the proxy server itself.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>host</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The URI of the proxy server.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>port</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The port of the proxy server.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+
+ </div><div class="apiItem">
+ <a name="type-ProxyRules"></a>
+ <h4>ProxyRules</h4>
+
+ <div>
+ <dt>
+ <var style="display: none; ">paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>An object encapsulating the set of proxy rules for all protocols.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>singleProxy</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyServer">ProxyServer</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The proxy server to be used for all per-URL requests (i.e., http, https, and ftp).</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>proxyForHttp</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyServer">ProxyServer</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The proxy server to be used for HTTP requests.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>proxyForHttps</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyServer">ProxyServer</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The proxy server to be used for HTTPS requests.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>proxyForFtp</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyServer">ProxyServer</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The proxy server to be used for FTP requests.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>socksProxy</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyServer">ProxyServer</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The proxy server to be used for SOCKS requests.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+
+ </div><div class="apiItem">
+ <a name="type-ProxyConfig"></a>
+ <h4>ProxyConfig</h4>
+
+ <div>
+ <dt>
+ <var style="display: none; ">paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>An object encapsulating a complete proxy configuration.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>rules</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="experimental.proxy.html#type-ProxyRules">ProxyRules</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The proxy rules describing this configuration.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ </div> <!-- /apiPage -->
+ </div> <!-- /gc-pagecontent -->
+ </div> <!-- /g-section -->
+ </div> <!-- /codesiteContent -->
+ <div id="gc-footer" --="">
+ <div class="text">
+ <p>
+ Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+ the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+ Attribution 3.0 License</a>, and code samples are licensed under the
+ <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+ </p>
+ <p>
+ ©2010 Google
+ </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+ // chrome doc tracking
+ try {
+ var engdocs = _gat._getTracker("YT-10763712-2");
+ engdocs._trackPageview();
+ } catch(err) {}
+
+ // code.google.com site-wide tracking
+ try {
+ _uacct="UA-18071-1";
+ _uanchor=1;
+ _uff=0;
+ urchinTracker();
+ }
+ catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+ </div>
+ </div> <!-- /gc-footer -->
+ </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 1860d6d..f18f6f2 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -126,6 +126,7 @@ const char* Extension::kGeolocationPermission = "geolocation";
const char* Extension::kHistoryPermission = "history";
const char* Extension::kIdlePermission = "idle";
const char* Extension::kNotificationPermission = "notifications";
+const char* Extension::kProxyPermission = "proxy";
const char* Extension::kTabPermission = "tabs";
const char* Extension::kUnlimitedStoragePermission = "unlimited_storage";
const char* Extension::kNativeClientPermission = "native_client";
@@ -140,6 +141,7 @@ const char* Extension::kPermissionNames[] = {
Extension::kIdlePermission,
Extension::kHistoryPermission,
Extension::kNotificationPermission,
+ Extension::kProxyPermission,
Extension::kTabPermission,
Extension::kUnlimitedStoragePermission,
Extension::kNativeClientPermission,
@@ -1708,6 +1710,10 @@ const std::set<std::string> Extension::GetEffectiveHostPermissions() const {
}
bool Extension::HasAccessToAllHosts() const {
+ // Proxies effectively grant access to every site.
+ if (HasApiPermission(kProxyPermission))
+ return true;
+
for (URLPatternList::const_iterator host = host_permissions_.begin();
host != host_permissions_.end(); ++host) {
if (host->match_subdomains() && host->host().empty())
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 8f15faf..8a55d65 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -104,6 +104,7 @@ class Extension {
static const char* kHistoryPermission;
static const char* kIdlePermission;
static const char* kNotificationPermission;
+ static const char* kProxyPermission;
static const char* kTabPermission;
static const char* kUnlimitedStoragePermission;
static const char* kNativeClientPermission;
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 85aba99..cbb737a 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -892,6 +892,11 @@ class NotificationType {
// session. The source is the profile.
EXTENSION_OMNIBOX_INPUT_ENTERED,
+ // Sent when an extension changes a preference value. The source is the
+ // profile, and the details are an ExtensionPrefStore::ExtensionPrefDetails
+ // object.
+ EXTENSION_PREF_CHANGED,
+
// Debugging ---------------------------------------------------------------
// TODO(mpcomplete): Sent to diagnose a bug. Remove when fixed.
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index afb8a0e3..8a67983 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -259,6 +259,7 @@ var chrome = chrome || {};
"experimental.omnibox",
"experimental.popup",
"experimental.processes",
+ "experimental.proxy",
"experimental.rlz",
"experimental.webNavigation",
"experimental.webRequest",
diff --git a/chrome/test/data/extensions/api_test/proxy/individual/manifest.json b/chrome/test/data/extensions/api_test/proxy/individual/manifest.json
new file mode 100644
index 0000000..ada15d1
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/proxy/individual/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "chrome.proxy",
+ "version": "0.1",
+ "description": "end-to-end browser test for chrome.proxy API",
+ "background_page": "test.html",
+ "permissions": ["experimental", "proxy"]
+}
diff --git a/chrome/test/data/extensions/api_test/proxy/individual/test.html b/chrome/test/data/extensions/api_test/proxy/individual/test.html
new file mode 100644
index 0000000..46f4d74
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/proxy/individual/test.html
@@ -0,0 +1 @@
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/proxy/individual/test.js b/chrome/test/data/extensions/api_test/proxy/individual/test.js
new file mode 100644
index 0000000..d4d02f6
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/proxy/individual/test.js
@@ -0,0 +1,38 @@
+// 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.
+
+// proxy api test
+// browser_tests.exe --gtest_filter=ExtensionApiTest.ProxyIndividual
+
+chrome.test.runTests([
+ function setIndividualProxies() {
+ var httpProxy = {
+ host: "1.1.1.1"
+ };
+ var httpsProxy = {
+ scheme: "socks",
+ host: "2.2.2.2"
+ };
+ var ftpProxy = {
+ host: "3.3.3.3",
+ port: 9000
+ };
+ var socksProxy = {
+ scheme: "socks4",
+ host: "4.4.4.4",
+ port: 9090
+ };
+
+ var rules = {
+ proxyForHttp: httpProxy,
+ proxyForHttps: httpsProxy,
+ proxyForFtp: ftpProxy,
+ socksProxy: socksProxy,
+ };
+
+ var config = { rules: rules };
+ chrome.experimental.proxy.useCustomProxySettings(config);
+ chrome.test.succeed();
+ }
+]);
diff --git a/chrome/test/data/extensions/api_test/proxy/single/manifest.json b/chrome/test/data/extensions/api_test/proxy/single/manifest.json
new file mode 100644
index 0000000..ada15d1
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/proxy/single/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "chrome.proxy",
+ "version": "0.1",
+ "description": "end-to-end browser test for chrome.proxy API",
+ "background_page": "test.html",
+ "permissions": ["experimental", "proxy"]
+}
diff --git a/chrome/test/data/extensions/api_test/proxy/single/test.html b/chrome/test/data/extensions/api_test/proxy/single/test.html
new file mode 100644
index 0000000..46f4d74
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/proxy/single/test.html
@@ -0,0 +1 @@
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/proxy/single/test.js b/chrome/test/data/extensions/api_test/proxy/single/test.js
new file mode 100644
index 0000000..74ec444
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/proxy/single/test.js
@@ -0,0 +1,36 @@
+// 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.
+
+// proxy api test
+// browser_tests.exe --gtest_filter=ExtensionApiTest.ProxySingle
+
+chrome.test.runTests([
+ function setSingleProxy() {
+ var oneProxy = {
+ scheme: "http",
+ host: "127.0.0.1",
+ port: 100
+ };
+
+ // Single proxy should override HTTP proxy.
+ var httpProxy = {
+ host: "8.8.8.8"
+ };
+
+ // Single proxy should not override SOCKS proxy.
+ var socksProxy = {
+ host: "9.9.9.9"
+ };
+
+ var rules = {
+ singleProxy: oneProxy,
+ proxyForHttp: httpProxy,
+ socksProxy: socksProxy,
+ };
+
+ var config = { rules: rules };
+ chrome.experimental.proxy.useCustomProxySettings(config);
+ chrome.test.succeed();
+ }
+]);