diff options
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&t13n_langs=en"></script> + <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&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(); + } +]); |