fune/servo/components/script/dom/storage.rs
Javier Rueda 9ad91e86cd servo: Merge #15475 - Only expose Storage/StorageEvent in Window (from kekkyojin:bb15436); r=jdm
<!-- Please describe your changes on the following line: -->
This patch removes Worker scope from Storage and StorageEvent WebIDL definition. This way it is possible to construct the objects passing Window instead of GlobalScope. It also removes some tests as they would run out of the scope.

It removes Worker from the WebIDL files defining the Storage and StorageEvent interfaces, as they should not be exposed in that scope.

In Rust source code, this patch replaces "GlobalScope" with "Window" on the contructors. It also modifies constructor calling code in order to pass Window instead of the previously used GlobalScope.

There has been removed these interfaces from the Worker tests.

(This time I did a real build and real tests. Sorry about previous pull requests, I am used to the Mozilla flow, which doesn't uses GitHub)

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #15436 (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 3d0fe9a0dd12650efc754f85287d2426c7463535

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : c7bb052d4be36590cd3584cb34a815207f8f86a4
2017-02-09 08:17:53 -08:00

209 lines
7.6 KiB
Rust

/* 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 dom::bindings::codegen::Bindings::StorageBinding;
use dom::bindings::codegen::Bindings::StorageBinding::StorageMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::storageevent::StorageEvent;
use dom::window::Window;
use ipc_channel::ipc::{self, IpcSender};
use net_traits::IpcSend;
use net_traits::storage_thread::{StorageThreadMsg, StorageType};
use script_thread::{Runnable, ScriptThread};
use script_traits::ScriptMsg;
use servo_url::ServoUrl;
use task_source::TaskSource;
#[dom_struct]
pub struct Storage {
reflector_: Reflector,
storage_type: StorageType
}
impl Storage {
fn new_inherited(storage_type: StorageType) -> Storage {
Storage {
reflector_: Reflector::new(),
storage_type: storage_type
}
}
pub fn new(global: &Window, storage_type: StorageType) -> Root<Storage> {
reflect_dom_object(box Storage::new_inherited(storage_type), global, StorageBinding::Wrap)
}
fn get_url(&self) -> ServoUrl {
self.global().get_url()
}
fn get_storage_thread(&self) -> IpcSender<StorageThreadMsg> {
self.global().resource_threads().sender()
}
}
impl StorageMethods for Storage {
// https://html.spec.whatwg.org/multipage/#dom-storage-length
fn Length(&self) -> u32 {
let (sender, receiver) = ipc::channel().unwrap();
self.get_storage_thread().send(StorageThreadMsg::Length(sender, self.get_url(), self.storage_type)).unwrap();
receiver.recv().unwrap() as u32
}
// https://html.spec.whatwg.org/multipage/#dom-storage-key
fn Key(&self, index: u32) -> Option<DOMString> {
let (sender, receiver) = ipc::channel().unwrap();
self.get_storage_thread()
.send(StorageThreadMsg::Key(sender, self.get_url(), self.storage_type, index))
.unwrap();
receiver.recv().unwrap().map(DOMString::from)
}
// https://html.spec.whatwg.org/multipage/#dom-storage-getitem
fn GetItem(&self, name: DOMString) -> Option<DOMString> {
let (sender, receiver) = ipc::channel().unwrap();
let name = String::from(name);
let msg = StorageThreadMsg::GetItem(sender, self.get_url(), self.storage_type, name);
self.get_storage_thread().send(msg).unwrap();
receiver.recv().unwrap().map(DOMString::from)
}
// https://html.spec.whatwg.org/multipage/#dom-storage-setitem
fn SetItem(&self, name: DOMString, value: DOMString) -> ErrorResult {
let (sender, receiver) = ipc::channel().unwrap();
let name = String::from(name);
let value = String::from(value);
let msg = StorageThreadMsg::SetItem(sender, self.get_url(), self.storage_type, name.clone(), value.clone());
self.get_storage_thread().send(msg).unwrap();
match receiver.recv().unwrap() {
Err(_) => Err(Error::QuotaExceeded),
Ok((changed, old_value)) => {
if changed {
self.broadcast_change_notification(Some(name), old_value, Some(value));
}
Ok(())
}
}
}
// https://html.spec.whatwg.org/multipage/#dom-storage-removeitem
fn RemoveItem(&self, name: DOMString) {
let (sender, receiver) = ipc::channel().unwrap();
let name = String::from(name);
let msg = StorageThreadMsg::RemoveItem(sender, self.get_url(), self.storage_type, name.clone());
self.get_storage_thread().send(msg).unwrap();
if let Some(old_value) = receiver.recv().unwrap() {
self.broadcast_change_notification(Some(name), Some(old_value), None);
}
}
// https://html.spec.whatwg.org/multipage/#dom-storage-clear
fn Clear(&self) {
let (sender, receiver) = ipc::channel().unwrap();
self.get_storage_thread().send(StorageThreadMsg::Clear(sender, self.get_url(), self.storage_type)).unwrap();
if receiver.recv().unwrap() {
self.broadcast_change_notification(None, None, None);
}
}
// https://html.spec.whatwg.org/multipage/#the-storage-interface:supported-property-names
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
let (sender, receiver) = ipc::channel().unwrap();
self.get_storage_thread().send(StorageThreadMsg::Keys(sender, self.get_url(), self.storage_type)).unwrap();
receiver.recv()
.unwrap()
.into_iter()
.map(DOMString::from)
.collect()
}
// check-tidy: no specs after this line
fn NamedGetter(&self, name: DOMString) -> Option<DOMString> {
self.GetItem(name)
}
fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
self.SetItem(name, value)
}
fn NamedDeleter(&self, name: DOMString) {
self.RemoveItem(name);
}
}
impl Storage {
/// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
fn broadcast_change_notification(&self, key: Option<String>, old_value: Option<String>,
new_value: Option<String>) {
let pipeline_id = self.global().pipeline_id();
let storage = self.storage_type;
let url = self.get_url();
let msg = ScriptMsg::BroadcastStorageEvent(pipeline_id, storage, url, key, old_value, new_value);
self.global().constellation_chan().send(msg).unwrap();
}
/// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
pub fn queue_storage_event(&self, url: ServoUrl,
key: Option<String>, old_value: Option<String>, new_value: Option<String>) {
let global = self.global();
let window = global.as_window();
let task_source = window.dom_manipulation_task_source();
let trusted_storage = Trusted::new(self);
task_source
.queue(
box StorageEventRunnable::new(trusted_storage, url, key, old_value, new_value), &global)
.unwrap();
}
}
pub struct StorageEventRunnable {
element: Trusted<Storage>,
url: ServoUrl,
key: Option<String>,
old_value: Option<String>,
new_value: Option<String>
}
impl StorageEventRunnable {
fn new(storage: Trusted<Storage>, url: ServoUrl,
key: Option<String>, old_value: Option<String>, new_value: Option<String>) -> StorageEventRunnable {
StorageEventRunnable { element: storage, url: url, key: key, old_value: old_value, new_value: new_value }
}
}
impl Runnable for StorageEventRunnable {
fn name(&self) -> &'static str { "StorageEventRunnable" }
fn main_thread_handler(self: Box<StorageEventRunnable>, _: &ScriptThread) {
let this = *self;
let storage = this.element.root();
let global = storage.global();
let window = global.as_window();
let storage_event = StorageEvent::new(
&window,
atom!("storage"),
EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
this.key.map(DOMString::from), this.old_value.map(DOMString::from), this.new_value.map(DOMString::from),
DOMString::from(this.url.into_string()),
Some(&storage)
);
storage_event.upcast::<Event>().fire(window.upcast());
}
}