Make stylesheets block page load.

This commit is contained in:
Josh Matthews 2014-10-17 11:11:46 -04:00
parent 7f0706ed42
commit 32a89c9455
10 changed files with 106 additions and 30 deletions

View file

@ -7,11 +7,10 @@
use script_task::{ScriptMsg, ScriptChan};
use msg::constellation_msg::{PipelineId};
use net_traits::{LoadResponse, Metadata, load_whole_resource, ResourceTask};
use net_traits::{ControlMsg, LoadData, LoadConsumer};
use net_traits::{LoadResponse, Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad};
use url::Url;
use std::sync::mpsc::{Receiver, channel};
use std::sync::mpsc::Receiver;
#[jstraceable]
#[derive(PartialEq, Clone)]
@ -69,15 +68,21 @@ impl DocumentLoader {
}
}
pub fn load_async(&mut self, load: LoadType) -> Receiver<LoadResponse> {
let (tx, rx) = channel();
/// Create a new pending network request, which can be initiated at some point in
/// the future.
pub fn prep_async_load(&mut self, load: LoadType) -> PendingAsyncLoad {
self.blocking_loads.push(load.clone());
let pipeline = self.notifier_data.as_ref().map(|data| data.pipeline);
let load_data = LoadData::new(load.url().clone(), pipeline);
self.resource_task.send(ControlMsg::Load(load_data, LoadConsumer::Channel(tx))).unwrap();
rx
PendingAsyncLoad::new(self.resource_task.clone(), load.url().clone(), pipeline)
}
/// Create and initiate a new network request.
pub fn load_async(&mut self, load: LoadType) -> Receiver<LoadResponse> {
let pending = self.prep_async_load(load);
pending.load()
}
/// Create, initiate, and await the response for a new network request.
pub fn load_sync(&mut self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> {
self.blocking_loads.push(load.clone());
let result = load_whole_resource(&self.resource_task, load.url().clone());
@ -85,6 +90,7 @@ impl DocumentLoader {
result
}
/// Mark an in-progress network request complete.
pub fn finish_load(&mut self, load: LoadType) {
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == load);
self.blocking_loads.remove(idx.expect("unknown completed load"));

View file

@ -72,7 +72,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyMod
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
use net_traits::CookieSource::NonHTTP;
use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
use net_traits::{Metadata, LoadResponse};
use net_traits::{Metadata, LoadResponse, PendingAsyncLoad};
use script_task::Runnable;
use script_traits::{MouseButton, UntrustedNodeAddress};
use util::opts;
@ -260,6 +260,7 @@ pub trait DocumentHelpers<'a> {
fn cancel_animation_frame(self, ident: i32);
/// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
fn invoke_animation_callbacks(self);
fn prep_async_load(self, load: LoadType) -> PendingAsyncLoad;
fn load_async(self, load: LoadType) -> Receiver<LoadResponse>;
fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String>;
fn finish_load(self, load: LoadType);
@ -884,6 +885,11 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
}
}
fn prep_async_load(self, load: LoadType) -> PendingAsyncLoad {
let mut loader = self.loader.borrow_mut();
loader.prep_async_load(load)
}
fn load_async(self, load: LoadType) -> Receiver<LoadResponse> {
let mut loader = self.loader.borrow_mut();
loader.load_async(load)

View file

@ -2,15 +2,17 @@
* 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 document_loader::LoadType;
use dom::attr::{Attr, AttrValue};
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary};
use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::document::Document;
use dom::document::{Document, DocumentHelpers};
use dom::domtokenlist::DOMTokenList;
use dom::element::{AttributeHandlers, Element};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -149,8 +151,10 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
let mut css_parser = CssParser::new(&mq_str);
let media = parse_media_query_list(&mut css_parser);
let doc = window.Document().root();
let pending = doc.r().prep_async_load(LoadType::Stylesheet(url.clone()));
let LayoutChan(ref layout_chan) = window.layout_chan();
layout_chan.send(Msg::LoadStylesheet(url, media)).unwrap();
layout_chan.send(Msg::LoadStylesheet(url, media, pending)).unwrap();
}
Err(e) => debug!("Parsing url {} failed: {}", href, e)
}

View file

@ -12,6 +12,7 @@ use geom::point::Point2D;
use geom::rect::Rect;
use libc::uintptr_t;
use msg::constellation_msg::{PipelineExitType, WindowSizeData};
use net_traits::PendingAsyncLoad;
use profile_traits::mem::{Reporter, ReportsChan};
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress};
use std::any::Any;
@ -30,7 +31,7 @@ pub enum Msg {
AddStylesheet(Stylesheet, MediaQueryList),
/// Adds the given stylesheet to the document.
LoadStylesheet(Url, MediaQueryList),
LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad),
/// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded.
SetQuirksMode,

View file

@ -19,7 +19,7 @@
#![allow(unsafe_code)]
use document_loader::{DocumentLoader, NotifierData};
use document_loader::{LoadType, DocumentLoader, NotifierData};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
@ -731,6 +731,8 @@ impl ScriptTask {
self.handle_webdriver_msg(pipeline_id, msg),
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
self.handle_tick_all_animations(pipeline_id),
ConstellationControlMsg::StylesheetLoadComplete(id, url) =>
self.handle_resource_loaded(id, LoadType::Stylesheet(url)),
}
}
@ -839,6 +841,12 @@ impl ScriptTask {
}
/// Handle a request to load a page in a new child frame of an existing page.
fn handle_resource_loaded(&self, pipeline: PipelineId, load: LoadType) {
let page = get_page(&self.root_page(), pipeline);
let doc = page.document().root();
doc.r().finish_load(load);
}
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
let NewLayoutInfo {
containing_pipeline_id,