From 51a6e835d28fc4e7dff26661b2e730197303969f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 27 Jul 2012 15:35:05 -0700 Subject: [PATCH] Add ResourceTask --- src/servo/resource/resource_task.rs | 117 ++++++++++++++++++++++++++++ src/servo/servo.rc | 4 + 2 files changed, 121 insertions(+) create mode 100644 src/servo/resource/resource_task.rs diff --git a/src/servo/resource/resource_task.rs b/src/servo/resource/resource_task.rs new file mode 100644 index 00000000000..0d7fcca2f46 --- /dev/null +++ b/src/servo/resource/resource_task.rs @@ -0,0 +1,117 @@ +/*! + +A task that takes a URL and streams back the binary data + +*/ + +export ControlMsg, ProgressMsg, ResourceTask, ResourceManager, LoaderTaskFactory; + +import comm::{chan, port, methods}; +import task::{spawn, spawn_listener}; +import std::net::url; +import std::net::url::url; +import result::{result, ok, err}; + +enum ControlMsg { + Load(url, chan), + Exit +} + +enum ProgressMsg { + Payload(~[u8]), + Done(result<(), ()>) +} + +type ResourceTask = chan; +/// Creates a task to load a specific resource +type LoaderTaskFactory = fn~(url: url, chan); + +fn ResourceTask() -> ResourceTask { + create_resource_task_with_loaders(~[]) +} + +fn create_resource_task_with_loaders(+loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask { + do spawn_listener |from_client| { + ResourceManager(from_client, loaders).start() + } +} + +class ResourceManager { + let from_client: port; + /// Per-scheme resource loaders + let loaders: ~[(~str, LoaderTaskFactory)]; + + new(from_client: port, loaders: ~[(~str, LoaderTaskFactory)]) { + self.from_client = from_client; + self.loaders = loaders; + } + + fn start() { + loop { + alt self.from_client.recv() { + Load(url, progress_chan) { + self.load(url, progress_chan) + } + Exit { + break + } + } + } + } + + fn load(url: url, progress_chan: chan) { + + alt self.get_loader_factory(url) { + some(loader_factory) { + loader_factory(url, progress_chan); + } + none { + #debug("resource_task: no loader for scheme %s", url.scheme); + progress_chan.send(Done(err(()))); + } + } + } + + fn get_loader_factory(url: url) -> option { + for self.loaders.each |scheme_loader| { + let (scheme, loader_factory) = scheme_loader; + if scheme == url.scheme { + ret some(loader_factory); + } + } + ret none; + } +} + +#[test] +fn test_exit() { + let resource_task = ResourceTask(); + resource_task.send(Exit); +} + +#[test] +fn test_bad_scheme() { + let resource_task = ResourceTask(); + let progress = port(); + resource_task.send(Load(url::from_str(~"bogus://whatever").get(), progress.chan())); + alt check progress.recv() { + Done(result) { assert result.is_err() } + } + resource_task.send(Exit); +} + +#[test] +fn should_delegate_to_scheme_loader() { + let payload = ~[1, 2, 3]; + let loader_factory = fn~(url: url, progress_chan: chan) { + progress_chan.send(Payload(payload)); + progress_chan.send(Done(ok(()))); + }; + let loader_factories = ~[(~"snicklefritz", loader_factory)]; + let resource_task = create_resource_task_with_loaders(loader_factories); + let progress = port(); + resource_task.send(Load(url::from_str(~"snicklefritz://heya").get(), progress.chan())); + assert progress.recv() == Payload(payload); + assert progress.recv() == Done(ok(())); + resource_task.send(Exit); +} \ No newline at end of file diff --git a/src/servo/servo.rc b/src/servo/servo.rc index 5163fb18acf..7b846e855e6 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -110,4 +110,8 @@ mod content { mod opts; mod engine; +mod resource { + mod resource_task; +} + import servo_text = text;