mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #26325 - jdm:devtools-nav, r=gterzian
Improve devtools experience when navigating The primary motivation for this work was to fix #15425, and these changes make it possible to use the devtools to meaningfully inspect multiple pages when navigating between them. Navigating through session history is not yet supported. These changes also include improvements to the dedicated worker support, which broke at some point. We now can observe console messages in workers.
This commit is contained in:
commit
1aab10f20a
17 changed files with 693 additions and 265 deletions
|
@ -43,7 +43,7 @@ use js::jsapi::JS_AddInterruptCallback;
|
|||
use js::jsapi::{Heap, JSContext, JSObject};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
|
||||
use net_traits::image_cache::ImageCache;
|
||||
use net_traits::request::{CredentialsMode, Destination, ParserMetadata};
|
||||
use net_traits::request::{Referrer, RequestBuilder, RequestMode};
|
||||
|
@ -180,6 +180,7 @@ pub struct DedicatedWorkerGlobalScope {
|
|||
parent_sender: Box<dyn ScriptChan + Send>,
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
browsing_context: Option<BrowsingContextId>,
|
||||
}
|
||||
|
||||
impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope {
|
||||
|
@ -221,6 +222,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
receiver: Receiver<DedicatedWorkerScriptMsg>,
|
||||
closing: Arc<AtomicBool>,
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
browsing_context: Option<BrowsingContextId>,
|
||||
) -> DedicatedWorkerGlobalScope {
|
||||
DedicatedWorkerGlobalScope {
|
||||
workerglobalscope: WorkerGlobalScope::new_inherited(
|
||||
|
@ -237,6 +239,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
parent_sender: parent_sender,
|
||||
worker: DomRefCell::new(None),
|
||||
image_cache: image_cache,
|
||||
browsing_context,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,6 +256,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
receiver: Receiver<DedicatedWorkerScriptMsg>,
|
||||
closing: Arc<AtomicBool>,
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
browsing_context: Option<BrowsingContextId>,
|
||||
) -> DomRoot<DedicatedWorkerGlobalScope> {
|
||||
let cx = runtime.cx();
|
||||
let scope = Box::new(DedicatedWorkerGlobalScope::new_inherited(
|
||||
|
@ -267,6 +271,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
receiver,
|
||||
closing,
|
||||
image_cache,
|
||||
browsing_context,
|
||||
));
|
||||
unsafe { DedicatedWorkerGlobalScopeBinding::Wrap(SafeJSContext::from_ptr(cx), scope) }
|
||||
}
|
||||
|
@ -286,6 +291,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
worker_type: WorkerType,
|
||||
closing: Arc<AtomicBool>,
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
browsing_context: Option<BrowsingContextId>,
|
||||
) {
|
||||
let serialized_worker_url = worker_url.to_string();
|
||||
let name = format!("WebWorker for {}", serialized_worker_url);
|
||||
|
@ -354,6 +360,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
receiver,
|
||||
closing,
|
||||
image_cache,
|
||||
browsing_context,
|
||||
);
|
||||
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
||||
// registration (#6631), so we instead use a random number and cross our fingers.
|
||||
|
@ -467,6 +474,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
}
|
||||
|
||||
fn handle_mixed_message(&self, msg: MixedMessage) {
|
||||
// FIXME(#26324): `self.worker` is None in devtools messages.
|
||||
match msg {
|
||||
MixedMessage::FromDevtools(msg) => match msg {
|
||||
DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) => {
|
||||
|
@ -551,6 +559,10 @@ impl DedicatedWorkerGlobalScope {
|
|||
.expect("Sending to parent failed");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn browsing_context(&self) -> Option<BrowsingContextId> {
|
||||
self.browsing_context
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
|
|
@ -934,6 +934,14 @@ impl Document {
|
|||
pub fn title_changed(&self) {
|
||||
if self.browsing_context().is_some() {
|
||||
self.send_title_to_embedder();
|
||||
let global = self.window.upcast::<GlobalScope>();
|
||||
if let Some(ref chan) = global.devtools_chan() {
|
||||
let title = String::from(self.Title());
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::TitleChanged(
|
||||
global.pipeline_id(),
|
||||
title,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ impl ServiceWorkerRegistration {
|
|||
|
||||
let worker_id = WorkerId(Uuid::new_v4());
|
||||
let devtools_chan = global.devtools_chan().cloned();
|
||||
let init = prepare_workerscope_init(&global, None);
|
||||
let init = prepare_workerscope_init(&global, None, None);
|
||||
ScopeThings {
|
||||
script_url: script_url,
|
||||
init: init,
|
||||
|
|
|
@ -2008,15 +2008,21 @@ impl Window {
|
|||
|
||||
// Step 8
|
||||
if doc.prompt_to_unload(false) {
|
||||
if self.window_proxy().parent().is_some() {
|
||||
let window_proxy = self.window_proxy();
|
||||
if window_proxy.parent().is_some() {
|
||||
// Step 10
|
||||
// If browsingContext is a nested browsing context,
|
||||
// then put it in the delaying load events mode.
|
||||
self.window_proxy().start_delaying_load_events_mode();
|
||||
window_proxy.start_delaying_load_events_mode();
|
||||
}
|
||||
// TODO: step 11, navigationType.
|
||||
// Step 12, 13
|
||||
ScriptThread::navigate(pipeline_id, load_data, replace);
|
||||
ScriptThread::navigate(
|
||||
window_proxy.browsing_context_id(),
|
||||
pipeline_id,
|
||||
load_data,
|
||||
replace,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ use crate::dom::dedicatedworkerglobalscope::{
|
|||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::messageevent::MessageEvent;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::workerglobalscope::prepare_workerscope_init;
|
||||
use crate::realms::enter_realm;
|
||||
use crate::script_runtime::JSContext;
|
||||
|
@ -95,23 +96,34 @@ impl Worker {
|
|||
pipeline_id: global.pipeline_id(),
|
||||
};
|
||||
|
||||
let browsing_context = global
|
||||
.downcast::<Window>()
|
||||
.map(|w| w.window_proxy().browsing_context_id())
|
||||
.or_else(|| {
|
||||
global
|
||||
.downcast::<DedicatedWorkerGlobalScope>()
|
||||
.and_then(|w| w.browsing_context())
|
||||
});
|
||||
|
||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||
let worker_id = WorkerId(Uuid::new_v4());
|
||||
if let Some(ref chan) = global.devtools_chan() {
|
||||
let pipeline_id = global.pipeline_id();
|
||||
let title = format!("Worker for {}", worker_url);
|
||||
let page_info = DevtoolsPageInfo {
|
||||
title: title,
|
||||
url: worker_url.clone(),
|
||||
};
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||
(pipeline_id, Some(worker_id)),
|
||||
devtools_sender.clone(),
|
||||
page_info,
|
||||
));
|
||||
if let Some(browsing_context) = browsing_context {
|
||||
let page_info = DevtoolsPageInfo {
|
||||
title: title,
|
||||
url: worker_url.clone(),
|
||||
};
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||
(browsing_context, pipeline_id, Some(worker_id)),
|
||||
devtools_sender.clone(),
|
||||
page_info,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let init = prepare_workerscope_init(global, Some(devtools_sender));
|
||||
let init = prepare_workerscope_init(global, Some(devtools_sender), Some(worker_id));
|
||||
|
||||
DedicatedWorkerGlobalScope::run_worker_scope(
|
||||
init,
|
||||
|
@ -126,6 +138,7 @@ impl Worker {
|
|||
worker_options.type_,
|
||||
closing,
|
||||
global.image_cache(),
|
||||
browsing_context,
|
||||
);
|
||||
|
||||
Ok(worker)
|
||||
|
|
|
@ -62,6 +62,7 @@ use uuid::Uuid;
|
|||
pub fn prepare_workerscope_init(
|
||||
global: &GlobalScope,
|
||||
devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
|
||||
worker_id: Option<WorkerId>,
|
||||
) -> WorkerGlobalScopeInit {
|
||||
let init = WorkerGlobalScopeInit {
|
||||
resource_threads: global.resource_threads().clone(),
|
||||
|
@ -71,7 +72,7 @@ pub fn prepare_workerscope_init(
|
|||
from_devtools_sender: devtools_sender,
|
||||
script_to_constellation_chan: global.script_to_constellation_chan().clone(),
|
||||
scheduler_chan: global.scheduler_chan().clone(),
|
||||
worker_id: WorkerId(Uuid::new_v4()),
|
||||
worker_id: worker_id.unwrap_or_else(|| WorkerId(Uuid::new_v4())),
|
||||
pipeline_id: global.pipeline_id(),
|
||||
origin: global.origin().immutable().clone(),
|
||||
is_headless: global.is_headless(),
|
||||
|
|
|
@ -93,7 +93,7 @@ use canvas_traits::webgl::WebGLPipeline;
|
|||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use devtools_traits::CSSError;
|
||||
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||
use devtools_traits::{NavigationState, ScriptToDevtoolsControlMsg, WorkerId};
|
||||
use embedder_traits::{EmbedderMsg, EventLoopWaker};
|
||||
use euclid::default::{Point2D, Rect};
|
||||
use euclid::Vector2D;
|
||||
|
@ -947,6 +947,7 @@ impl ScriptThread {
|
|||
|
||||
/// Step 13 of https://html.spec.whatwg.org/multipage/#navigate
|
||||
pub fn navigate(
|
||||
browsing_context: BrowsingContextId,
|
||||
pipeline_id: PipelineId,
|
||||
mut load_data: LoadData,
|
||||
replace: HistoryEntryReplacement,
|
||||
|
@ -985,6 +986,12 @@ impl ScriptThread {
|
|||
.queue(task, global.upcast())
|
||||
.expect("Enqueing navigate js task on the DOM manipulation task source failed");
|
||||
} else {
|
||||
if let Some(ref sender) = script_thread.devtools_chan {
|
||||
let _ = sender.send(ScriptToDevtoolsControlMsg::Navigate(
|
||||
browsing_context, NavigationState::Start(load_data.url.clone())
|
||||
));
|
||||
}
|
||||
|
||||
script_thread
|
||||
.script_sender
|
||||
.send((pipeline_id, ScriptMsg::LoadUrl(load_data, replace)))
|
||||
|
@ -3341,7 +3348,7 @@ impl ScriptThread {
|
|||
self.notify_devtools(
|
||||
document.Title(),
|
||||
final_url.clone(),
|
||||
(incomplete.pipeline_id, None),
|
||||
(incomplete.browsing_context_id, incomplete.pipeline_id, None),
|
||||
);
|
||||
|
||||
let parse_input = DOMString::new();
|
||||
|
@ -3372,7 +3379,7 @@ impl ScriptThread {
|
|||
&self,
|
||||
title: DOMString,
|
||||
url: ServoUrl,
|
||||
ids: (PipelineId, Option<WorkerId>),
|
||||
(bc, p, w): (BrowsingContextId, PipelineId, Option<WorkerId>),
|
||||
) {
|
||||
if let Some(ref chan) = self.devtools_chan {
|
||||
let page_info = DevtoolsPageInfo {
|
||||
|
@ -3380,11 +3387,14 @@ impl ScriptThread {
|
|||
url: url,
|
||||
};
|
||||
chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||
ids,
|
||||
(bc, p, w),
|
||||
self.devtools_sender.clone(),
|
||||
page_info,
|
||||
page_info.clone(),
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let state = NavigationState::Stop(p, page_info);
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::Navigate(bc, state));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::dom::abstractworker::WorkerScriptMsg;
|
|||
use crate::dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg};
|
||||
use crate::dom::serviceworkerregistration::longest_prefix_match;
|
||||
use crossbeam_channel::{unbounded, Receiver, RecvError, Sender};
|
||||
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::{CoreResourceMsg, CustomResponseMediator};
|
||||
|
@ -79,19 +78,7 @@ impl ServiceWorkerManager {
|
|||
let scope_things = self.registered_workers.get(&scope_url);
|
||||
if let Some(scope_things) = scope_things {
|
||||
let (sender, receiver) = unbounded();
|
||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||
if let Some(ref chan) = scope_things.devtools_chan {
|
||||
let title = format!("ServiceWorker for {}", scope_things.script_url);
|
||||
let page_info = DevtoolsPageInfo {
|
||||
title: title,
|
||||
url: scope_things.script_url.clone(),
|
||||
};
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||
(scope_things.init.pipeline_id, Some(scope_things.worker_id)),
|
||||
devtools_sender,
|
||||
page_info,
|
||||
));
|
||||
};
|
||||
let (_devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||
ServiceWorkerGlobalScope::run_serviceworker_scope(
|
||||
scope_things.clone(),
|
||||
sender.clone(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue