@@ -18,8 +18,11 @@ use compositor_task::Msg as ToCompositorMsg;
1818use devtools_traits:: { ChromeToDevtoolsControlMsg , DevtoolsControlMsg } ;
1919use euclid:: scale_factor:: ScaleFactor ;
2020use euclid:: size:: { Size2D , TypedSize2D } ;
21+ use gaol;
22+ use gaol:: sandbox:: { self , Sandbox , SandboxMethods } ;
2123use gfx:: font_cache_task:: FontCacheTask ;
22- use ipc_channel:: ipc:: { self , IpcSender } ;
24+ use ipc_channel:: ipc:: { self , IpcOneShotServer , IpcSender } ;
25+ use ipc_channel:: router:: ROUTER ;
2326use layout_traits:: { LayoutControlChan , LayoutTaskFactory } ;
2427use msg:: compositor_msg:: Epoch ;
2528use msg:: constellation_msg:: AnimationState ;
@@ -37,19 +40,21 @@ use net_traits::image_cache_task::ImageCacheTask;
3740use net_traits:: storage_task:: { StorageTask , StorageTaskMsg } ;
3841use net_traits:: { self , ResourceTask } ;
3942use offscreen_gl_context:: GLContextAttributes ;
40- use pipeline:: { CompositionPipeline , InitialPipelineState , Pipeline } ;
43+ use pipeline:: { CompositionPipeline , InitialPipelineState , Pipeline , UnprivilegedPipelineContent } ;
4144use profile_traits:: mem;
4245use profile_traits:: time;
46+ use sandboxing;
4347use script_traits:: { CompositorEvent , ConstellationControlMsg , LayoutControlMsg } ;
4448use script_traits:: { ScriptState , ScriptTaskFactory } ;
4549use script_traits:: { TimerEventRequest } ;
4650use std:: borrow:: ToOwned ;
4751use std:: collections:: HashMap ;
52+ use std:: env;
4853use std:: io:: { self , Write } ;
4954use std:: marker:: PhantomData ;
5055use std:: mem:: replace;
5156use std:: process;
52- use std:: sync:: mpsc:: { Receiver , Sender , channel} ;
57+ use std:: sync:: mpsc:: { Sender , channel, Receiver } ;
5358use style_traits:: viewport:: ViewportConstraints ;
5459use timer_scheduler:: TimerScheduler ;
5560use url:: Url ;
@@ -79,7 +84,7 @@ pub struct Constellation<LTF, STF> {
7984 pub script_sender : ConstellationChan < FromScriptMsg > ,
8085
8186 /// A channel through which compositor messages can be sent to this object.
82- pub compositor_sender : ConstellationChan < FromCompositorMsg > ,
87+ pub compositor_sender : Sender < FromCompositorMsg > ,
8388
8489 /// Receives messages from scripts.
8590 pub script_receiver : Receiver < FromScriptMsg > ,
@@ -156,6 +161,9 @@ pub struct Constellation<LTF, STF> {
156161 webgl_paint_tasks : Vec < Sender < CanvasMsg > > ,
157162
158163 scheduler_chan : IpcSender < TimerEventRequest > ,
164+
165+ /// A list of child content processes.
166+ child_processes : Vec < ChildProcess > ,
159167}
160168
161169/// State needed to construct a constellation.
@@ -259,14 +267,21 @@ enum ExitPipelineMode {
259267 Force ,
260268}
261269
270+ enum ChildProcess {
271+ Sandboxed ( gaol:: platform:: process:: Process ) ,
272+ Unsandboxed ( process:: Child ) ,
273+ }
274+
262275impl < LTF : LayoutTaskFactory , STF : ScriptTaskFactory > Constellation < LTF , STF > {
263- pub fn start ( state : InitialConstellationState ) -> ConstellationChan < FromCompositorMsg > {
264- let ( script_receiver, script_sender) = ConstellationChan :: < FromScriptMsg > :: new ( ) ;
265- let ( compositor_receiver, compositor_sender) = ConstellationChan :: < FromCompositorMsg > :: new ( ) ;
276+ pub fn start ( state : InitialConstellationState ) -> Sender < FromCompositorMsg > {
277+ let ( ipc_script_receiver, ipc_script_sender) = ConstellationChan :: < FromScriptMsg > :: new ( ) ;
278+ //let (script_receiver, script_sender) = channel();
279+ let script_receiver = ROUTER . route_ipc_receiver_to_new_mpsc_receiver ( ipc_script_receiver) ;
280+ let ( compositor_sender, compositor_receiver) = channel ( ) ;
266281 let compositor_sender_clone = compositor_sender. clone ( ) ;
267282 spawn_named ( "Constellation" . to_owned ( ) , move || {
268283 let mut constellation: Constellation < LTF , STF > = Constellation {
269- script_sender : script_sender ,
284+ script_sender : ipc_script_sender ,
270285 compositor_sender : compositor_sender_clone,
271286 script_receiver : script_receiver,
272287 compositor_receiver : compositor_receiver,
@@ -305,6 +320,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
305320 canvas_paint_tasks : Vec :: new ( ) ,
306321 webgl_paint_tasks : Vec :: new ( ) ,
307322 scheduler_chan : TimerScheduler :: start ( ) ,
323+ child_processes : Vec :: new ( ) ,
308324 } ;
309325 let namespace_id = constellation. next_pipeline_namespace_id ( ) ;
310326 PipelineNamespace :: install ( namespace_id) ;
@@ -333,10 +349,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
333349 pipeline_id : PipelineId ,
334350 parent_info : Option < ( PipelineId , SubpageId ) > ,
335351 initial_window_size : Option < TypedSize2D < PagePx , f32 > > ,
336- script_channel : Option < Sender < ConstellationControlMsg > > ,
352+ script_channel : Option < IpcSender < ConstellationControlMsg > > ,
337353 load_data : LoadData ) {
338354 let spawning_paint_only = script_channel. is_some ( ) ;
339- let ( pipeline, mut pipeline_content ) =
355+ let ( pipeline, unprivileged_pipeline_content , mut privileged_pipeline_content ) =
340356 Pipeline :: create :: < LTF , STF > ( InitialPipelineState {
341357 id : pipeline_id,
342358 parent_info : parent_info,
@@ -357,12 +373,39 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
357373 pipeline_namespace_id : self . next_pipeline_namespace_id ( ) ,
358374 } ) ;
359375
360- // TODO(pcwalton): In multiprocess mode, send that `PipelineContent` instance over to
361- // the content process and call this over there.
362376 if spawning_paint_only {
363- pipeline_content . start_paint_task ( ) ;
377+ privileged_pipeline_content . start_paint_task ( ) ;
364378 } else {
365- pipeline_content. start_all :: < LTF , STF > ( ) ;
379+ privileged_pipeline_content. start_all ( ) ;
380+
381+ // Spawn the child process.
382+ //
383+ // Yes, that's all there is to it!
384+ if opts:: multiprocess ( ) {
385+ let ( server, token) =
386+ IpcOneShotServer :: < IpcSender < UnprivilegedPipelineContent > > :: new ( ) . unwrap ( ) ;
387+
388+ // If there is a sandbox, use the `gaol` API to create the child process.
389+ let child_process = if opts:: get ( ) . sandbox {
390+ let mut command = sandbox:: Command :: me ( ) . unwrap ( ) ;
391+ command. arg ( "--content-process" ) . arg ( token) ;
392+ let profile = sandboxing:: content_process_sandbox_profile ( ) ;
393+ ChildProcess :: Sandboxed ( Sandbox :: new ( profile) . start ( & mut command) . expect (
394+ "Failed to start sandboxed child process!" ) )
395+ } else {
396+ let path_to_self = env:: current_exe ( ) . unwrap ( ) ;
397+ let mut child_process = process:: Command :: new ( path_to_self) ;
398+ child_process. arg ( "--content-process" ) ;
399+ child_process. arg ( token) ;
400+ ChildProcess :: Unsandboxed ( child_process. spawn ( ) . unwrap ( ) )
401+ } ;
402+ self . child_processes . push ( child_process) ;
403+
404+ let ( _receiver, sender) = server. accept ( ) . unwrap ( ) ;
405+ sender. send ( unprivileged_pipeline_content) . unwrap ( ) ;
406+ } else {
407+ unprivileged_pipeline_content. start_all :: < LTF , STF > ( false ) ;
408+ }
366409 }
367410
368411 assert ! ( !self . pipelines. contains_key( & pipeline_id) ) ;
@@ -1290,7 +1333,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
12901333
12911334 // Synchronously query the script task for this pipeline
12921335 // to see if it is idle.
1293- let ( sender, receiver) = channel ( ) ;
1336+ let ( sender, receiver) = ipc :: channel ( ) . unwrap ( ) ;
12941337 let msg = ConstellationControlMsg :: GetCurrentState ( sender, frame. current ) ;
12951338 pipeline. script_chan . send ( msg) . unwrap ( ) ;
12961339 let result = receiver. recv ( ) . unwrap ( ) ;
@@ -1445,7 +1488,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
14451488 if let Some ( root_frame_id) = self . root_frame_id {
14461489 let frame_tree = self . frame_to_sendable ( root_frame_id) ;
14471490
1448- let ( chan, port) = channel ( ) ;
1491+ let ( chan, port) = ipc :: channel ( ) . unwrap ( ) ;
14491492 self . compositor_proxy . send ( ToCompositorMsg :: SetFrameTree ( frame_tree,
14501493 chan,
14511494 self . compositor_sender . clone ( ) ) ) ;
0 commit comments