Skip to content

Commit

Permalink
Auto merge of #10826 - danlrobertson:cookies, r=asajeffrey
Browse files Browse the repository at this point in the history
Add webdriver commands for (Get|Add)Cookie

Add the webdriver commands for GetCookie and AddCookie. In addition the basic messages for sending cookie data back and forth from the resource thread needed to be created and the handlers for those messages were created as well.

Do we plan to have some sort of test suite for the webdriver at some point? At this point I primarily test my PRs with basic shell scripts with a lot of `curl` and `jq`.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10826)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Jun 26, 2016
2 parents 8dcb12a + 2467231 commit 054bb38
Show file tree
Hide file tree
Showing 19 changed files with 214 additions and 23 deletions.
1 change: 1 addition & 0 deletions components/msg/Cargo.toml
Expand Up @@ -24,3 +24,4 @@ serde_macros = "0.7"
url = {version = "1.0.0", features = ["heap_size", "serde"]}
util = {path = "../util", features = ["servo"]}
webrender_traits = {git = "https://github.com/servo/webrender_traits"}
cookie = { version = "0.2.5", features = ["serialize-serde", "serialize-rustc" ] }
1 change: 1 addition & 0 deletions components/msg/lib.rs
Expand Up @@ -10,6 +10,7 @@
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
extern crate cookie as cookie_rs;
extern crate euclid;
extern crate heapsize;
extern crate hyper;
Expand Down
10 changes: 10 additions & 0 deletions components/msg/webdriver_msg.rs
Expand Up @@ -3,19 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use constellation_msg::PipelineId;
use cookie_rs::Cookie;
use euclid::rect::Rect;
use ipc_channel::ipc::IpcSender;
use rustc_serialize::json::{Json, ToJson};
use url::Url;

#[derive(Deserialize, Serialize)]
pub enum WebDriverScriptCommand {
AddCookie(Cookie, IpcSender<Result<(), WebDriverCookieError>>),
ExecuteScript(String, IpcSender<WebDriverJSResult>),
ExecuteAsyncScript(String, IpcSender<WebDriverJSResult>),
FindElementCSS(String, IpcSender<Result<Option<String>, ()>>),
FindElementsCSS(String, IpcSender<Result<Vec<String>, ()>>),
FocusElement(String, IpcSender<Result<(), ()>>),
GetActiveElement(IpcSender<Option<String>>),
GetCookie(String, IpcSender<Vec<Cookie>>),
GetCookies(IpcSender<Vec<Cookie>>),
GetElementAttribute(String, String, IpcSender<Result<Option<String>, ()>>),
GetElementCSS(String, String, IpcSender<Result<String, ()>>),
GetElementRect(String, IpcSender<Result<Rect<f64>, ()>>),
Expand All @@ -28,6 +32,12 @@ pub enum WebDriverScriptCommand {
GetTitle(IpcSender<String>)
}

#[derive(Deserialize, Serialize)]
pub enum WebDriverCookieError {
InvalidDomain,
UnableToSetCookie
}

#[derive(Deserialize, Serialize)]
pub enum WebDriverJSValue {
Undefined,
Expand Down
2 changes: 1 addition & 1 deletion components/net/Cargo.toml
Expand Up @@ -12,7 +12,7 @@ path = "lib.rs"
bitflags = "0.7"
brotli = {git = "https://github.com/ende76/brotli-rs"}
content-blocker = "0.2"
cookie = {version = "0.2.4", features = ["serialize-rustc"]}
cookie = { version = "0.2.5", features = ["serialize-serde", "serialize-rustc" ] }
device = {git = "https://github.com/servo/devices"}
devtools_traits = {path = "../devtools_traits"}
flate2 = "0.2.0"
Expand Down
9 changes: 9 additions & 0 deletions components/net/cookie_storage.rs
Expand Up @@ -6,6 +6,7 @@
//! http://tools.ietf.org/html/rfc6265

use cookie::Cookie;
use cookie_rs;
use net_traits::CookieSource;
use std::cmp::Ordering;
use url::Url;
Expand Down Expand Up @@ -114,4 +115,12 @@ impl CookieStorage {
_ => Some(result)
}
}

pub fn cookies_data_for_url<'a>(&'a mut self, url: &'a Url,
source: CookieSource) -> Box<Iterator<Item=cookie_rs::Cookie> + 'a> {
Box::new(self.cookies.iter_mut().filter(move |c| { c.appropriate_for_url(url, source) }).map(|c| {
c.touch();
c.cookie.clone()
}))
}
}
16 changes: 16 additions & 0 deletions components/net/resource_thread.rs
Expand Up @@ -8,6 +8,7 @@ use chrome_loader;
use connector::{Connector, create_http_connector};
use content_blocker::BLOCKED_CONTENT_RULES;
use cookie;
use cookie_rs;
use cookie_storage::CookieStorage;
use data_loader;
use devtools_traits::DevtoolsControlMsg;
Expand Down Expand Up @@ -277,10 +278,17 @@ impl ResourceChannelManager {
self.resource_manager.websocket_connect(connect, connect_data, group),
CoreResourceMsg::SetCookiesForUrl(request, cookie_list, source) =>
self.resource_manager.set_cookies_for_url(request, cookie_list, source, group),
CoreResourceMsg::SetCookiesForUrlWithData(request, cookie, source) =>
self.resource_manager.set_cookies_for_url_with_data(request, cookie, source, group),
CoreResourceMsg::GetCookiesForUrl(url, consumer, source) => {
let mut cookie_jar = group.cookie_jar.write().unwrap();
consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap();
}
CoreResourceMsg::GetCookiesDataForUrl(url, consumer, source) => {
let mut cookie_jar = group.cookie_jar.write().unwrap();
let cookies = cookie_jar.cookies_data_for_url(&url, source).collect();
consumer.send(cookies).unwrap();
}
CoreResourceMsg::Cancel(res_id) => {
if let Some(cancel_sender) = self.resource_manager.cancel_load_map.get(&res_id) {
let _ = cancel_sender.send(());
Expand Down Expand Up @@ -488,6 +496,14 @@ impl CoreResourceManager {
}
}

fn set_cookies_for_url_with_data(&mut self, request: Url, cookie: cookie_rs::Cookie, source: CookieSource,
resource_group: &ResourceGroup) {
if let Some(cookie) = cookie::Cookie::new_wrapped(cookie, &request, source) {
let mut cookie_jar = resource_group.cookie_jar.write().unwrap();
cookie_jar.push(cookie, source)
}
}

fn load(&mut self,
load_data: LoadData,
consumer: LoadConsumer,
Expand Down
1 change: 1 addition & 0 deletions components/net_traits/Cargo.toml
Expand Up @@ -23,3 +23,4 @@ serde_macros = "0.7"
url = {version = "1.0.0", features = ["heap_size"]}
websocket = "0.17"
uuid = { version = "0.2.2", features = ["v4", "serde"] }
cookie = { version = "0.2.5", features = ["serialize-serde", "serialize-rustc" ] }
6 changes: 6 additions & 0 deletions components/net_traits/lib.rs
Expand Up @@ -12,6 +12,7 @@

#![deny(unsafe_code)]

extern crate cookie as cookie_rs;
extern crate heapsize;
extern crate hyper;
extern crate image as piston_image;
Expand All @@ -28,6 +29,7 @@ extern crate util;
extern crate uuid;
extern crate websocket;

use cookie_rs::Cookie;
use filemanager_thread::FileManagerThreadMsg;
use heapsize::HeapSizeOf;
use hyper::header::{ContentType, Headers};
Expand Down Expand Up @@ -423,8 +425,12 @@ pub enum CoreResourceMsg {
WebsocketConnect(WebSocketCommunicate, WebSocketConnectData),
/// Store a set of cookies for a given originating URL
SetCookiesForUrl(Url, String, CookieSource),
/// Store a set of cookies for a given originating URL
SetCookiesForUrlWithData(Url, Cookie, CookieSource),
/// Retrieve the stored cookies for a given URL
GetCookiesForUrl(Url, IpcSender<Option<String>>, CookieSource),
/// Get a cookie by name for a given originating URL
GetCookiesDataForUrl(Url, IpcSender<Vec<Cookie>>, CookieSource),
/// Cancel a network request corresponding to a given `ResourceId`
Cancel(ResourceId),
/// Synchronization message solely for knowing the state of the ResourceChannelManager loop
Expand Down
1 change: 1 addition & 0 deletions components/script/Cargo.toml
Expand Up @@ -22,6 +22,7 @@ app_units = {version = "0.2.3", features = ["plugins"]}
bitflags = "0.7"
canvas_traits = {path = "../canvas_traits"}
caseless = "0.1.0"
cookie = { version = "0.2.5", features = ["serialize-serde", "serialize-rustc" ] }
cssparser = {version = "0.5.4", features = ["heap_size", "serde-serialization"]}
devtools_traits = {path = "../devtools_traits"}
encoding = "0.2"
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/document.rs
Expand Up @@ -1562,7 +1562,7 @@ impl Document {
}

/// https://html.spec.whatwg.org/multipage/#cookie-averse-document-object
fn is_cookie_averse(&self) -> bool {
pub fn is_cookie_averse(&self) -> bool {
self.browsing_context.is_none() || !url_has_network_scheme(&self.url)
}

Expand Down
1 change: 1 addition & 0 deletions components/script/lib.rs
Expand Up @@ -36,6 +36,7 @@ extern crate app_units;
extern crate bitflags;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use]
extern crate cssparser;
Expand Down
6 changes: 6 additions & 0 deletions components/script/script_thread.rs
Expand Up @@ -1059,6 +1059,8 @@ impl ScriptThread {
fn handle_webdriver_msg(&self, pipeline_id: PipelineId, msg: WebDriverScriptCommand) {
let context = self.root_browsing_context();
match msg {
WebDriverScriptCommand::AddCookie(params, reply) =>
webdriver_handlers::handle_add_cookie(&context, pipeline_id, params, reply),
WebDriverScriptCommand::ExecuteScript(script, reply) =>
webdriver_handlers::handle_execute_script(&context, pipeline_id, script, reply),
WebDriverScriptCommand::FindElementCSS(selector, reply) =>
Expand All @@ -1069,6 +1071,10 @@ impl ScriptThread {
webdriver_handlers::handle_focus_element(&context, pipeline_id, element_id, reply),
WebDriverScriptCommand::GetActiveElement(reply) =>
webdriver_handlers::handle_get_active_element(&context, pipeline_id, reply),
WebDriverScriptCommand::GetCookies(reply) =>
webdriver_handlers::handle_get_cookies(&context, pipeline_id, reply),
WebDriverScriptCommand::GetCookie(name, reply) =>
webdriver_handlers::handle_get_cookie(&context, pipeline_id, name, reply),
WebDriverScriptCommand::GetElementTagName(node_id, reply) =>
webdriver_handlers::handle_get_name(&context, pipeline_id, node_id, reply),
WebDriverScriptCommand::GetElementAttribute(node_id, name, reply) =>
Expand Down
67 changes: 66 additions & 1 deletion components/script/webdriver_handlers.rs
Expand Up @@ -2,6 +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 cookie_rs::Cookie;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
Expand All @@ -26,12 +27,16 @@ use dom::window::ScriptHelpers;
use euclid::point::Point2D;
use euclid::rect::Rect;
use euclid::size::Size2D;
use ipc_channel::ipc::IpcSender;
use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::JSContext;
use js::jsapi::{HandleValue, RootedValue};
use js::jsval::UndefinedValue;
use msg::constellation_msg::PipelineId;
use msg::webdriver_msg::WebDriverCookieError;
use msg::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue};
use net_traits::CookieSource::{HTTP, NonHTTP};
use net_traits::CoreResourceMsg::{GetCookiesDataForUrl, SetCookiesForUrlWithData};
use net_traits::IpcSend;
use script_thread::get_browsing_context;
use url::Url;

Expand Down Expand Up @@ -177,6 +182,66 @@ pub fn handle_get_active_element(context: &BrowsingContext,
|elem| elem.upcast::<Node>().unique_id())).unwrap();
}

pub fn handle_get_cookies(context: &BrowsingContext,
_pipeline: PipelineId,
reply: IpcSender<Vec<Cookie>>) {
let document = context.active_document();
let url = document.url();
let (sender, receiver) = ipc::channel().unwrap();
let _ = document.window().resource_threads().send(
GetCookiesDataForUrl(url.clone(), sender, NonHTTP)
);
let cookies = receiver.recv().unwrap();
reply.send(cookies).unwrap();
}

// https://w3c.github.io/webdriver/webdriver-spec.html#get-cookie
pub fn handle_get_cookie(context: &BrowsingContext,
_pipeline: PipelineId,
name: String,
reply: IpcSender<Vec<Cookie>>) {
let document = context.active_document();
let url = document.url();
let (sender, receiver) = ipc::channel().unwrap();
let _ = document.window().resource_threads().send(
GetCookiesDataForUrl(url.clone(), sender, NonHTTP)
);
let cookies = receiver.recv().unwrap();
reply.send(cookies.into_iter().filter(|c| c.name == &*name).collect()).unwrap();
}

// https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie
pub fn handle_add_cookie(context: &BrowsingContext,
_pipeline: PipelineId,
cookie: Cookie,
reply: IpcSender<Result<(), WebDriverCookieError>>) {
let document = context.active_document();
let url = document.url();
let method = if cookie.httponly {
HTTP
} else {
NonHTTP
};
reply.send(match (document.is_cookie_averse(), cookie.domain.clone()) {
(true, _) => Err(WebDriverCookieError::InvalidDomain),
(false, Some(ref domain)) if url.host_str().map(|x| { x == &**domain }).unwrap_or(false) => {
let _ = document.window().resource_threads().send(
SetCookiesForUrlWithData(url.clone(), cookie, method)
);
Ok(())
},
(false, None) => {
let _ = document.window().resource_threads().send(
SetCookiesForUrlWithData(url.clone(), cookie, method)
);
Ok(())
},
(_, _) => {
Err(WebDriverCookieError::UnableToSetCookie)
},
}).unwrap();
}

pub fn handle_get_title(context: &BrowsingContext, _pipeline: PipelineId, reply: IpcSender<String>) {
reply.send(String::from(context.active_document().Title())).unwrap();
}
Expand Down
13 changes: 9 additions & 4 deletions components/servo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/webdriver_server/Cargo.toml
Expand Up @@ -23,3 +23,4 @@ script_traits = {path = "../script_traits"}
url = {version = "1.0.0", features = ["heap_size"]}
uuid = { version = "0.2", features = ["v4"] }
webdriver = "0.9"
cookie = { version = "0.2.5", features = ["serialize-serde", "serialize-rustc" ] }

0 comments on commit 054bb38

Please sign in to comment.