aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/compositing/scrolling.rs12
-rw-r--r--components/compositing/timer_scheduler.rs3
-rw-r--r--components/devtools/actors/timeline.rs7
-rw-r--r--components/msg/webdriver_msg.rs5
-rw-r--r--components/profile/mem.rs6
-rw-r--r--components/profile/time.rs10
-rw-r--r--components/script/script_task.rs6
-rw-r--r--components/script/webdriver_handlers.rs52
-rw-r--r--components/util/lib.rs1
-rw-r--r--components/util/time.rs32
-rw-r--r--components/webdriver_server/lib.rs65
-rw-r--r--components/webdriver_traits/lib.rs51
12 files changed, 175 insertions, 75 deletions
diff --git a/components/compositing/scrolling.rs b/components/compositing/scrolling.rs
index c4f4be7804c..0fec56f1527 100644
--- a/components/compositing/scrolling.rs
+++ b/components/compositing/scrolling.rs
@@ -6,13 +6,15 @@
use compositor_task::{CompositorProxy, Msg};
use std::sync::mpsc::{Receiver, Sender, channel};
-use std::thread::{Builder, sleep_ms};
+use std::thread::{self, Builder};
+use std::u32;
use time;
+use util::time::duration_from_nanoseconds;
/// The amount of time in nanoseconds that we give to the painting thread to paint new tiles upon
/// processing a scroll event that caused new tiles to be revealed. When this expires, we give up
/// and composite anyway (showing a "checkerboard") to avoid dropping the frame.
-static TIMEOUT: i64 = 12_000_000;
+static TIMEOUT: u64 = 12_000_000;
pub struct ScrollingTimerProxy {
sender: Sender<ToScrollingTimerMsg>,
@@ -55,9 +57,9 @@ impl ScrollingTimerProxy {
impl ScrollingTimer {
pub fn run(&mut self) {
while let Ok(ToScrollingTimerMsg::ScrollEventProcessedMsg(timestamp)) = self.receiver.recv() {
- let target = timestamp as i64 + TIMEOUT;
- let delta_ns = target - (time::precise_time_ns() as i64);
- sleep_ms((delta_ns / 1000000) as u32);
+ let target = timestamp + TIMEOUT;
+ let delta_ns = target - time::precise_time_ns();
+ thread::sleep(duration_from_nanoseconds(delta_ns));
self.compositor_proxy.send(Msg::ScrollTimeout(timestamp));
}
}
diff --git a/components/compositing/timer_scheduler.rs b/components/compositing/timer_scheduler.rs
index 7cfeb539998..b81290bc74d 100644
--- a/components/compositing/timer_scheduler.rs
+++ b/components/compositing/timer_scheduler.rs
@@ -15,6 +15,7 @@ use std::sync::Arc;
use std::sync::atomic::{self, AtomicBool};
use std::sync::mpsc::{channel, Receiver, Select};
use std::thread::{self, spawn, Thread};
+use std::time::Duration;
use util::task::spawn_named;
/// A quick hack to work around the removal of [`std::old_io::timer::Timer`](
@@ -37,7 +38,7 @@ impl CancelableOneshotTimer {
let mut park_time = duration;
loop {
- thread::park_timeout_ms(park_time.get() as u32);
+ thread::park_timeout(Duration::from_millis(park_time.get()));
if canceled_clone.load(atomic::Ordering::Relaxed) {
return;
diff --git a/components/devtools/actors/timeline.rs b/components/devtools/actors/timeline.rs
index d55f380c68a..56ac06c40b2 100644
--- a/components/devtools/actors/timeline.rs
+++ b/components/devtools/actors/timeline.rs
@@ -16,7 +16,8 @@ use std::cell::RefCell;
use std::net::TcpStream;
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};
-use std::thread::sleep_ms;
+use std::thread;
+use std::time::Duration;
use util::task;
pub struct TimelineActor {
@@ -116,7 +117,7 @@ impl Encodable for HighResolutionStamp {
}
}
-static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u32 = 200; //ms
+static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u64 = 200; //ms
impl TimelineActor {
pub fn new(name: String,
@@ -158,7 +159,7 @@ impl TimelineActor {
}
emitter.send(markers);
- sleep_ms(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT);
+ thread::sleep(Duration::from_millis(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT));
}
});
}
diff --git a/components/msg/webdriver_msg.rs b/components/msg/webdriver_msg.rs
index 658df1e79e1..94c4556b5f0 100644
--- a/components/msg/webdriver_msg.rs
+++ b/components/msg/webdriver_msg.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use constellation_msg::PipelineId;
+use constellation_msg::{PipelineId, WindowSizeData};
use ipc_channel::ipc::IpcSender;
use rustc_serialize::json::{Json, ToJson};
use url::Url;
@@ -21,6 +21,9 @@ pub enum WebDriverScriptCommand {
GetElementText(String, IpcSender<Result<String, ()>>),
GetFrameId(WebDriverFrameId, IpcSender<Result<Option<PipelineId>, ()>>),
GetUrl(IpcSender<Url>),
+ GetWindowSize(IpcSender<Option<WindowSizeData>>),
+ IsEnabled(String, IpcSender<Result<bool, ()>>),
+ IsSelected(String, IpcSender<Result<bool, ()>>),
GetTitle(IpcSender<String>)
}
diff --git a/components/profile/mem.rs b/components/profile/mem.rs
index becd2d05554..8a9314c69c1 100644
--- a/components/profile/mem.rs
+++ b/components/profile/mem.rs
@@ -11,8 +11,9 @@ use profile_traits::mem::{ProfilerChan, ProfilerMsg, ReportKind, Reporter, Repor
use std::borrow::ToOwned;
use std::cmp::Ordering;
use std::collections::HashMap;
-use std::thread::sleep_ms;
+use std::thread;
use util::task::spawn_named;
+use util::time::duration_from_seconds;
pub struct Profiler {
/// The port through which messages are received.
@@ -31,11 +32,10 @@ impl Profiler {
// Create the timer thread if a period was provided.
if let Some(period) = period {
- let period_ms = (period * 1000.) as u32;
let chan = chan.clone();
spawn_named("Memory profiler timer".to_owned(), move || {
loop {
- sleep_ms(period_ms);
+ thread::sleep(duration_from_seconds(period));
if chan.send(ProfilerMsg::Print).is_err() {
break;
}
diff --git a/components/profile/time.rs b/components/profile/time.rs
index 8092be811bd..71dfc29a519 100644
--- a/components/profile/time.rs
+++ b/components/profile/time.rs
@@ -12,10 +12,11 @@ use profile_traits::time::{TimerMetadataReflowType, TimerMetadataFrameType};
use std::borrow::ToOwned;
use std::cmp::Ordering;
use std::collections::BTreeMap;
-use std::f64;
-use std::thread::sleep_ms;
+use std::time::Duration;
+use std::{thread, f64};
use std_time::precise_time_ns;
use util::task::spawn_named;
+use util::time::duration_from_seconds;
pub trait Formattable {
fn format(&self) -> String;
@@ -123,11 +124,10 @@ impl Profiler {
let (chan, port) = ipc::channel().unwrap();
match period {
Some(period) => {
- let period = (period * 1000.) as u32;
let chan = chan.clone();
spawn_named("Time profiler timer".to_owned(), move || {
loop {
- sleep_ms(period);
+ thread::sleep(duration_from_seconds(period));
if chan.send(ProfilerMsg::Print).is_err() {
break;
}
@@ -173,7 +173,7 @@ impl Profiler {
loop {
for _ in 0..loop_count {
match run_ap_thread() {
- true => sleep_ms(SLEEP_MS),
+ true => thread::sleep(Duration::from_millis(SLEEP_MS as u64)),
false => return,
}
}
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 7ceb22cbd73..848f964d2c0 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -1116,6 +1116,12 @@ impl ScriptTask {
webdriver_handlers::handle_get_frame_id(&page, pipeline_id, frame_id, reply),
WebDriverScriptCommand::GetUrl(reply) =>
webdriver_handlers::handle_get_url(&page, pipeline_id, reply),
+ WebDriverScriptCommand::GetWindowSize(reply) =>
+ webdriver_handlers::handle_get_window_size(&page, pipeline_id, reply),
+ WebDriverScriptCommand::IsEnabled(element_id, reply) =>
+ webdriver_handlers::handle_is_enabled(&page, pipeline_id, element_id, reply),
+ WebDriverScriptCommand::IsSelected(element_id, reply) =>
+ webdriver_handlers::handle_is_selected(&page, pipeline_id, element_id, reply),
WebDriverScriptCommand::GetTitle(reply) =>
webdriver_handlers::handle_get_title(&page, pipeline_id, reply),
WebDriverScriptCommand::ExecuteAsyncScript(script, reply) =>
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs
index 818ad20abf9..bd5fd9576c7 100644
--- a/components/script/webdriver_handlers.rs
+++ b/components/script/webdriver_handlers.rs
@@ -7,6 +7,8 @@ use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
+use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
+use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
@@ -16,13 +18,15 @@ use dom::bindings::js::Root;
use dom::element::Element;
use dom::htmlelement::HTMLElement;
use dom::htmliframeelement::HTMLIFrameElement;
+use dom::htmlinputelement::HTMLInputElement;
+use dom::htmloptionelement::HTMLOptionElement;
use dom::node::Node;
use dom::window::ScriptHelpers;
use ipc_channel::ipc::IpcSender;
use js::jsapi::JSContext;
use js::jsapi::{HandleValue, RootedValue};
use js::jsval::UndefinedValue;
-use msg::constellation_msg::PipelineId;
+use msg::constellation_msg::{PipelineId, WindowSizeData};
use msg::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue};
use page::Page;
use script_task::get_page;
@@ -242,3 +246,49 @@ pub fn handle_get_url(page: &Rc<Page>,
let url = document.url();
reply.send((*url).clone()).unwrap();
}
+
+pub fn handle_get_window_size(page: &Rc<Page>,
+ _pipeline: PipelineId,
+ reply: IpcSender<Option<WindowSizeData>>) {
+ let window = page.window();
+ let size = window.window_size();
+ reply.send(size).unwrap();
+}
+
+pub fn handle_is_enabled(page: &Rc<Page>,
+ pipeline: PipelineId,
+ element_id: String,
+ reply: IpcSender<Result<bool, ()>>) {
+ reply.send(match find_node_by_unique_id(page, pipeline, element_id) {
+ Some(ref node) => {
+ match node.downcast::<Element>() {
+ Some(elem) => Ok(elem.get_enabled_state()),
+ None => Err(())
+ }
+ },
+ None => Err(())
+ }).unwrap();
+}
+
+pub fn handle_is_selected(page: &Rc<Page>,
+ pipeline: PipelineId,
+ element_id: String,
+ reply: IpcSender<Result<bool, ()>>) {
+ reply.send(match find_node_by_unique_id(page, pipeline, element_id) {
+ Some(ref node) => {
+ if let Some(input_element) = node.downcast::<HTMLInputElement>() {
+ Ok(input_element.Checked())
+ }
+ else if let Some(option_element) = node.downcast::<HTMLOptionElement>() {
+ Ok(option_element.Selected())
+ }
+ else if let Some(_) = node.downcast::<HTMLElement>() {
+ Ok(false) // regular elements are not selectable
+ }
+ else {
+ Err(())
+ }
+ },
+ None => Err(())
+ }).unwrap();
+}
diff --git a/components/util/lib.rs b/components/util/lib.rs
index f39940fd78d..9afbf0d5293 100644
--- a/components/util/lib.rs
+++ b/components/util/lib.rs
@@ -73,6 +73,7 @@ pub mod task;
pub mod task_state;
pub mod taskpool;
pub mod tid;
+pub mod time;
pub mod vec;
pub mod workqueue;
diff --git a/components/util/time.rs b/components/util/time.rs
new file mode 100644
index 00000000000..8186fc2ebed
--- /dev/null
+++ b/components/util/time.rs
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::time::Duration;
+use std::{u32, u64};
+
+pub const NANOS_PER_SEC: u32 = 1_000_000_000;
+
+pub fn duration_from_seconds(secs: f64) -> Duration {
+
+ // Get number of seconds and check that it fits in a u64.
+ let whole_secs = secs.trunc();
+ assert!(whole_secs >= 0.0 && whole_secs <= u64::MAX as f64);
+
+ // Get number of nanoseconds. This should always fit in a u32, but check anyway.
+ let nanos = (secs.fract() * (NANOS_PER_SEC as f64)).trunc();
+ assert!(nanos >= 0.0 && nanos <= u32::MAX as f64);
+
+ Duration::new(whole_secs as u64, nanos as u32)
+}
+
+pub fn duration_from_nanoseconds(nanos: u64) -> Duration {
+ // Get number of seconds.
+ let secs = nanos / NANOS_PER_SEC as u64;
+
+ // Get number of extra nanoseconds. This should always fit in a u32, but check anyway.
+ let subsec_nanos = nanos % NANOS_PER_SEC as u64;
+ assert!(subsec_nanos <= u32::MAX as u64);
+
+ Duration::new(secs, subsec_nanos as u32)
+}
diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs
index 0f01059005c..1acd63f352a 100644
--- a/components/webdriver_server/lib.rs
+++ b/components/webdriver_server/lib.rs
@@ -38,7 +38,8 @@ use std::borrow::ToOwned;
use std::collections::BTreeMap;
use std::net::SocketAddr;
use std::sync::mpsc::Sender;
-use std::thread::{self, sleep_ms};
+use std::thread;
+use std::time::Duration;
use url::Url;
use util::prefs::{get_pref, reset_all_prefs, reset_pref, set_pref, PrefValue};
use util::task::spawn_named;
@@ -49,7 +50,7 @@ use webdriver::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverM
use webdriver::common::{LocatorStrategy, WebElement};
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
use webdriver::httpapi::{WebDriverExtensionRoute};
-use webdriver::response::{NewSessionResponse, ValueResponse, WebDriverResponse};
+use webdriver::response::{NewSessionResponse, ValueResponse, WebDriverResponse, WindowSizeResponse};
use webdriver::server::{self, Session, WebDriverHandler};
fn extension_routes() -> Vec<(Method, &'static str, ServoExtensionRoute)> {
@@ -228,7 +229,7 @@ impl Handler {
return Ok(x)
};
- sleep_ms(interval);
+ thread::sleep(Duration::from_millis(interval));
};
Err(WebDriverError::new(ErrorStatus::Timeout,
@@ -319,7 +320,7 @@ impl Handler {
let timeout = self.load_timeout;
let timeout_chan = sender;
thread::spawn(move || {
- sleep_ms(timeout);
+ thread::sleep(Duration::from_millis(timeout as u64));
let _ = timeout_chan.send(LoadStatus::LoadTimeout);
});
@@ -345,6 +346,57 @@ impl Handler {
Ok(WebDriverResponse::Generic(ValueResponse::new(url.serialize().to_json())))
}
+ fn handle_window_size(&self) -> WebDriverResult<WebDriverResponse> {
+ let pipeline_id = try!(self.root_pipeline());
+
+ let (sender, receiver) = ipc::channel().unwrap();
+
+ let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
+ WebDriverScriptCommand::GetWindowSize(sender));
+ self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
+
+ match receiver.recv().unwrap() {
+ Some(window_size) => {
+ let vp = window_size.visible_viewport;
+ let window_size_response = WindowSizeResponse::new(vp.width.get() as u64, vp.height.get() as u64);
+ Ok(WebDriverResponse::WindowSize(window_size_response))
+ },
+ None => Err(WebDriverError::new(ErrorStatus::NoSuchWindow, "Unable to determine window size"))
+ }
+ }
+
+ fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
+ let pipeline_id = try!(self.root_pipeline());
+
+ let (sender, receiver) = ipc::channel().unwrap();
+
+ let element_id = element.id.clone();
+ let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
+ WebDriverScriptCommand::IsEnabled(element_id, sender));
+ self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
+
+ match receiver.recv().unwrap() {
+ Ok(is_enabled) => Ok(WebDriverResponse::Generic(ValueResponse::new(is_enabled.to_json()))),
+ Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, "Element not found"))
+ }
+ }
+
+ fn handle_is_selected(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
+ let pipeline_id = try!(self.root_pipeline());
+
+ let (sender, receiver) = ipc::channel().unwrap();
+
+ let element_id = element.id.clone();
+ let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id,
+ WebDriverScriptCommand::IsSelected(element_id, sender));
+ self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
+
+ match receiver.recv().unwrap() {
+ Ok(is_selected) => Ok(WebDriverResponse::Generic(ValueResponse::new(is_selected.to_json()))),
+ Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, "Element not found"))
+ }
+ }
+
fn handle_go_back(&self) -> WebDriverResult<WebDriverResponse> {
self.constellation_chan.send(ConstellationMsg::Navigate(None, NavigationDirection::Back)).unwrap();
Ok(WebDriverResponse::Void)
@@ -653,7 +705,7 @@ impl Handler {
break;
};
- sleep_ms(interval)
+ thread::sleep(Duration::from_millis(interval))
}
let img = match img {
@@ -730,6 +782,9 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
WebDriverCommand::NewSession => self.handle_new_session(),
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
WebDriverCommand::GetCurrentUrl => self.handle_current_url(),
+ WebDriverCommand::GetWindowSize => self.handle_window_size(),
+ WebDriverCommand::IsEnabled(ref element) => self.handle_is_enabled(element),
+ WebDriverCommand::IsSelected(ref element) => self.handle_is_selected(element),
WebDriverCommand::GoBack => self.handle_go_back(),
WebDriverCommand::GoForward => self.handle_go_forward(),
WebDriverCommand::Refresh => self.handle_refresh(),
diff --git a/components/webdriver_traits/lib.rs b/components/webdriver_traits/lib.rs
deleted file mode 100644
index d2654b5c4e2..00000000000
--- a/components/webdriver_traits/lib.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#![crate_name = "webdriver_traits"]
-#![crate_type = "rlib"]
-
-extern crate rustc_serialize;
-use rustc_serialize::json::{Json, ToJson};
-use std::sync::mpsc::Sender;
-
-pub enum WebDriverScriptCommand {
- ExecuteScript(String, Sender<WebDriverJSResult>),
- ExecuteAsyncScript(String, Sender<WebDriverJSResult>),
- FindElementCSS(String, Sender<Result<Option<String>, ()>>),
- FindElementsCSS(String, Sender<Result<Vec<String>, ()>>),
- GetActiveElement(Sender<Option<String>>),
- GetElementTagName(String, Sender<Result<String, ()>>),
- GetElementText(String, Sender<Result<String, ()>>),
- GetTitle(Sender<String>)
-}
-
-pub enum WebDriverJSValue {
- Undefined,
- Null,
- Boolean(bool),
- Number(f64),
- String(String),
- // TODO: ObjectValue and WebElementValue
-}
-
-pub enum WebDriverJSError {
- Timeout,
- UnknownType
-}
-
-pub type WebDriverJSResult = Result<WebDriverJSValue, WebDriverJSError>;
-
-impl ToJson for WebDriverJSValue {
- fn to_json(&self) -> Json {
- match self {
- &WebDriverJSValue::Undefined => Json::Null,
- &WebDriverJSValue::Null => Json::Null,
- &WebDriverJSValue::Boolean(ref x) => x.to_json(),
- &WebDriverJSValue::Number(ref x) => x.to_json(),
- &WebDriverJSValue::String(ref x) => x.to_json()
- }
- }
-}
-
-pub struct LoadComplete;