aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/constellation.rs4
-rw-r--r--components/compositing/pipeline.rs2
-rw-r--r--components/script/dom/htmliframeelement.rs2
-rw-r--r--components/script/dom/mouseevent.rs2
-rw-r--r--components/style/properties.mako.rs12
-rw-r--r--components/style/stylesheets.rs2
-rw-r--r--components/util/opts.rs4
-rw-r--r--components/util/prefs.rs160
-rw-r--r--components/webdriver_server/lib.rs13
-rw-r--r--tests/unit/style/viewport.rs6
10 files changed, 174 insertions, 33 deletions
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs
index a9797225454..81a35241b80 100644
--- a/components/compositing/constellation.rs
+++ b/components/compositing/constellation.rs
@@ -905,7 +905,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
containing_pipeline_id: PipelineId,
subpage_id: SubpageId,
event: MozBrowserEvent) {
- assert!(prefs::get_pref("dom.mozbrowser.enabled").unwrap_or(false));
+ assert!(prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false));
// Find the script channel for the given parent pipeline,
// and pass the event to that script task.
@@ -1387,7 +1387,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
- if prefs::get_pref("dom.mozbrowser.enabled").unwrap_or(false) {
+ if prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false) {
// Work around borrow checker
let event_info = {
let pipeline = self.pipeline(pipeline_id);
diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs
index 8e07e220da8..73cabc1d35e 100644
--- a/components/compositing/pipeline.rs
+++ b/components/compositing/pipeline.rs
@@ -289,7 +289,7 @@ impl Pipeline {
pub fn trigger_mozbrowser_event(&self,
subpage_id: SubpageId,
event: MozBrowserEvent) {
- assert!(prefs::get_pref("dom.mozbrowser.enabled").unwrap_or(false));
+ assert!(prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false));
let event = ConstellationControlMsg::MozBrowserEvent(self.id,
subpage_id,
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index a5d2941e2ce..8e0016f4bb0 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -40,7 +40,7 @@ use util::str::DOMString;
use util::str::{self, LengthOrPercentageOrAuto};
pub fn mozbrowser_enabled() -> bool {
- prefs::get_pref("dom.mozbrowser.enabled").unwrap_or(false)
+ prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false)
}
#[derive(HeapSizeOf)]
diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs
index 5e75d11ea9d..3e6f5c20e30 100644
--- a/components/script/dom/mouseevent.rs
+++ b/components/script/dom/mouseevent.rs
@@ -171,7 +171,7 @@ impl MouseEventMethods for MouseEvent {
// This returns the same result as current gecko.
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
fn Which(&self) -> i32 {
- if prefs::get_pref("dom.mouseevent.which.enabled").unwrap_or(false) {
+ if prefs::get_pref("dom.mouseevent.which.enabled").as_boolean().unwrap_or(false) {
(self.button.get() + 1) as i32
} else {
0
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs
index 374b9b875d0..c1bca4d56dc 100644
--- a/components/style/properties.mako.rs
+++ b/components/style/properties.mako.rs
@@ -477,7 +477,8 @@ pub mod longhands {
% for value in values[:-1]:
"${value}" => {
% if value in experimental_values:
- if !::util::prefs::get_pref("layout.${value}.enabled").unwrap_or(false) {
+ if !::util::prefs::get_pref("layout.${value}.enabled")
+ .as_boolean().unwrap_or(false) {
return Err(())
}
% endif
@@ -487,7 +488,8 @@ pub mod longhands {
% for value in values[-1:]:
"${value}" => {
% if value in experimental_values:
- if !::util::prefs::get_pref("layout.${value}.enabled".unwrap_or(false) {
+ if !::util::prefs::get_pref("layout.${value}.enabled")
+ .as_boolean().unwrap_or(false) {
return Err(())
}
% endif
@@ -5945,7 +5947,8 @@ impl PropertyDeclaration {
% if property.derived_from is None:
"${property.name}" => {
% if property.experimental:
- if !::util::prefs::get_pref("${property.experimental}").unwrap_or(false) {
+ if !::util::prefs::get_pref("${property.experimental}")
+ .as_boolean().unwrap_or(false) {
return PropertyDeclarationParseResult::ExperimentalProperty
}
% endif
@@ -5964,7 +5967,8 @@ impl PropertyDeclaration {
% for shorthand in SHORTHANDS:
"${shorthand.name}" => {
% if shorthand.experimental:
- if !::util::prefs::get_pref("${shorthand.experimental}").unwrap_or(false) {
+ if !::util::prefs::get_pref("${shorthand.experimental}")
+ .as_boolean().unwrap_or(false) {
return PropertyDeclarationParseResult::ExperimentalProperty
}
% endif
diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs
index 8c78b19aa3c..c9d5354238a 100644
--- a/components/style/stylesheets.rs
+++ b/components/style/stylesheets.rs
@@ -426,7 +426,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
Ok(AtRuleType::WithBlock(AtRulePrelude::FontFace))
},
"viewport" => {
- if ::util::prefs::get_pref("layout.viewport.enabled").unwrap_or(false) {
+ if ::util::prefs::get_pref("layout.viewport.enabled").as_boolean().unwrap_or(false) {
Ok(AtRuleType::WithBlock(AtRulePrelude::Viewport))
} else {
Err(())
diff --git a/components/util/opts.rs b/components/util/opts.rs
index 1a310dd543c..bdf8277adce 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -9,7 +9,7 @@ use euclid::size::{Size2D, TypedSize2D};
use geometry::ScreenPx;
use getopts::Options;
use num_cpus;
-use prefs;
+use prefs::{self, PrefValue};
use std::cmp;
use std::default::Default;
use std::env;
@@ -614,7 +614,7 @@ pub fn from_cmdline_args(args: &[String]) {
// This must happen after setting the default options, since the prefs rely on
// on the resource path.
for pref in opt_match.opt_strs("pref").iter() {
- prefs::set_pref(pref, true);
+ prefs::set_pref(pref, PrefValue::Boolean(true));
}
}
diff --git a/components/util/prefs.rs b/components/util/prefs.rs
index bd3110b6995..e2ee109ea00 100644
--- a/components/util/prefs.rs
+++ b/components/util/prefs.rs
@@ -3,19 +3,122 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use resource_files::resources_dir_path;
-use rustc_serialize::json::Json;
+use rustc_serialize::json::{Json, ToJson};
+use std::borrow::ToOwned;
use std::collections::HashMap;
use std::fs::File;
use std::sync::{Arc, Mutex};
lazy_static! {
- static ref PREFS: Arc<Mutex<HashMap<String, bool>>> = {
+ static ref PREFS: Arc<Mutex<HashMap<String, Pref>>> = {
let prefs = read_prefs().unwrap_or(HashMap::new());
Arc::new(Mutex::new(prefs))
};
}
-fn read_prefs() -> Result<HashMap<String, bool>, ()> {
+#[derive(PartialEq, Clone, Debug)]
+pub enum PrefValue {
+ Boolean(bool),
+ String(String),
+ Missing
+}
+
+impl PrefValue {
+ pub fn from_json(data: Json) -> Result<PrefValue, ()> {
+ let value = match data {
+ Json::Boolean(x) => PrefValue::Boolean(x),
+ Json::String(x) => PrefValue::String(x),
+ _ => return Err(())
+ };
+ Ok(value)
+ }
+
+ pub fn as_boolean(&self) -> Option<bool> {
+ match self {
+ &PrefValue::Boolean(value) => {
+ Some(value)
+ },
+ _ => None
+ }
+ }
+
+ pub fn as_string(&self) -> Option<&str> {
+ match *self {
+ PrefValue::String(ref value) => {
+ Some(&value)
+ },
+ _ => None
+ }
+ }
+}
+
+impl ToJson for PrefValue {
+ fn to_json(&self) -> Json {
+ match *self {
+ PrefValue::Boolean(x) => {
+ Json::Boolean(x)
+ },
+ PrefValue::String(ref x) => {
+ Json::String(x.clone())
+ }
+ PrefValue::Missing => Json::Null
+ }
+ }
+}
+
+enum Pref {
+ NoDefault(Arc<PrefValue>),
+ WithDefault(Arc<PrefValue>, Option<Arc<PrefValue>>)
+}
+
+
+impl Pref {
+ pub fn new(value: PrefValue) -> Pref {
+ Pref::NoDefault(Arc::new(value))
+ }
+
+ fn new_default(value: PrefValue) -> Pref {
+ Pref::WithDefault(Arc::new(value), None)
+ }
+
+ fn from_json(data: Json) -> Result<Pref, ()> {
+ let value = try!(PrefValue::from_json(data));
+ Ok(Pref::new_default(value))
+ }
+
+ pub fn value(&self) -> &Arc<PrefValue> {
+ match self {
+ &Pref::NoDefault(ref x) => x,
+ &Pref::WithDefault(ref default, ref override_value) => {
+ match override_value {
+ &Some(ref x) => x,
+ &None => default
+ }
+ }
+ }
+ }
+
+ fn set(&mut self, value: PrefValue) {
+ // TODO - this should error if we try to override a pref of one type
+ // with a value of a different type
+ match self {
+ &mut Pref::NoDefault(ref mut pref_value) => {
+ *pref_value = Arc::new(value)
+ },
+ &mut Pref::WithDefault(_, ref mut override_value) => {
+ *override_value = Some(Arc::new(value))
+ }
+ }
+ }
+}
+
+impl ToJson for Pref {
+ fn to_json(&self) -> Json {
+ self.value().to_json()
+ }
+}
+
+fn read_prefs() -> Result<HashMap<String, Pref>, ()> {
let mut path = resources_dir_path();
path.push("prefs.json");
@@ -29,22 +132,53 @@ fn read_prefs() -> Result<HashMap<String, bool>, ()> {
}));
let mut prefs = HashMap::new();
- if let Some(obj) = json.as_object() {
- for (name, value) in obj.iter() {
- if let Some(bool_value) = value.as_boolean() {
- prefs.insert(name.clone(), bool_value);
- } else {
- println!("Ignoring non-boolean preference value for {:?}", name);
+ if let Json::Object(obj) = json {
+ for (name, value) in obj.into_iter() {
+ match Pref::from_json(value) {
+ Ok(x) => {
+ prefs.insert(name, x);
+ },
+ Err(_) => println!("Ignoring non-boolean/string preference value for {:?}", name)
}
}
}
Ok(prefs)
}
-pub fn get_pref(name: &str) -> Option<bool> {
- PREFS.lock().unwrap().get(name).cloned()
+pub fn get_pref(name: &str) -> Arc<PrefValue> {
+ PREFS.lock().unwrap().get(name).map(|x| x.value().clone()).unwrap_or(Arc::new(PrefValue::Missing))
+}
+
+pub fn set_pref(name: &str, value: PrefValue) {
+ let mut prefs = PREFS.lock().unwrap();
+ if let Some(pref) = prefs.get_mut(name) {
+ pref.set(value);
+ return;
+ }
+ prefs.insert(name.to_owned(), Pref::new(value));
}
-pub fn set_pref(name: &str, value: bool) {
- let _ = PREFS.lock().unwrap().insert(name.to_owned(), value);
+pub fn reset_pref(name: &str) -> Arc<PrefValue> {
+ let mut prefs = PREFS.lock().unwrap();
+ let result = match prefs.get_mut(name) {
+ None => return Arc::new(PrefValue::Missing),
+ Some(&mut Pref::NoDefault(_)) => Arc::new(PrefValue::Missing),
+ Some(&mut Pref::WithDefault(ref default, ref mut set_value)) => {
+ *set_value = None;
+ default.clone()
+ },
+ };
+ if *result == PrefValue::Missing {
+ prefs.remove(name);
+ }
+ result
+}
+
+pub fn reset_all_prefs() {
+ let names = {
+ PREFS.lock().unwrap().keys().map(|x| x.clone()).collect::<Vec<String>>()
+ };
+ for name in names.iter() {
+ reset_pref(name);
+ }
}
diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs
index 6ecbdd18c68..29bac552568 100644
--- a/components/webdriver_server/lib.rs
+++ b/components/webdriver_server/lib.rs
@@ -35,7 +35,7 @@ use std::collections::BTreeMap;
use std::net::SocketAddr;
use std::thread::{self, sleep_ms};
use url::Url;
-use util::prefs::{get_pref, set_pref};
+use util::prefs::{get_pref, reset_all_prefs, reset_pref, set_pref, PrefValue};
use util::task::spawn_named;
use uuid::Uuid;
use webdriver::command::{GetParameters, JavascriptCommandParameters, LocatorParameters};
@@ -150,7 +150,7 @@ impl ToJson for GetPrefsParameters {
#[derive(Clone, PartialEq)]
struct SetPrefsParameters {
- prefs: Vec<(String, bool)>
+ prefs: Vec<(String, PrefValue)>
}
impl Parameters for SetPrefsParameters {
@@ -166,9 +166,9 @@ impl Parameters for SetPrefsParameters {
"prefs was not an array")));
let mut params = Vec::with_capacity(items.len());
for (name, val) in items.iter() {
- let value = try!(val.as_boolean().ok_or(
- WebDriverError::new(ErrorStatus::InvalidArgument,
- "Pref is not a bool")));
+ let value = try!(PrefValue::from_json(val).or(
+ Err(WebDriverError::new(ErrorStatus::InvalidArgument,
+ "Pref is not a boolean or string"))));
let key = name.to_owned();
params.push((key, value));
}
@@ -633,13 +633,14 @@ impl Handler {
.iter()
.map(|item| (item.clone(), get_pref(item).to_json()))
.collect::<BTreeMap<_, _>>();
+
Ok(WebDriverResponse::Generic(ValueResponse::new(prefs.to_json())))
}
fn handle_set_prefs(&self,
parameters: &SetPrefsParameters) -> WebDriverResult<WebDriverResponse> {
for &(ref key, ref value) in parameters.prefs.iter() {
- set_pref(key, *value);
+ set_pref(key, value.clone());
}
Ok(WebDriverResponse::Void)
}
diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs
index 994908b3cfb..bd1a2c0195a 100644
--- a/tests/unit/style/viewport.rs
+++ b/tests/unit/style/viewport.rs
@@ -26,7 +26,8 @@ fn test_viewport_rule<F>(css: &str,
callback: F)
where F: Fn(&Vec<ViewportDescriptorDeclaration>, &str)
{
- ::util::prefs::set_pref("layout.viewport.enabled", true);
+ ::util::prefs::set_pref("layout.viewport.enabled",
+ ::util::prefs::PrefValue::Boolean(true));
let stylesheet = stylesheet!(css, Author);
let mut rule_count = 0;
@@ -173,7 +174,8 @@ fn cascading_within_viewport_rule() {
#[test]
fn multiple_stylesheets_cascading() {
- ::util::prefs::set_pref("layout.viewport.enabled", true);
+ ::util::prefs::set_pref("layout.viewport.enabled",
+ ::util::prefs::PrefValue::Boolean(true));
let device = Device::new(MediaType::Screen, Size2D::typed(800., 600.));
let stylesheets = vec![