Auto merge of #11716 - izgzhen:impl-blob-url-dom, r=Manishearth

Implement Blob URL's DOM interfaces

r? @Manishearth

Implement the two functions in `URL` to create/revoke Blob URLs, and related code to approximate our proposed design to make things work together.

<!-- Please describe your changes on the following line: -->

---
<!-- 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 part of #10539, related to #11131

<!-- Either: -->
- [x] There are tests for these changes OR

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

<!-- 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/11716)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-06-17 07:26:16 -05:00 committed by GitHub
commit 0c9d0eb685
17 changed files with 146 additions and 97 deletions

View file

@ -3,18 +3,25 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::URLBinding::{self, URLMethods};
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
use dom::blob::Blob;
use dom::urlhelper::UrlHelper;
use dom::urlsearchparams::URLSearchParams;
use ipc_channel::ipc;
use net_traits::IpcSend;
use net_traits::blob_url_store::{BlobURLStoreEntry, BlobURLStoreMsg, parse_blob_url};
use net_traits::filemanager_thread::FileManagerThreadMsg;
use std::borrow::ToOwned;
use std::default::Default;
use url::quirks::domain_to_unicode;
use url::{Host, Url};
use uuid::Uuid;
// https://url.spec.whatwg.org/#url
#[dom_struct]
@ -105,6 +112,90 @@ impl URL {
pub fn DomainToUnicode(_: GlobalRef, origin: USVString) -> USVString {
USVString(domain_to_unicode(&origin.0))
}
// https://w3c.github.io/FileAPI/#dfn-createObjectURL
pub fn CreateObjectURL(global: GlobalRef, blob: &Blob) -> DOMString {
/// XXX: Second field is an unicode-serialized Origin, it is a temporary workaround
/// and should not be trusted. See issue https://github.com/servo/servo/issues/11722
let origin = global.get_url().origin().unicode_serialization();
if blob.IsClosed() {
// Generate a dummy id
let id = Uuid::new_v4().simple().to_string();
return DOMString::from(URL::unicode_serialization_blob_url(&origin, &id));
}
let filemanager = global.resource_threads().sender();
let slice = blob.get_slice_or_empty();
let bytes = slice.get_bytes();
let entry = BlobURLStoreEntry {
type_string: blob.Type().to_string(),
filename: None, // XXX: the filename is currently only in File object now
size: blob.Size(),
bytes: bytes.to_vec(),
};
let (tx, rx) = ipc::channel().unwrap();
let msg = BlobURLStoreMsg::AddEntry(entry, origin.clone(), tx);
let _ = filemanager.send(FileManagerThreadMsg::BlobURLStoreMsg(msg));
match rx.recv().unwrap() {
Ok(id) => {
DOMString::from(URL::unicode_serialization_blob_url(&origin, &id))
}
Err(_) => {
// Generate a dummy id
let id = Uuid::new_v4().simple().to_string();
DOMString::from(URL::unicode_serialization_blob_url(&origin, &id))
}
}
}
// https://w3c.github.io/FileAPI/#dfn-revokeObjectURL
pub fn RevokeObjectURL(global: GlobalRef, url: DOMString) {
/*
If the url refers to a Blob that has a readability state of CLOSED OR
if the value provided for the url argument is not a Blob URL, OR
if the value provided for the url argument does not have an entry in the Blob URL Store,
this method call does nothing. User agents may display a message on the error console.
NOTE: The first step is unnecessary, since closed blobs do not exist in the store
*/
match Url::parse(&url) {
Ok(url) => match parse_blob_url(&url) {
Some((id, _)) => {
let filemanager = global.resource_threads().sender();
let msg = BlobURLStoreMsg::DeleteEntry(id.simple().to_string());
let _ = filemanager.send(FileManagerThreadMsg::BlobURLStoreMsg(msg));
}
None => {}
},
Err(_) => {}
}
}
// https://w3c.github.io/FileAPI/#unicodeSerializationOfBlobURL
fn unicode_serialization_blob_url(origin: &str, id: &str) -> String {
// Step 1, 2
let mut result = "blob:".to_string();
// Step 3
result.push_str(origin);
// Step 4
result.push('/');
// Step 5
result.push_str(id);
result
}
}
impl URLMethods for URL {

View file

@ -23,6 +23,11 @@ interface URL {
readonly attribute URLSearchParams searchParams;
attribute USVString hash;
// https://w3c.github.io/FileAPI/#creating-revoking
static DOMString createObjectURL(Blob blob);
// static DOMString createFor(Blob blob);
static void revokeObjectURL(DOMString url);
// This is only doing as well as gecko right now.
// https://github.com/servo/servo/issues/7590 is on file for
// adding attribute stringifier support.

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use app_units::Au;
use blob_url_store::BlobURLStore;
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType, WorkerId};
use dom::bindings::callback::ExceptionHandling;
use dom::bindings::cell::DOMRefCell;
@ -167,9 +166,6 @@ pub struct Window {
scheduler_chan: IpcSender<TimerEventRequest>,
timers: OneshotTimers,
/// Blob URL store
blob_url_store: DOMRefCell<BlobURLStore>,
next_worker_id: Cell<WorkerId>,
/// For sending messages to the memory profiler.
@ -1641,7 +1637,6 @@ impl Window {
console: Default::default(),
crypto: Default::default(),
navigator: Default::default(),
blob_url_store: DOMRefCell::new(BlobURLStore::new()),
image_cache_thread: image_cache_thread,
mem_profiler_chan: mem_profiler_chan,
time_profiler_chan: time_profiler_chan,

View file

@ -147,7 +147,10 @@ impl WorkerMethods for Worker {
fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
let data = try!(StructuredCloneData::write(cx, message));
let address = Trusted::new(self);
self.sender.send((address, WorkerScriptMsg::DOMMessage(data))).unwrap();
// NOTE: step 9 of https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage
// indicates that a nonexistent communication channel should result in a silent error.
let _ = self.sender.send((address, WorkerScriptMsg::DOMMessage(data)));
Ok(())
}

View file

@ -2,9 +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 blob_url_store::BlobURLStore;
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId, DevtoolsPageInfo};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
@ -115,8 +113,6 @@ pub struct WorkerGlobalScope {
console: MutNullableHeap<JS<Console>>,
crypto: MutNullableHeap<JS<Crypto>>,
timers: OneshotTimers,
/// Blob URL store
blob_url_store: DOMRefCell<BlobURLStore>,
#[ignore_heap_size_of = "Defined in std"]
mem_profiler_chan: mem::ProfilerChan,
@ -177,7 +173,6 @@ impl WorkerGlobalScope {
console: Default::default(),
crypto: Default::default(),
timers: OneshotTimers::new(timer_event_chan, init.scheduler_chan.clone()),
blob_url_store: DOMRefCell::new(BlobURLStore::new()),
mem_profiler_chan: init.mem_profiler_chan,
time_profiler_chan: init.time_profiler_chan,
to_devtools_sender: init.to_devtools_sender,