diff --git a/ports/servoshell/egl/android.rs b/ports/servoshell/egl/android.rs index f53ed5b2f51..d3b09769627 100644 --- a/ports/servoshell/egl/android.rs +++ b/ports/servoshell/egl/android.rs @@ -4,6 +4,7 @@ #![allow(non_snake_case)] +mod resources; mod simpleservo; use std::collections::HashMap; diff --git a/ports/servoshell/egl/resources.rs b/ports/servoshell/egl/android/resources.rs similarity index 53% rename from ports/servoshell/egl/resources.rs rename to ports/servoshell/egl/android/resources.rs index 9ada47afdb4..fb9d837aeb6 100644 --- a/ports/servoshell/egl/resources.rs +++ b/ports/servoshell/egl/android/resources.rs @@ -16,32 +16,32 @@ impl ResourceReaderInstance { impl ResourceReaderMethods for ResourceReaderInstance { fn read(&self, res: Resource) -> Vec { Vec::from(match res { - Resource::Preferences => &include_bytes!("../../../resources/prefs.json")[..], + Resource::Preferences => &include_bytes!("../../../../resources/prefs.json")[..], Resource::HstsPreloadList => { - &include_bytes!("../../../resources/hsts_preload.json")[..] + &include_bytes!("../../../../resources/hsts_preload.json")[..] }, - Resource::BadCertHTML => &include_bytes!("../../../resources/badcert.html")[..], - Resource::NetErrorHTML => &include_bytes!("../../../resources/neterror.html")[..], - Resource::UserAgentCSS => &include_bytes!("../../../resources/user-agent.css")[..], - Resource::ServoCSS => &include_bytes!("../../../resources/servo.css")[..], + Resource::BadCertHTML => &include_bytes!("../../../../resources/badcert.html")[..], + Resource::NetErrorHTML => &include_bytes!("../../../../resources/neterror.html")[..], + Resource::UserAgentCSS => &include_bytes!("../../../../resources/user-agent.css")[..], + Resource::ServoCSS => &include_bytes!("../../../../resources/servo.css")[..], Resource::PresentationalHintsCSS => { - &include_bytes!("../../../resources/presentational-hints.css")[..] + &include_bytes!("../../../../resources/presentational-hints.css")[..] }, - Resource::QuirksModeCSS => &include_bytes!("../../../resources/quirks-mode.css")[..], - Resource::RippyPNG => &include_bytes!("../../../resources/rippy.png")[..], - Resource::DomainList => &include_bytes!("../../../resources/public_domains.txt")[..], + Resource::QuirksModeCSS => &include_bytes!("../../../../resources/quirks-mode.css")[..], + Resource::RippyPNG => &include_bytes!("../../../../resources/rippy.png")[..], + Resource::DomainList => &include_bytes!("../../../../resources/public_domains.txt")[..], Resource::BluetoothBlocklist => { - &include_bytes!("../../../resources/gatt_blocklist.txt")[..] + &include_bytes!("../../../../resources/gatt_blocklist.txt")[..] }, Resource::MediaControlsCSS => { - &include_bytes!("../../../resources/media-controls.css")[..] + &include_bytes!("../../../../resources/media-controls.css")[..] }, Resource::MediaControlsJS => { - &include_bytes!("../../../resources/media-controls.js")[..] + &include_bytes!("../../../../resources/media-controls.js")[..] }, - Resource::CrashHTML => &include_bytes!("../../../resources/crash.html")[..], + Resource::CrashHTML => &include_bytes!("../../../../resources/crash.html")[..], Resource::DirectoryListingHTML => { - &include_bytes!("../../../resources/directory-listing.html")[..] + &include_bytes!("../../../../resources/directory-listing.html")[..] }, }) } diff --git a/ports/servoshell/egl/android/simpleservo.rs b/ports/servoshell/egl/android/simpleservo.rs index d5b9a73ebc8..194203d9102 100644 --- a/ports/servoshell/egl/android/simpleservo.rs +++ b/ports/servoshell/egl/android/simpleservo.rs @@ -27,8 +27,8 @@ use servo::webrender_traits::RenderingContext; use servo::{self, gl, Servo}; use surfman::{Connection, SurfaceType}; +use crate::egl::android::resources::ResourceReaderInstance; use crate::egl::host_trait::HostTrait; -use crate::egl::resources::ResourceReaderInstance; use crate::egl::servo_glue::{ Coordinates, ServoEmbedderCallbacks, ServoGlue, ServoWindowCallbacks, }; @@ -173,7 +173,7 @@ pub fn init( ); SERVO.with(|s| { - let mut servo_glue = ServoGlue::new(rendering_context, servo.servo, window_callbacks); + let mut servo_glue = ServoGlue::new(rendering_context, servo.servo, window_callbacks, None); let _ = servo_glue.process_event(EmbedderEvent::NewWebView(url, servo.browser_id)); *s.borrow_mut() = Some(servo_glue); }); diff --git a/ports/servoshell/egl/mod.rs b/ports/servoshell/egl/mod.rs index 28074756b57..b67dea98d1c 100644 --- a/ports/servoshell/egl/mod.rs +++ b/ports/servoshell/egl/mod.rs @@ -14,5 +14,4 @@ mod ohos; mod log; mod host_trait; -mod resources; mod servo_glue; diff --git a/ports/servoshell/egl/ohos.rs b/ports/servoshell/egl/ohos.rs index d5bf4b4dafb..363125dc287 100644 --- a/ports/servoshell/egl/ohos.rs +++ b/ports/servoshell/egl/ohos.rs @@ -31,6 +31,7 @@ use super::gl_glue; use super::host_trait::HostTrait; use super::servo_glue::ServoGlue; +mod resources; mod simpleservo; // Todo: in the future these libraries should be added by Rust sys-crates @@ -47,6 +48,8 @@ pub struct InitOpts { pub url: String, pub device_type: String, pub os_full_name: String, + /// Path to application data bundled with the servo app, e.g. web-pages. + pub resource_dir: String, pub display_density: f64, } diff --git a/ports/servoshell/egl/ohos/resources.rs b/ports/servoshell/egl/ohos/resources.rs new file mode 100644 index 00000000000..77d8fe68892 --- /dev/null +++ b/ports/servoshell/egl/ohos/resources.rs @@ -0,0 +1,33 @@ +/* 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 https://mozilla.org/MPL/2.0/. */ +use std::fs; +use std::path::PathBuf; + +use servo::embedder_traits::resources::{Resource, ResourceReaderMethods}; + +pub(crate) struct ResourceReaderInstance { + resource_dir: PathBuf, +} + +impl ResourceReaderInstance { + pub(crate) fn new(resource_dir: PathBuf) -> Self { + assert!(resource_dir.is_dir()); + Self { resource_dir } + } +} + +impl ResourceReaderMethods for ResourceReaderInstance { + fn read(&self, res: Resource) -> Vec { + let file_path = self.resource_dir.join(res.filename()); + fs::read(&file_path).expect("failed to read resource file") + } + + fn sandbox_access_files(&self) -> Vec { + vec![] + } + + fn sandbox_access_files_dirs(&self) -> Vec { + vec![] + } +} diff --git a/ports/servoshell/egl/ohos/simpleservo.rs b/ports/servoshell/egl/ohos/simpleservo.rs index 226a5c18fc7..4dad52c0c75 100644 --- a/ports/servoshell/egl/ohos/simpleservo.rs +++ b/ports/servoshell/egl/ohos/simpleservo.rs @@ -23,8 +23,8 @@ use servo::{self, gl, Servo}; use surfman::{Connection, SurfaceType}; use crate::egl::host_trait::HostTrait; +use crate::egl::ohos::resources::ResourceReaderInstance; use crate::egl::ohos::InitOpts; -use crate::egl::resources::ResourceReaderInstance; use crate::egl::servo_glue::{ Coordinates, ServoEmbedderCallbacks, ServoGlue, ServoWindowCallbacks, }; @@ -41,7 +41,8 @@ pub fn init( ) -> Result { info!("Entered simpleservo init function"); crate::init_tracing(); - resources::set(Box::new(ResourceReaderInstance::new())); + let resource_dir = PathBuf::from(&options.resource_dir).join("servo"); + resources::set(Box::new(ResourceReaderInstance::new(resource_dir))); gl.clear_color(1.0, 1.0, 1.0, 1.0); gl.clear(gl::COLOR_BUFFER_BIT); @@ -96,7 +97,12 @@ pub fn init( CompositeTarget::Window, ); - let mut servo_glue = ServoGlue::new(rendering_context, servo.servo, window_callbacks); + let mut servo_glue = ServoGlue::new( + rendering_context, + servo.servo, + window_callbacks, + Some(options.resource_dir), + ); let initial_url = ServoUrl::parse(options.url.as_str()) .inspect_err(|e| error!("Invalid initial Servo URL `{}`. Error: {e:?}", options.url)) diff --git a/ports/servoshell/egl/servo_glue.rs b/ports/servoshell/egl/servo_glue.rs index 48e3954bdb2..b5739f2ba50 100644 --- a/ports/servoshell/egl/servo_glue.rs +++ b/ports/servoshell/egl/servo_glue.rs @@ -23,6 +23,7 @@ use servo::keyboard_types::{Key, KeyState, KeyboardEvent}; use servo::script_traits::{ MediaSessionActionType, MouseButton, TouchEventType, TouchId, TraversalDirection, }; +use servo::servo_url::ServoUrl; use servo::style_traits::DevicePixel; use servo::webrender_api::ScrollLocation; use servo::webrender_traits::RenderingContext; @@ -85,6 +86,7 @@ pub struct ServoGlue { need_present: bool, callbacks: Rc, events: Vec, + resource_dir: Option, context_menu_sender: Option>, /// List of top-level browsing contexts. @@ -106,6 +108,7 @@ impl ServoGlue { rendering_context: RenderingContext, servo: Servo, callbacks: Rc, + resource_dir: Option, ) -> Self { Self { rendering_context, @@ -114,6 +117,7 @@ impl ServoGlue { need_present: false, callbacks, events: vec![], + resource_dir, context_menu_sender: None, webviews: HashMap::default(), creation_order: vec![], diff --git a/python/servo/package_commands.py b/python/servo/package_commands.py index cad2a73f275..6ddf378c2c5 100644 --- a/python/servo/package_commands.py +++ b/python/servo/package_commands.py @@ -194,6 +194,10 @@ class PackageCommands(CommandBase): print("Cleaning up from previous packaging") delete(ohos_target_dir) shutil.copytree(ohos_app_dir, ohos_target_dir) + resources_src_dir = path.join(self.get_top_dir(), "resources") + resources_app_dir = path.join(ohos_target_dir, "AppScope", "resources", "resfile", "servo") + os.makedirs(resources_app_dir, exist_ok=True) + shutil.copytree(resources_src_dir, resources_app_dir, dirs_exist_ok=True) # Map non-debug profiles to 'release' buildMode HAP. if build_type.is_custom(): diff --git a/support/openharmony/entry/src/main/ets/pages/Index.ets b/support/openharmony/entry/src/main/ets/pages/Index.ets index 96c5a65846b..f9eda7854a7 100644 --- a/support/openharmony/entry/src/main/ets/pages/Index.ets +++ b/support/openharmony/entry/src/main/ets/pages/Index.ets @@ -1,3 +1,4 @@ +import { common } from '@kit.AbilityKit'; import display from '@ohos.display'; import deviceInfo from '@ohos.deviceInfo'; @@ -13,6 +14,7 @@ interface InitOpts { url: string; deviceType: string, osFullName: string, + resourceDir: string, displayDensity: number, } @@ -47,6 +49,7 @@ struct Index { libraryname: 'servoshell', } @State urlToLoad: string = 'https://servo.org' + private context = getContext(this) as common.UIAbilityContext; build() { Column() { @@ -82,11 +85,14 @@ struct Index { .focusable(true) .onLoad((xComponentContext) => { this.xComponentContext = xComponentContext as ServoXComponentInterface; + let resource_dir: string = this.context.resourceDir; + console.debug("Resources are located at %s", resource_dir); let init_options: InitOpts = { url: this.urlToLoad, deviceType: get_device_type(), osFullName: deviceInfo.osFullName, displayDensity: get_density(), + resourceDir: resource_dir, } this.xComponentContext.initServo(init_options) this.xComponentContext.registerURLcallback((new_url) => {