Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DO NOT MERGE] Initiate image loads in the script thread #14781

Closed
wants to merge 8 commits into from

Extract layout image request into separate file. Do not block the doc…

…ument load event.
  • Loading branch information
jdm committed Jan 11, 2017
commit bf2505fc691b920af17fdcda376e691081cd669e
@@ -116,6 +116,13 @@ impl DocumentLoader {
request: RequestInit,
fetch_target: IpcSender<FetchResponseMsg>) {
self.add_blocking_load(load);
self.fetch_async_background(request, fetch_target);
}

/// Initiate a new fetch that does not block the document load event.
pub fn fetch_async_background(&mut self,
request: RequestInit,
fetch_target: IpcSender<FetchResponseMsg>) {
self.resource_threads.sender().send(CoreResourceMsg::Fetch(request, fetch_target)).unwrap();
}

@@ -6,7 +6,6 @@ use app_units::Au;
use bluetooth_traits::BluetoothRequest;
use cssparser::Parser;
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
use document_loader::LoadType;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
@@ -40,7 +39,7 @@ use dom::location::Location;
use dom::mediaquerylist::{MediaQueryList, WeakMediaQueryListVec};
use dom::messageevent::MessageEvent;
use dom::navigator::Navigator;
use dom::node::{Node, from_untrusted_node_address, window_from_node, document_from_node, NodeDamage};
use dom::node::{Node, from_untrusted_node_address, window_from_node, NodeDamage};
use dom::performance::Performance;
use dom::promise::Promise;
use dom::screen::Screen;
@@ -55,14 +54,12 @@ use js::jsapi::{HandleObject, HandleValue, JSAutoCompartment, JSContext};
use js::jsapi::{JS_GC, JS_GetRuntime, SetWindowProxy};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use layout_image::fetch_image_for_layout;
use msg::constellation_msg::{FrameType, PipelineId};
use net_traits::{FetchResponseMsg, NetworkError};
use net_traits::{ResourceThreads, ReferrerPolicy, FetchResponseListener, FetchMetadata};
use net_traits::{ResourceThreads, ReferrerPolicy};
use net_traits::image_cache_thread::{ImageResponder, ImageResponse};
use net_traits::image_cache_thread::{PendingImageResponse, ImageCacheThread, PendingImageId};
use net_traits::request::{Type as RequestType, RequestInit as FetchRequestInit};
use net_traits::storage_thread::StorageType;
use network_listener::{NetworkListener, PreInvoke};
use num_traits::ToPrimitive;
use open;
use origin::Origin;
@@ -1842,69 +1839,3 @@ impl Runnable for PostMessageHandler {
message.handle());
}
}

struct LayoutImageContext {
node: Trusted<Node>,
id: PendingImageId,
url: ServoUrl,
cache: ImageCacheThread,
}

impl FetchResponseListener for LayoutImageContext {
fn process_request_body(&mut self) {}
fn process_request_eof(&mut self) {}
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
self.cache.notify_pending_response(
self.id,
FetchResponseMsg::ProcessResponse(metadata));
}

fn process_response_chunk(&mut self, payload: Vec<u8>) {
self.cache.notify_pending_response(
self.id,
FetchResponseMsg::ProcessResponseChunk(payload));
}

fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
let node = self.node.root();
let document = document_from_node(&*node);
self.cache.notify_pending_response(self.id,
FetchResponseMsg::ProcessResponseEOF(response));
document.finish_load(LoadType::Image(self.url.clone()));
}
}

impl PreInvoke for LayoutImageContext {}

fn fetch_image_for_layout(url: ServoUrl, node: &Node, id: PendingImageId, cache: ImageCacheThread) {
let context = Arc::new(Mutex::new(LayoutImageContext {
node: Trusted::new(node),
id: id,
url: url.clone(),
cache: cache,
}));

let document = document_from_node(node);
let window = window_from_node(node);

let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
task_source: window.networking_task_source(),
wrapper: Some(window.get_runnable_wrapper()),
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
listener.notify_fetch(message.to().unwrap());
});

let request = FetchRequestInit {
url: url.clone(),
origin: document.url().clone(),
type_: RequestType::Image,
pipeline_id: Some(document.global().pipeline_id()),
.. FetchRequestInit::default()
};

//XXXjdm should not block load event
document.fetch_async(LoadType::Image(url), request, action_sender);
}
@@ -0,0 +1,81 @@
/* 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/. */

//! Infrastructure to initiate network requests for images needed by the layout
//! thread. The script thread needs to be responsible for them because there's
//! no guarantee that the responsible nodes will still exist in the future if the
//! layout thread holds on to them during asynchronous operations.

use dom::bindings::reflector::DomObject;
use dom::node::{Node, document_from_node, window_from_node};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::{FetchResponseMsg, FetchResponseListener, FetchMetadata, NetworkError};
use net_traits::image_cache_thread::{ImageCacheThread, PendingImageId};
use net_traits::request::{Type as RequestType, RequestInit as FetchRequestInit};
use network_listener::{NetworkListener, PreInvoke};
use servo_url::ServoUrl;
use std::sync::{Arc, Mutex};

struct LayoutImageContext {
id: PendingImageId,
cache: ImageCacheThread,
}

impl FetchResponseListener for LayoutImageContext {
fn process_request_body(&mut self) {}
fn process_request_eof(&mut self) {}
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
self.cache.notify_pending_response(
self.id,
FetchResponseMsg::ProcessResponse(metadata));
}

fn process_response_chunk(&mut self, payload: Vec<u8>) {
self.cache.notify_pending_response(
self.id,
FetchResponseMsg::ProcessResponseChunk(payload));
}

fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
self.cache.notify_pending_response(self.id,
FetchResponseMsg::ProcessResponseEOF(response));
}
}

impl PreInvoke for LayoutImageContext {}

pub fn fetch_image_for_layout(url: ServoUrl,
node: &Node,
id: PendingImageId,
cache: ImageCacheThread) {
let context = Arc::new(Mutex::new(LayoutImageContext {
id: id,
cache: cache,
}));

let document = document_from_node(node);
let window = window_from_node(node);

let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
task_source: window.networking_task_source(),
wrapper: Some(window.get_runnable_wrapper()),
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
listener.notify_fetch(message.to().unwrap());
});

let request = FetchRequestInit {
url: url,
origin: document.url().clone(),
type_: RequestType::Image,
pipeline_id: Some(document.global().pipeline_id()),
.. FetchRequestInit::default()
};

// Layout image loads do not delay the document load event.
document.mut_loader().fetch_async_background(request, action_sender);
}
@@ -108,6 +108,7 @@ pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
mod layout_image;
pub mod layout_wrapper;
mod mem;
mod network_listener;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.