mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Propagate privacy information of iframes to corresponding pipelines. Make iframes of differing privacy values be considered cross-origin.
Make the constellation hand out separate private and public channels for the pipeline content to communicate with the resource thread as necessary.
This commit is contained in:
parent
a5778fb5da
commit
7e2b4d163b
14 changed files with 294 additions and 138 deletions
|
@ -108,7 +108,10 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
compositor_proxy: Box<CompositorProxy>,
|
compositor_proxy: Box<CompositorProxy>,
|
||||||
|
|
||||||
/// Channels through which messages can be sent to the resource-related threads.
|
/// Channels through which messages can be sent to the resource-related threads.
|
||||||
resource_threads: ResourceThreads,
|
public_resource_threads: ResourceThreads,
|
||||||
|
|
||||||
|
/// Channels through which messages can be sent to the resource-related threads.
|
||||||
|
private_resource_threads: ResourceThreads,
|
||||||
|
|
||||||
/// A channel through which messages can be sent to the image cache thread.
|
/// A channel through which messages can be sent to the image cache thread.
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
|
@ -201,7 +204,9 @@ pub struct InitialConstellationState {
|
||||||
/// A channel to the font cache thread.
|
/// A channel to the font cache thread.
|
||||||
pub font_cache_thread: FontCacheThread,
|
pub font_cache_thread: FontCacheThread,
|
||||||
/// A channel to the resource thread.
|
/// A channel to the resource thread.
|
||||||
pub resource_threads: ResourceThreads,
|
pub public_resource_threads: ResourceThreads,
|
||||||
|
/// A channel to the resource thread.
|
||||||
|
pub private_resource_threads: ResourceThreads,
|
||||||
/// A channel to the time profiler thread.
|
/// A channel to the time profiler thread.
|
||||||
pub time_profiler_chan: time::ProfilerChan,
|
pub time_profiler_chan: time::ProfilerChan,
|
||||||
/// A channel to the memory profiler thread.
|
/// A channel to the memory profiler thread.
|
||||||
|
@ -331,7 +336,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
compositor_proxy: state.compositor_proxy,
|
compositor_proxy: state.compositor_proxy,
|
||||||
devtools_chan: state.devtools_chan,
|
devtools_chan: state.devtools_chan,
|
||||||
bluetooth_thread: state.bluetooth_thread,
|
bluetooth_thread: state.bluetooth_thread,
|
||||||
resource_threads: state.resource_threads,
|
public_resource_threads: state.public_resource_threads,
|
||||||
|
private_resource_threads: state.private_resource_threads,
|
||||||
image_cache_thread: state.image_cache_thread,
|
image_cache_thread: state.image_cache_thread,
|
||||||
font_cache_thread: state.font_cache_thread,
|
font_cache_thread: state.font_cache_thread,
|
||||||
pipelines: HashMap::new(),
|
pipelines: HashMap::new(),
|
||||||
|
@ -404,9 +410,16 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
parent_info: Option<(PipelineId, SubpageId, FrameType)>,
|
parent_info: Option<(PipelineId, SubpageId, FrameType)>,
|
||||||
initial_window_size: Option<TypedSize2D<PagePx, f32>>,
|
initial_window_size: Option<TypedSize2D<PagePx, f32>>,
|
||||||
script_channel: Option<IpcSender<ConstellationControlMsg>>,
|
script_channel: Option<IpcSender<ConstellationControlMsg>>,
|
||||||
load_data: LoadData) {
|
load_data: LoadData,
|
||||||
|
is_private: bool) {
|
||||||
if self.shutting_down { return; }
|
if self.shutting_down { return; }
|
||||||
|
|
||||||
|
let resource_threads = if is_private {
|
||||||
|
self.private_resource_threads.clone()
|
||||||
|
} else {
|
||||||
|
self.public_resource_threads.clone()
|
||||||
|
};
|
||||||
|
|
||||||
let parent_visibility = if let Some((parent_pipeline_id, _, _)) = parent_info {
|
let parent_visibility = if let Some((parent_pipeline_id, _, _)) = parent_info {
|
||||||
self.pipelines.get(&parent_pipeline_id).map(|pipeline| pipeline.visible)
|
self.pipelines.get(&parent_pipeline_id).map(|pipeline| pipeline.visible)
|
||||||
} else {
|
} else {
|
||||||
|
@ -425,7 +438,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
bluetooth_thread: self.bluetooth_thread.clone(),
|
bluetooth_thread: self.bluetooth_thread.clone(),
|
||||||
image_cache_thread: self.image_cache_thread.clone(),
|
image_cache_thread: self.image_cache_thread.clone(),
|
||||||
font_cache_thread: self.font_cache_thread.clone(),
|
font_cache_thread: self.font_cache_thread.clone(),
|
||||||
resource_threads: self.resource_threads.clone(),
|
resource_threads: resource_threads,
|
||||||
time_profiler_chan: self.time_profiler_chan.clone(),
|
time_profiler_chan: self.time_profiler_chan.clone(),
|
||||||
mem_profiler_chan: self.mem_profiler_chan.clone(),
|
mem_profiler_chan: self.mem_profiler_chan.clone(),
|
||||||
window_size: initial_window_size,
|
window_size: initial_window_size,
|
||||||
|
@ -435,6 +448,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
pipeline_namespace_id: self.next_pipeline_namespace_id(),
|
pipeline_namespace_id: self.next_pipeline_namespace_id(),
|
||||||
parent_visibility: parent_visibility,
|
parent_visibility: parent_visibility,
|
||||||
webrender_api_sender: self.webrender_api_sender.clone(),
|
webrender_api_sender: self.webrender_api_sender.clone(),
|
||||||
|
is_private: is_private,
|
||||||
});
|
});
|
||||||
|
|
||||||
let (pipeline, child_process) = match result {
|
let (pipeline, child_process) = match result {
|
||||||
|
@ -850,7 +864,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.image_cache_thread.exit();
|
self.image_cache_thread.exit();
|
||||||
|
|
||||||
debug!("Exiting core resource threads.");
|
debug!("Exiting core resource threads.");
|
||||||
if let Err(e) = self.resource_threads.send(net_traits::CoreResourceMsg::Exit(core_sender)) {
|
if let Err(e) = self.public_resource_threads.send(net_traits::CoreResourceMsg::Exit(core_sender)) {
|
||||||
warn!("Exit resource thread failed ({})", e);
|
warn!("Exit resource thread failed ({})", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,12 +877,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Exiting storage resource threads.");
|
debug!("Exiting storage resource threads.");
|
||||||
if let Err(e) = self.resource_threads.send(StorageThreadMsg::Exit(storage_sender)) {
|
if let Err(e) = self.public_resource_threads.send(StorageThreadMsg::Exit(storage_sender)) {
|
||||||
warn!("Exit storage thread failed ({})", e);
|
warn!("Exit storage thread failed ({})", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Exiting file manager resource threads.");
|
debug!("Exiting file manager resource threads.");
|
||||||
if let Err(e) = self.resource_threads.send(FileManagerThreadMsg::Exit) {
|
if let Err(e) = self.public_resource_threads.send(FileManagerThreadMsg::Exit) {
|
||||||
warn!("Exit storage thread failed ({})", e);
|
warn!("Exit storage thread failed ({})", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +965,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
let new_pipeline_id = PipelineId::new();
|
let new_pipeline_id = PipelineId::new();
|
||||||
let load_data = LoadData::new(failure_url, None, None);
|
let load_data = LoadData::new(failure_url, None, None);
|
||||||
self.new_pipeline(new_pipeline_id, parent_info, window_size, None, load_data);
|
self.new_pipeline(new_pipeline_id, parent_info, window_size, None, load_data, false);
|
||||||
|
|
||||||
self.push_pending_frame(new_pipeline_id, Some(pipeline_id));
|
self.push_pending_frame(new_pipeline_id, Some(pipeline_id));
|
||||||
|
|
||||||
|
@ -965,7 +979,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let root_pipeline_id = PipelineId::new();
|
let root_pipeline_id = PipelineId::new();
|
||||||
debug_assert!(PipelineId::fake_root_pipeline_id() == root_pipeline_id);
|
debug_assert!(PipelineId::fake_root_pipeline_id() == root_pipeline_id);
|
||||||
self.new_pipeline(root_pipeline_id, None, Some(window_size), None,
|
self.new_pipeline(root_pipeline_id, None, Some(window_size), None,
|
||||||
LoadData::new(url.clone(), None, None));
|
LoadData::new(url.clone(), None, None), false);
|
||||||
self.handle_load_start_msg(&root_pipeline_id);
|
self.handle_load_start_msg(&root_pipeline_id);
|
||||||
self.push_pending_frame(root_pipeline_id, None);
|
self.push_pending_frame(root_pipeline_id, None);
|
||||||
self.compositor_proxy.send(ToCompositorMsg::ChangePageUrl(root_pipeline_id, url));
|
self.compositor_proxy.send(ToCompositorMsg::ChangePageUrl(root_pipeline_id, url));
|
||||||
|
@ -1030,7 +1044,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
.and_then(|old_subpage_id| self.subpage_map.get(&(load_info.containing_pipeline_id, old_subpage_id)))
|
.and_then(|old_subpage_id| self.subpage_map.get(&(load_info.containing_pipeline_id, old_subpage_id)))
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
let (load_data, script_chan, window_size) = {
|
let (load_data, script_chan, window_size, is_private) = {
|
||||||
let old_pipeline = old_pipeline_id
|
let old_pipeline = old_pipeline_id
|
||||||
.and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id));
|
.and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id));
|
||||||
|
|
||||||
|
@ -1054,11 +1068,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// then reuse the script thread in creating the new pipeline
|
// then reuse the script thread in creating the new pipeline
|
||||||
let source_url = &source_pipeline.url;
|
let source_url = &source_pipeline.url;
|
||||||
|
|
||||||
|
let is_private = load_info.is_private || source_pipeline.is_private;
|
||||||
|
|
||||||
// FIXME(#10968): this should probably match the origin check in
|
// FIXME(#10968): this should probably match the origin check in
|
||||||
// HTMLIFrameElement::contentDocument.
|
// HTMLIFrameElement::contentDocument.
|
||||||
let same_script = source_url.host() == load_data.url.host() &&
|
let same_script = source_url.host() == load_data.url.host() &&
|
||||||
source_url.port() == load_data.url.port() &&
|
source_url.port() == load_data.url.port() &&
|
||||||
load_info.sandbox == IFrameSandboxState::IFrameUnsandboxed;
|
load_info.sandbox == IFrameSandboxState::IFrameUnsandboxed &&
|
||||||
|
source_pipeline.is_private == is_private;
|
||||||
|
|
||||||
// Reuse the script thread if the URL is same-origin
|
// Reuse the script thread if the URL is same-origin
|
||||||
let script_chan = if same_script {
|
let script_chan = if same_script {
|
||||||
|
@ -1077,16 +1094,17 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
old_pipeline.freeze();
|
old_pipeline.freeze();
|
||||||
}
|
}
|
||||||
|
|
||||||
(load_data, script_chan, window_size)
|
(load_data, script_chan, window_size, is_private)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Create the new pipeline, attached to the parent and push to pending frames
|
// Create the new pipeline, attached to the parent and push to pending frames
|
||||||
self.new_pipeline(load_info.new_pipeline_id,
|
self.new_pipeline(load_info.new_pipeline_id,
|
||||||
Some((load_info.containing_pipeline_id, load_info.new_subpage_id, load_info.frame_type)),
|
Some((load_info.containing_pipeline_id, load_info.new_subpage_id, load_info.frame_type)),
|
||||||
window_size,
|
window_size,
|
||||||
script_chan,
|
script_chan,
|
||||||
load_data);
|
load_data,
|
||||||
|
is_private);
|
||||||
|
|
||||||
self.subpage_map.insert((load_info.containing_pipeline_id, load_info.new_subpage_id),
|
self.subpage_map.insert((load_info.containing_pipeline_id, load_info.new_subpage_id),
|
||||||
load_info.new_pipeline_id);
|
load_info.new_pipeline_id);
|
||||||
|
@ -1217,7 +1235,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
// Create the new pipeline
|
// Create the new pipeline
|
||||||
let window_size = self.pipelines.get(&source_id).and_then(|source| source.size);
|
let window_size = self.pipelines.get(&source_id).and_then(|source| source.size);
|
||||||
let new_pipeline_id = PipelineId::new();
|
let new_pipeline_id = PipelineId::new();
|
||||||
self.new_pipeline(new_pipeline_id, None, window_size, None, load_data);
|
self.new_pipeline(new_pipeline_id, None, window_size, None, load_data, false);
|
||||||
self.push_pending_frame(new_pipeline_id, Some(source_id));
|
self.push_pending_frame(new_pipeline_id, Some(source_id));
|
||||||
|
|
||||||
// Send message to ScriptThread that will suspend all timers
|
// Send message to ScriptThread that will suspend all timers
|
||||||
|
@ -1906,25 +1924,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
ReadyToSave::Ready
|
ReadyToSave::Ready
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether the pipeline or its ancestors are private
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn check_is_pipeline_private(&self, mut pipeline_id: PipelineId) -> bool {
|
|
||||||
loop {
|
|
||||||
match self.pipelines.get(&pipeline_id) {
|
|
||||||
Some(pipeline) if pipeline.is_private => return true,
|
|
||||||
Some(pipeline) => match pipeline.parent_info {
|
|
||||||
None => return false,
|
|
||||||
Some((_, _, FrameType::MozBrowserIFrame)) => return false,
|
|
||||||
Some((parent_id, _, _)) => pipeline_id = parent_id,
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
warn!("Finding private ancestor for pipeline {} after closure.", pipeline_id);
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close a frame (and all children)
|
// Close a frame (and all children)
|
||||||
fn close_frame(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) {
|
fn close_frame(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) {
|
||||||
// Store information about the pipelines to be closed. Then close the
|
// Store information about the pipelines to be closed. Then close the
|
||||||
|
|
|
@ -64,6 +64,7 @@ pub struct Pipeline {
|
||||||
/// animations cause composites to be continually scheduled.
|
/// animations cause composites to be continually scheduled.
|
||||||
pub running_animations: bool,
|
pub running_animations: bool,
|
||||||
pub children: Vec<FrameId>,
|
pub children: Vec<FrameId>,
|
||||||
|
/// Whether this pipeline is considered distinct from public pipelines.
|
||||||
pub is_private: bool,
|
pub is_private: bool,
|
||||||
/// Whether this pipeline should be treated as visible for the purposes of scheduling and
|
/// Whether this pipeline should be treated as visible for the purposes of scheduling and
|
||||||
/// resource management.
|
/// resource management.
|
||||||
|
@ -119,6 +120,8 @@ pub struct InitialPipelineState {
|
||||||
pub parent_visibility: Option<bool>,
|
pub parent_visibility: Option<bool>,
|
||||||
/// Optional webrender api (if enabled).
|
/// Optional webrender api (if enabled).
|
||||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||||
|
/// Whether this pipeline is considered private.
|
||||||
|
pub is_private: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
|
@ -254,6 +257,7 @@ impl Pipeline {
|
||||||
pipeline_chan,
|
pipeline_chan,
|
||||||
state.compositor_proxy,
|
state.compositor_proxy,
|
||||||
chrome_to_paint_chan,
|
chrome_to_paint_chan,
|
||||||
|
state.is_private,
|
||||||
state.load_data.url,
|
state.load_data.url,
|
||||||
state.window_size,
|
state.window_size,
|
||||||
state.parent_visibility.unwrap_or(true));
|
state.parent_visibility.unwrap_or(true));
|
||||||
|
@ -269,6 +273,7 @@ impl Pipeline {
|
||||||
layout_chan: IpcSender<LayoutControlMsg>,
|
layout_chan: IpcSender<LayoutControlMsg>,
|
||||||
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
||||||
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||||
|
is_private: bool,
|
||||||
url: Url,
|
url: Url,
|
||||||
size: Option<TypedSize2D<PagePx, f32>>,
|
size: Option<TypedSize2D<PagePx, f32>>,
|
||||||
visible: bool)
|
visible: bool)
|
||||||
|
@ -285,8 +290,8 @@ impl Pipeline {
|
||||||
children: vec!(),
|
children: vec!(),
|
||||||
size: size,
|
size: size,
|
||||||
running_animations: false,
|
running_animations: false,
|
||||||
is_private: false,
|
|
||||||
visible: visible,
|
visible: visible,
|
||||||
|
is_private: is_private,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,13 @@ use http_loader::{self, HttpState};
|
||||||
use hyper::client::pool::Pool;
|
use hyper::client::pool::Pool;
|
||||||
use hyper::header::{ContentType, Header, SetCookie};
|
use hyper::header::{ContentType, Header, SetCookie};
|
||||||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender, IpcReceiverSet};
|
||||||
use mime_classifier::{ApacheBugFlag, MIMEClassifier, NoSniffFlag};
|
use mime_classifier::{ApacheBugFlag, MIMEClassifier, NoSniffFlag};
|
||||||
use net_traits::LoadContext;
|
use net_traits::LoadContext;
|
||||||
use net_traits::ProgressMsg::Done;
|
use net_traits::ProgressMsg::Done;
|
||||||
|
use net_traits::filemanager_thread::FileManagerThreadMsg;
|
||||||
use net_traits::request::{Request, RequestInit};
|
use net_traits::request::{Request, RequestInit};
|
||||||
|
use net_traits::storage_thread::StorageThreadMsg;
|
||||||
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResponseAction, CoreResourceThread};
|
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResponseAction, CoreResourceThread};
|
||||||
use net_traits::{CoreResourceMsg, CookieSource, FetchResponseMsg, FetchTaskTarget, LoadConsumer};
|
use net_traits::{CoreResourceMsg, CookieSource, FetchResponseMsg, FetchTaskTarget, LoadConsumer};
|
||||||
use net_traits::{LoadData, LoadResponse, NetworkError, ResourceId};
|
use net_traits::{LoadData, LoadResponse, NetworkError, ResourceId};
|
||||||
|
@ -56,6 +58,14 @@ pub enum ProgressSender {
|
||||||
Listener(AsyncResponseTarget),
|
Listener(AsyncResponseTarget),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ResourceGroup {
|
||||||
|
cookie_jar: Arc<RwLock<CookieStorage>>,
|
||||||
|
auth_cache: Arc<RwLock<AuthCache>>,
|
||||||
|
hsts_list: Arc<RwLock<HstsList>>,
|
||||||
|
connector: Arc<Pool<Connector>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl ProgressSender {
|
impl ProgressSender {
|
||||||
//XXXjdm return actual error
|
//XXXjdm return actual error
|
||||||
pub fn send(&self, msg: ProgressMsg) -> Result<(), ()> {
|
pub fn send(&self, msg: ProgressMsg) -> Result<(), ()> {
|
||||||
|
@ -158,89 +168,149 @@ fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a tuple of (public, private) senders to the new threads.
|
||||||
pub fn new_resource_threads(user_agent: String,
|
pub fn new_resource_threads(user_agent: String,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
profiler_chan: ProfilerChan) -> ResourceThreads {
|
profiler_chan: ProfilerChan) -> (ResourceThreads, ResourceThreads) {
|
||||||
ResourceThreads::new(new_core_resource_thread(user_agent, devtools_chan, profiler_chan),
|
let (public_core, private_core) = new_core_resource_thread(user_agent, devtools_chan, profiler_chan);
|
||||||
StorageThreadFactory::new(),
|
let storage: IpcSender<StorageThreadMsg> = StorageThreadFactory::new();
|
||||||
FileManagerThreadFactory::new(TFD_PROVIDER))
|
let filemanager: IpcSender<FileManagerThreadMsg> = FileManagerThreadFactory::new(TFD_PROVIDER);
|
||||||
|
(ResourceThreads::new(public_core, storage.clone(), filemanager.clone()),
|
||||||
|
ResourceThreads::new(private_core, storage, filemanager))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a CoreResourceThread
|
/// Create a CoreResourceThread
|
||||||
pub fn new_core_resource_thread(user_agent: String,
|
pub fn new_core_resource_thread(user_agent: String,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
profiler_chan: ProfilerChan) -> CoreResourceThread {
|
profiler_chan: ProfilerChan)
|
||||||
let hsts_preload = HstsList::from_servo_preload();
|
-> (CoreResourceThread, CoreResourceThread) {
|
||||||
let (setup_chan, setup_port) = ipc::channel().unwrap();
|
let (public_setup_chan, public_setup_port) = ipc::channel().unwrap();
|
||||||
let setup_chan_clone = setup_chan.clone();
|
let (private_setup_chan, private_setup_port) = ipc::channel().unwrap();
|
||||||
|
let public_setup_chan_clone = public_setup_chan.clone();
|
||||||
|
let private_setup_chan_clone = private_setup_chan.clone();
|
||||||
spawn_named("ResourceManager".to_owned(), move || {
|
spawn_named("ResourceManager".to_owned(), move || {
|
||||||
let resource_manager = CoreResourceManager::new(
|
let resource_manager = CoreResourceManager::new(
|
||||||
user_agent, hsts_preload, devtools_chan, profiler_chan
|
user_agent, devtools_chan, profiler_chan
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut channel_manager = ResourceChannelManager {
|
let mut channel_manager = ResourceChannelManager {
|
||||||
from_client: setup_port,
|
resource_manager: resource_manager,
|
||||||
resource_manager: resource_manager
|
|
||||||
};
|
};
|
||||||
channel_manager.start(setup_chan_clone);
|
channel_manager.start(public_setup_chan_clone,
|
||||||
|
private_setup_chan_clone,
|
||||||
|
public_setup_port,
|
||||||
|
private_setup_port);
|
||||||
});
|
});
|
||||||
setup_chan
|
(public_setup_chan, private_setup_chan)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ResourceChannelManager {
|
struct ResourceChannelManager {
|
||||||
from_client: IpcReceiver<CoreResourceMsg>,
|
resource_manager: CoreResourceManager,
|
||||||
resource_manager: CoreResourceManager
|
}
|
||||||
|
|
||||||
|
fn create_resource_groups() -> (ResourceGroup, ResourceGroup) {
|
||||||
|
let mut hsts_list = HstsList::from_servo_preload();
|
||||||
|
let mut auth_cache = AuthCache::new();
|
||||||
|
let mut cookie_jar = CookieStorage::new();
|
||||||
|
if let Some(ref config_dir) = opts::get().config_dir {
|
||||||
|
read_json_from_file(&mut auth_cache, config_dir, "auth_cache.json");
|
||||||
|
read_json_from_file(&mut hsts_list, config_dir, "hsts_list.json");
|
||||||
|
read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json");
|
||||||
|
}
|
||||||
|
let resource_group = ResourceGroup {
|
||||||
|
cookie_jar: Arc::new(RwLock::new(cookie_jar)),
|
||||||
|
auth_cache: Arc::new(RwLock::new(auth_cache)),
|
||||||
|
hsts_list: Arc::new(RwLock::new(hsts_list.clone())),
|
||||||
|
connector: create_http_connector(),
|
||||||
|
};
|
||||||
|
let private_resource_group = ResourceGroup {
|
||||||
|
cookie_jar: Arc::new(RwLock::new(CookieStorage::new())),
|
||||||
|
auth_cache: Arc::new(RwLock::new(AuthCache::new())),
|
||||||
|
hsts_list: Arc::new(RwLock::new(HstsList::new())),
|
||||||
|
connector: create_http_connector(),
|
||||||
|
};
|
||||||
|
(resource_group, private_resource_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResourceChannelManager {
|
impl ResourceChannelManager {
|
||||||
fn start(&mut self, control_sender: CoreResourceThread) {
|
#[allow(unsafe_code)]
|
||||||
loop {
|
fn start(&mut self,
|
||||||
match self.from_client.recv().unwrap() {
|
public_control_sender: CoreResourceThread,
|
||||||
CoreResourceMsg::Load(load_data, consumer, id_sender) =>
|
private_control_sender: CoreResourceThread,
|
||||||
self.resource_manager.load(load_data, consumer, id_sender, control_sender.clone()),
|
public_receiver: IpcReceiver<CoreResourceMsg>,
|
||||||
CoreResourceMsg::Fetch(init, sender) =>
|
private_receiver: IpcReceiver<CoreResourceMsg>) {
|
||||||
self.resource_manager.fetch(init, sender),
|
let (public_resource_group, private_resource_group) = create_resource_groups();
|
||||||
CoreResourceMsg::WebsocketConnect(connect, connect_data) =>
|
|
||||||
self.resource_manager.websocket_connect(connect, connect_data),
|
|
||||||
CoreResourceMsg::SetCookiesForUrl(request, cookie_list, source) =>
|
|
||||||
self.resource_manager.set_cookies_for_url(request, cookie_list, source),
|
|
||||||
CoreResourceMsg::GetCookiesForUrl(url, consumer, source) => {
|
|
||||||
let cookie_jar = &self.resource_manager.cookie_jar;
|
|
||||||
let mut cookie_jar = cookie_jar.write().unwrap();
|
|
||||||
consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap();
|
|
||||||
}
|
|
||||||
CoreResourceMsg::Cancel(res_id) => {
|
|
||||||
if let Some(cancel_sender) = self.resource_manager.cancel_load_map.get(&res_id) {
|
|
||||||
let _ = cancel_sender.send(());
|
|
||||||
}
|
|
||||||
self.resource_manager.cancel_load_map.remove(&res_id);
|
|
||||||
}
|
|
||||||
CoreResourceMsg::Synchronize(sender) => {
|
|
||||||
let _ = sender.send(());
|
|
||||||
}
|
|
||||||
CoreResourceMsg::Exit(sender) => {
|
|
||||||
if let Some(ref config_dir) = opts::get().config_dir {
|
|
||||||
match self.resource_manager.auth_cache.read() {
|
|
||||||
Ok(auth_cache) => write_json_to_file(&*auth_cache, config_dir, "auth_cache.json"),
|
|
||||||
Err(_) => warn!("Error writing auth cache to disk"),
|
|
||||||
}
|
|
||||||
match self.resource_manager.cookie_jar.read() {
|
|
||||||
Ok(jar) => write_json_to_file(&*jar, config_dir, "cookie_jar.json"),
|
|
||||||
Err(_) => warn!("Error writing cookie jar to disk"),
|
|
||||||
}
|
|
||||||
match self.resource_manager.hsts_list.read() {
|
|
||||||
Ok(hsts) => write_json_to_file(&*hsts, config_dir, "hsts_list.json"),
|
|
||||||
Err(_) => warn!("Error writing hsts list to disk"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _ = sender.send(());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let mut rx_set = IpcReceiverSet::new().unwrap();
|
||||||
|
let private_id = rx_set.add(private_receiver).unwrap();
|
||||||
|
let public_id = rx_set.add(public_receiver).unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
for (id, data) in rx_set.select().unwrap().into_iter().map(|m| m.unwrap()) {
|
||||||
|
let (group, sender) = if id == private_id {
|
||||||
|
(&private_resource_group, &private_control_sender)
|
||||||
|
} else {
|
||||||
|
assert_eq!(id, public_id);
|
||||||
|
(&public_resource_group, &public_control_sender)
|
||||||
|
};
|
||||||
|
if let Ok(msg) = data.to() {
|
||||||
|
if !self.process_msg(msg, group, &sender) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns false if the thread should exit.
|
||||||
|
fn process_msg(&mut self,
|
||||||
|
msg: CoreResourceMsg,
|
||||||
|
group: &ResourceGroup,
|
||||||
|
control_sender: &CoreResourceThread) -> bool {
|
||||||
|
match msg {
|
||||||
|
CoreResourceMsg::Load(load_data, consumer, id_sender) =>
|
||||||
|
self.resource_manager.load(load_data, consumer, id_sender, control_sender.clone(), group),
|
||||||
|
CoreResourceMsg::Fetch(init, sender) =>
|
||||||
|
self.resource_manager.fetch(init, sender, group),
|
||||||
|
CoreResourceMsg::WebsocketConnect(connect, connect_data) =>
|
||||||
|
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::GetCookiesForUrl(url, consumer, source) => {
|
||||||
|
let mut cookie_jar = group.cookie_jar.write().unwrap();
|
||||||
|
consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap();
|
||||||
|
}
|
||||||
|
CoreResourceMsg::Cancel(res_id) => {
|
||||||
|
if let Some(cancel_sender) = self.resource_manager.cancel_load_map.get(&res_id) {
|
||||||
|
let _ = cancel_sender.send(());
|
||||||
|
}
|
||||||
|
self.resource_manager.cancel_load_map.remove(&res_id);
|
||||||
|
}
|
||||||
|
CoreResourceMsg::Synchronize(sender) => {
|
||||||
|
let _ = sender.send(());
|
||||||
|
}
|
||||||
|
CoreResourceMsg::Exit(sender) => {
|
||||||
|
if let Some(ref config_dir) = opts::get().config_dir {
|
||||||
|
match group.auth_cache.read() {
|
||||||
|
Ok(auth_cache) => write_json_to_file(&*auth_cache, config_dir, "auth_cache.json"),
|
||||||
|
Err(_) => warn!("Error writing auth cache to disk"),
|
||||||
|
}
|
||||||
|
match group.cookie_jar.read() {
|
||||||
|
Ok(jar) => write_json_to_file(&*jar, config_dir, "cookie_jar.json"),
|
||||||
|
Err(_) => warn!("Error writing cookie jar to disk"),
|
||||||
|
}
|
||||||
|
match group.hsts_list.read() {
|
||||||
|
Ok(hsts) => write_json_to_file(&*hsts, config_dir, "hsts_list.json"),
|
||||||
|
Err(_) => warn!("Error writing hsts list to disk"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = sender.send(());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_json_from_file<T: Decodable>(data: &mut T, config_dir: &str, filename: &str) {
|
pub fn read_json_from_file<T: Decodable>(data: &mut T, config_dir: &str, filename: &str) {
|
||||||
|
@ -381,50 +451,37 @@ pub struct AuthCache {
|
||||||
|
|
||||||
pub struct CoreResourceManager {
|
pub struct CoreResourceManager {
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
cookie_jar: Arc<RwLock<CookieStorage>>,
|
|
||||||
auth_cache: Arc<RwLock<AuthCache>>,
|
|
||||||
mime_classifier: Arc<MIMEClassifier>,
|
mime_classifier: Arc<MIMEClassifier>,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
hsts_list: Arc<RwLock<HstsList>>,
|
|
||||||
connector: Arc<Pool<Connector>>,
|
|
||||||
cancel_load_map: HashMap<ResourceId, Sender<()>>,
|
cancel_load_map: HashMap<ResourceId, Sender<()>>,
|
||||||
next_resource_id: ResourceId,
|
next_resource_id: ResourceId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoreResourceManager {
|
impl CoreResourceManager {
|
||||||
pub fn new(user_agent: String,
|
pub fn new(user_agent: String,
|
||||||
mut hsts_list: HstsList,
|
|
||||||
devtools_channel: Option<Sender<DevtoolsControlMsg>>,
|
devtools_channel: Option<Sender<DevtoolsControlMsg>>,
|
||||||
profiler_chan: ProfilerChan) -> CoreResourceManager {
|
profiler_chan: ProfilerChan) -> CoreResourceManager {
|
||||||
let mut auth_cache = AuthCache::new();
|
|
||||||
let mut cookie_jar = CookieStorage::new();
|
|
||||||
if let Some(ref config_dir) = opts::get().config_dir {
|
|
||||||
read_json_from_file(&mut auth_cache, config_dir, "auth_cache.json");
|
|
||||||
read_json_from_file(&mut hsts_list, config_dir, "hsts_list.json");
|
|
||||||
read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json");
|
|
||||||
}
|
|
||||||
CoreResourceManager {
|
CoreResourceManager {
|
||||||
user_agent: user_agent,
|
user_agent: user_agent,
|
||||||
cookie_jar: Arc::new(RwLock::new(cookie_jar)),
|
|
||||||
auth_cache: Arc::new(RwLock::new(auth_cache)),
|
|
||||||
mime_classifier: Arc::new(MIMEClassifier::new()),
|
mime_classifier: Arc::new(MIMEClassifier::new()),
|
||||||
devtools_chan: devtools_channel,
|
devtools_chan: devtools_channel,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
hsts_list: Arc::new(RwLock::new(hsts_list)),
|
|
||||||
connector: create_http_connector(),
|
|
||||||
cancel_load_map: HashMap::new(),
|
cancel_load_map: HashMap::new(),
|
||||||
next_resource_id: ResourceId(0),
|
next_resource_id: ResourceId(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cookies_for_url(&mut self, request: Url, cookie_list: String, source: CookieSource) {
|
fn set_cookies_for_url(&mut self,
|
||||||
|
request: Url,
|
||||||
|
cookie_list: String,
|
||||||
|
source: CookieSource,
|
||||||
|
resource_group: &ResourceGroup) {
|
||||||
let header = Header::parse_header(&[cookie_list.into_bytes()]);
|
let header = Header::parse_header(&[cookie_list.into_bytes()]);
|
||||||
if let Ok(SetCookie(cookies)) = header {
|
if let Ok(SetCookie(cookies)) = header {
|
||||||
for bare_cookie in cookies {
|
for bare_cookie in cookies {
|
||||||
if let Some(cookie) = cookie::Cookie::new_wrapped(bare_cookie, &request, source) {
|
if let Some(cookie) = cookie::Cookie::new_wrapped(bare_cookie, &request, source) {
|
||||||
let cookie_jar = &self.cookie_jar;
|
let mut cookie_jar = resource_group.cookie_jar.write().unwrap();
|
||||||
let mut cookie_jar = cookie_jar.write().unwrap();
|
|
||||||
cookie_jar.push(cookie, source);
|
cookie_jar.push(cookie, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,7 +492,8 @@ impl CoreResourceManager {
|
||||||
load_data: LoadData,
|
load_data: LoadData,
|
||||||
consumer: LoadConsumer,
|
consumer: LoadConsumer,
|
||||||
id_sender: Option<IpcSender<ResourceId>>,
|
id_sender: Option<IpcSender<ResourceId>>,
|
||||||
resource_thread: CoreResourceThread) {
|
resource_thread: CoreResourceThread,
|
||||||
|
resource_grp: &ResourceGroup) {
|
||||||
fn from_factory(factory: fn(LoadData, LoadConsumer, Arc<MIMEClassifier>, CancellationListener))
|
fn from_factory(factory: fn(LoadData, LoadConsumer, Arc<MIMEClassifier>, CancellationListener))
|
||||||
-> Box<FnBox(LoadData,
|
-> Box<FnBox(LoadData,
|
||||||
LoadConsumer,
|
LoadConsumer,
|
||||||
|
@ -461,16 +519,16 @@ impl CoreResourceManager {
|
||||||
"file" => from_factory(file_loader::factory),
|
"file" => from_factory(file_loader::factory),
|
||||||
"http" | "https" | "view-source" => {
|
"http" | "https" | "view-source" => {
|
||||||
let http_state = HttpState {
|
let http_state = HttpState {
|
||||||
hsts_list: self.hsts_list.clone(),
|
|
||||||
cookie_jar: self.cookie_jar.clone(),
|
|
||||||
auth_cache: self.auth_cache.clone(),
|
|
||||||
blocked_content: BLOCKED_CONTENT_RULES.clone(),
|
blocked_content: BLOCKED_CONTENT_RULES.clone(),
|
||||||
|
hsts_list: resource_grp.hsts_list.clone(),
|
||||||
|
cookie_jar: resource_grp.cookie_jar.clone(),
|
||||||
|
auth_cache: resource_grp.auth_cache.clone()
|
||||||
};
|
};
|
||||||
http_loader::factory(self.user_agent.clone(),
|
http_loader::factory(self.user_agent.clone(),
|
||||||
http_state,
|
http_state,
|
||||||
self.devtools_chan.clone(),
|
self.devtools_chan.clone(),
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
self.connector.clone())
|
resource_grp.connector.clone())
|
||||||
},
|
},
|
||||||
"data" => from_factory(data_loader::factory),
|
"data" => from_factory(data_loader::factory),
|
||||||
"about" => from_factory(about_loader::factory),
|
"about" => from_factory(about_loader::factory),
|
||||||
|
@ -488,11 +546,14 @@ impl CoreResourceManager {
|
||||||
cancel_listener));
|
cancel_listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(&self, init: RequestInit, sender: IpcSender<FetchResponseMsg>) {
|
fn fetch(&self,
|
||||||
|
init: RequestInit,
|
||||||
|
sender: IpcSender<FetchResponseMsg>,
|
||||||
|
group: &ResourceGroup) {
|
||||||
let http_state = HttpState {
|
let http_state = HttpState {
|
||||||
hsts_list: self.hsts_list.clone(),
|
hsts_list: group.hsts_list.clone(),
|
||||||
cookie_jar: self.cookie_jar.clone(),
|
cookie_jar: group.cookie_jar.clone(),
|
||||||
auth_cache: self.auth_cache.clone(),
|
auth_cache: group.auth_cache.clone(),
|
||||||
blocked_content: BLOCKED_CONTENT_RULES.clone(),
|
blocked_content: BLOCKED_CONTENT_RULES.clone(),
|
||||||
};
|
};
|
||||||
let ua = self.user_agent.clone();
|
let ua = self.user_agent.clone();
|
||||||
|
@ -510,7 +571,8 @@ impl CoreResourceManager {
|
||||||
|
|
||||||
fn websocket_connect(&self,
|
fn websocket_connect(&self,
|
||||||
connect: WebSocketCommunicate,
|
connect: WebSocketCommunicate,
|
||||||
connect_data: WebSocketConnectData) {
|
connect_data: WebSocketConnectData,
|
||||||
websocket_loader::init(connect, connect_data, self.cookie_jar.clone());
|
resource_grp: &ResourceGroup) {
|
||||||
|
websocket_loader::init(connect, connect_data, resource_grp.cookie_jar.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use request::{Request, RequestInit};
|
use request::{Request, RequestInit};
|
||||||
use response::{HttpsState, Response};
|
use response::{HttpsState, Response};
|
||||||
use std::io::Error as IOError;
|
use std::io::Error as IOError;
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use storage_thread::StorageThreadMsg;
|
use storage_thread::StorageThreadMsg;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -649,9 +648,10 @@ pub fn unwrap_websocket_protocol(wsp: Option<&header::WebSocketProtocol>) -> Opt
|
||||||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub struct ResourceId(pub u32);
|
pub struct ResourceId(pub u32);
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum ConstellationMsg {
|
pub enum ConstellationMsg {
|
||||||
/// Queries whether a pipeline or its ancestors are private
|
/// Queries whether a pipeline or its ancestors are private
|
||||||
IsPrivate(PipelineId, Sender<bool>),
|
IsPrivate(PipelineId, IpcSender<bool>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Network errors that have to be exported out of the loaders
|
/// Network errors that have to be exported out of the loaders
|
||||||
|
|
|
@ -562,6 +562,21 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
||||||
make_getter!(Height, "height");
|
make_getter!(Height, "height");
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-dim-height
|
// https://html.spec.whatwg.org/multipage/#dom-dim-height
|
||||||
make_dimension_setter!(SetHeight, "height");
|
make_dimension_setter!(SetHeight, "height");
|
||||||
|
|
||||||
|
// check-tidy: no specs after this line
|
||||||
|
fn SetMozprivatebrowsing(&self, value: bool) {
|
||||||
|
let element = self.upcast::<Element>();
|
||||||
|
element.set_bool_attribute(&Atom::from("mozprivatebrowsing"), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Mozprivatebrowsing(&self) -> bool {
|
||||||
|
if window_from_node(self).is_mozbrowser() {
|
||||||
|
let element = self.upcast::<Element>();
|
||||||
|
element.has_attribute(&Atom::from("mozprivatebrowsing"))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLIFrameElement {
|
impl VirtualMethods for HTMLIFrameElement {
|
||||||
|
|
|
@ -33,6 +33,9 @@ partial interface HTMLIFrameElement {
|
||||||
partial interface HTMLIFrameElement {
|
partial interface HTMLIFrameElement {
|
||||||
[Func="::dom::window::Window::global_is_mozbrowser"]
|
[Func="::dom::window::Window::global_is_mozbrowser"]
|
||||||
attribute boolean mozbrowser;
|
attribute boolean mozbrowser;
|
||||||
|
|
||||||
|
[Func="::dom::window::Window::global_is_mozbrowser"]
|
||||||
|
attribute boolean mozprivatebrowsing;
|
||||||
};
|
};
|
||||||
|
|
||||||
HTMLIFrameElement implements BrowserElement;
|
HTMLIFrameElement implements BrowserElement;
|
||||||
|
|
|
@ -489,8 +489,8 @@ impl Runnable for ConnectionEstablishedTask {
|
||||||
for cookie in cookies.iter() {
|
for cookie in cookies.iter() {
|
||||||
if let Ok(cookie_value) = String::from_utf8(cookie.clone()) {
|
if let Ok(cookie_value) = String::from_utf8(cookie.clone()) {
|
||||||
let _ = ws.global().r().core_resource_thread().send(SetCookiesForUrl(ws.url.clone(),
|
let _ = ws.global().r().core_resource_thread().send(SetCookiesForUrl(ws.url.clone(),
|
||||||
cookie_value,
|
cookie_value,
|
||||||
HTTP));
|
HTTP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,12 +208,13 @@ fn create_constellation(opts: opts::Opts,
|
||||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
|
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
|
||||||
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
|
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
|
||||||
|
|
||||||
let resource_threads = new_resource_threads(opts.user_agent.clone(),
|
let (public_resource_threads, private_resource_threads) =
|
||||||
devtools_chan.clone(),
|
new_resource_threads(opts.user_agent.clone(),
|
||||||
time_profiler_chan.clone());
|
devtools_chan.clone(),
|
||||||
let image_cache_thread = new_image_cache_thread(resource_threads.sender(),
|
time_profiler_chan.clone());
|
||||||
|
let image_cache_thread = new_image_cache_thread(public_resource_threads.sender(),
|
||||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||||
let font_cache_thread = FontCacheThread::new(resource_threads.sender(),
|
let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
|
||||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||||
|
|
||||||
let initial_state = InitialConstellationState {
|
let initial_state = InitialConstellationState {
|
||||||
|
@ -222,7 +223,8 @@ fn create_constellation(opts: opts::Opts,
|
||||||
bluetooth_thread: bluetooth_thread,
|
bluetooth_thread: bluetooth_thread,
|
||||||
image_cache_thread: image_cache_thread,
|
image_cache_thread: image_cache_thread,
|
||||||
font_cache_thread: font_cache_thread,
|
font_cache_thread: font_cache_thread,
|
||||||
resource_threads: resource_threads,
|
public_resource_threads: public_resource_threads,
|
||||||
|
private_resource_threads: private_resource_threads,
|
||||||
time_profiler_chan: time_profiler_chan,
|
time_profiler_chan: time_profiler_chan,
|
||||||
mem_profiler_chan: mem_profiler_chan,
|
mem_profiler_chan: mem_profiler_chan,
|
||||||
supports_clipboard: supports_clipboard,
|
supports_clipboard: supports_clipboard,
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl LoadOrigin for ResourceTest {
|
||||||
fn test_exit() {
|
fn test_exit() {
|
||||||
let (tx, _rx) = ipc::channel().unwrap();
|
let (tx, _rx) = ipc::channel().unwrap();
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
let resource_thread = new_core_resource_thread("".to_owned(), None, ProfilerChan(tx));
|
let (resource_thread, _) = new_core_resource_thread("".to_owned(), None, ProfilerChan(tx));
|
||||||
resource_thread.send(CoreResourceMsg::Exit(sender)).unwrap();
|
resource_thread.send(CoreResourceMsg::Exit(sender)).unwrap();
|
||||||
receiver.recv().unwrap();
|
receiver.recv().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ fn test_exit() {
|
||||||
fn test_bad_scheme() {
|
fn test_bad_scheme() {
|
||||||
let (tx, _rx) = ipc::channel().unwrap();
|
let (tx, _rx) = ipc::channel().unwrap();
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
let resource_thread = new_core_resource_thread("".to_owned(), None, ProfilerChan(tx));
|
let (resource_thread, _) = new_core_resource_thread("".to_owned(), None, ProfilerChan(tx));
|
||||||
let (start_chan, start) = ipc::channel().unwrap();
|
let (start_chan, start) = ipc::channel().unwrap();
|
||||||
let url = Url::parse("bogus://whatever").unwrap();
|
let url = Url::parse("bogus://whatever").unwrap();
|
||||||
resource_thread.send(CoreResourceMsg::Load(LoadData::new(LoadContext::Browsing, url, &ResourceTest),
|
resource_thread.send(CoreResourceMsg::Load(LoadData::new(LoadContext::Browsing, url, &ResourceTest),
|
||||||
|
@ -228,7 +228,7 @@ fn test_cancelled_listener() {
|
||||||
|
|
||||||
let (tx, _rx) = ipc::channel().unwrap();
|
let (tx, _rx) = ipc::channel().unwrap();
|
||||||
let (exit_sender, exit_receiver) = ipc::channel().unwrap();
|
let (exit_sender, exit_receiver) = ipc::channel().unwrap();
|
||||||
let resource_thread = new_core_resource_thread("".to_owned(), None, ProfilerChan(tx));
|
let (resource_thread, _) = new_core_resource_thread("".to_owned(), None, ProfilerChan(tx));
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
let (id_sender, id_receiver) = ipc::channel().unwrap();
|
let (id_sender, id_receiver) = ipc::channel().unwrap();
|
||||||
let (sync_sender, sync_receiver) = ipc::channel().unwrap();
|
let (sync_sender, sync_receiver) = ipc::channel().unwrap();
|
||||||
|
|
|
@ -6616,6 +6616,12 @@
|
||||||
"url": "/_mozilla/mozilla/mozbrowser/mozbrowsertitlechangedeagerly_event.html"
|
"url": "/_mozilla/mozilla/mozbrowser/mozbrowsertitlechangedeagerly_event.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"mozilla/mozbrowser/private_browsing.html": [
|
||||||
|
{
|
||||||
|
"path": "mozilla/mozbrowser/private_browsing.html",
|
||||||
|
"url": "/_mozilla/mozilla/mozbrowser/private_browsing.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"mozilla/mozbrowser/redirect.html": [
|
"mozilla/mozbrowser/redirect.html": [
|
||||||
{
|
{
|
||||||
"path": "mozilla/mozbrowser/redirect.html",
|
"path": "mozilla/mozbrowser/redirect.html",
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<html><body><div id="test">Normal iFrame</div></body>
|
||||||
|
<script>alert(document.cookie)</script>
|
||||||
|
</html>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<span id="cookie"></span>
|
||||||
|
<script>
|
||||||
|
document.querySelector('#cookie').innerHTML = document.cookie;
|
||||||
|
</script>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div id="test">Private iFrame</div>
|
||||||
|
</body>
|
||||||
|
<script>document.cookie = "private=active;path=/";</script>
|
||||||
|
<iframe src="iframe_privateContent_grandchild.html"></iframe>
|
||||||
|
<script>
|
||||||
|
var iframe = document.querySelector('iframe');
|
||||||
|
iframe.onload = function() {
|
||||||
|
alert(document.cookie + ' ' + iframe.contentDocument.querySelector('#cookie').textContent);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<head>
|
||||||
|
<meta charset="utf8" />
|
||||||
|
<title>Private browsing</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
async_test(function(t) {
|
||||||
|
var privateFrame = document.createElement("iframe");
|
||||||
|
privateFrame.mozbrowser = true;
|
||||||
|
privateFrame.mozprivatebrowsing = true;
|
||||||
|
|
||||||
|
var gotGrandchildResult = false;
|
||||||
|
privateFrame.addEventListener("mozbrowsershowmodalprompt", t.step_func(e => {
|
||||||
|
assert_equals(e.detail.message, 'private=active private=active');
|
||||||
|
gotGrandchildResult = true;
|
||||||
|
}));
|
||||||
|
|
||||||
|
privateFrame.onload = t.step_func(function() {
|
||||||
|
assert_true(gotGrandchildResult);
|
||||||
|
|
||||||
|
var parent = privateFrame.parentNode;
|
||||||
|
parent.removeChild(privateFrame);
|
||||||
|
|
||||||
|
var iframe = document.createElement("iframe");
|
||||||
|
var promptDisplay = false;
|
||||||
|
iframe.mozbrowser = true;
|
||||||
|
iframe.onload = t.step_func(function() {
|
||||||
|
assert_true(promptDisplay);
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
iframe.addEventListener("mozbrowsershowmodalprompt", t.step_func(e => {
|
||||||
|
promptDisplay = true;
|
||||||
|
assert_equals(e.detail.message, "");
|
||||||
|
}));
|
||||||
|
iframe.src = "iframe_contentDocument_inner.html";
|
||||||
|
parent.appendChild(iframe);
|
||||||
|
});
|
||||||
|
privateFrame.src = "iframe_privateContent_inner.html";
|
||||||
|
document.body.appendChild(privateFrame);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
Loading…
Add table
Add a link
Reference in a new issue