System App
system app 是由gecko层的
shell.js引导启动的第一个App,相当于Nutria的界面框架。
capyloon系统的状态栏、导航栏、通知栏、系统开关机等都是有system app 负责管理的。
项目布局
system app 重要文件和目录分别是
index.html、manifest.webmanifest、components文件夹、js文件夹
├── **components**
│ ├── activity_chooser.css
│ ├── activity_chooser.js
│ ├── app_icon.css
│ ├── apps_list.css
│ ├── apps_list.js
│ ├── audio_volume_indicator.css
│ ├── audio_volume_indicator.js
│ ├── browser_action_popup.css
│ ├── browser_action_popup.js
│ ├── confirm_dialog.css
│ ├── confirm_dialog.js
│ ├── content_window.css
│ ├── content_window.js
│ ├── context_menu.css
│ ├── context_menu.js
│ ├── input_method.css
│ ├── input_method.js
│ ├── lock_screen.css
│ ├── lock_screen.js
│ ├── notification.js
│ ├── places_item.css
│ ├── publish_dialog.css
│ ├── publish_dialog.js
│ ├── quick_settings.css
│ ├── quick_settings.js
│ ├── reboot_menu.css
│ ├── reboot_menu.js
│ ├── select_ui.css
│ ├── select_ui.js
│ ├── site_info.css
│ ├── site_info.js
│ ├── status_bar.css
│ ├── status_bar.js
│ ├── status_icons.css
│ ├── status_icons.js
│ ├── text_share.css
│ ├── text_share.js
│ ├── ucan.js
│ ├── ucan_dialog.css
│ ├── url_edit.css
│ ├── url_edit.js
│ ├── web_extensions.js
│ ├── window_manager.css
│ └── window_manager.js
├── index.html
├── **js**
│ ├── actions_dispatcher.js
│ ├── activity_handler.js
│ ├── **audio_volume**
│ │ ├── gonk.js
│ │ └── linux.js
│ ├── battery.js
│ ├── bootstrap.js
│ ├── config.js
│ ├── dependencies.js
│ ├── downloads.js
│ ├── embedding.js
│ ├── estuary.js
│ ├── flashlight.js
│ ├── haptic_feedback.js
│ ├── input_method.js
│ ├── ipfs_publisher.js
│ ├── keys.js
│ ├── notifications.js
│ ├── p2p.js
│ ├── power_manager.js
│ ├── ua_store.js
│ ├── wallpaper_manager.js
│ └── web_extensions_delegate.js
├── **locales**
├── manifest.webmanifest
├── **neterror**
│ ├── config.js
│ ├── index.html
│ ├── main.js
│ └── style.css
├── **resources**
│ ├── default-wallpaper.webp
│ ├── logo-b2g.webp
│ ├── pwalogo.svg
│ └── tor.ico
├── **style**
│ ├── desktop.css
│ ├── device.css
│ └── index.css
└── **swproxy**
├── helper.js
├── proxy.html
├── proxy.js
└── sw.js
index.html
我们先从index入口开始分析
<!DOCTYPE html>
<html lang="en-US">
<head>
...
<!-- embedding API provider -->
<script src="chrome://b2g/content/embedding/web-embedder.js"></script>
<!--
This will setup Fluent for l10n
We don't lazy load it because it's needed at startup to localize the boot screen.
-->
<script src="js/config.js"></script>
<script src="js/embedding.js"></script>
<script src="js/dependencies.js"></script>
<script src="js/bootstrap.js" type="module"></script>
</head>
<body>
<!-- 开机关机 -->
<div id="logo" class="starting">
<div class="title" data-l10n-id="logo-title">Capyloon</div>
<div class="subtitle" data-l10n-id="logo-subtitle"></div>
<div class="image"></div>
<div class="action starting" data-l10n-id="logo-starting"></div>
<div class="action shutdown" data-l10n-id="logo-shutdown"></div>
<div class="action reboot" data-l10n-id="logo-reboot"></div>
</div>
<!-- 主界面框架 -->
<div id="screen">
<!-- 顶部状态栏 -->
<div id="status-top"></div>
<!-- web complement 应用管理器 - 其他应用都是显示在这里面 -->
<window-manager id="wm"></window-manager>
<!-- 底部操作栏 -->
<status-bar id="statusbar"></status-bar>
</div>
<!-- shoelace components - 底部快速设置抽屉 -->
<sl-drawer no-header placement="bottom" id="quick-settings">
<quick-settings></quick-settings>
</sl-drawer>
<!-- shoelace components - 侧边电源菜单抽屉 -->
<sl-drawer no-header placement="end" id="reboot-menu">
<reboot-menu></reboot-menu>
</sl-drawer>
<!-- shoelace components - 当前页面标题UA相关信息面板 -->
<sl-drawer no-header placement="bottom" id="site-info">
<site-info></site-info>
</sl-drawer>
<!-- shoelace components - ??? -->
<sl-drawer no-header placement="bottom" id="activity-chooser">
<activity-chooser></activity-chooser>
</sl-drawer>
<!-- app 列表 -->
<apps-list id="apps-list"></apps-list>
<!-- 其他全局弹窗 -->
<context-menu></context-menu>
<text-share></text-share>
<confirm-dialog></confirm-dialog>
<publish-dialog></publish-dialog>
<ucan-dialog></ucan-dialog>
<-- 地址输入栏面版 -->
<url-edit class="offscreen"></url-edit>
<webext-browser-action class="offscreen"></webext-browser-action>
<!-- 输入法弹窗 -->
<input-method class="offscreen"></input-method>
<!-- 锁屏界面 -->
<lock-screen id="lockscreen" class="unlocked"></lock-screen>
<!-- 音量 -->
<audio-volume id="audiovolume" class="offscreen" hidden></audio-volume>
<!-- 权限使用图标 -->
<status-icons id="status-icons" class="hidden"></status-icons>
<!-- 提示 -->
<template id="toaster-template">
<sl-alert duration="2000" closable>
<sl-icon slot="icon"></sl-icon>
<strong></strong>
</sl-alert>
</template>
</body>
</html>
js/config.js
1 preconnect to the api daemon api server.
2 preconnect to the homescreen.
3 加载depGraphLoaded引擎
4 MinuteTimer 一个正秒的事件定时器
5 创建Toaster class, 把html 的Toaster dom 绑定,然后把实例挂载window.toaster 使用show方法。
js/bootstrap.js
DOMContentLoaded 事件进行初始化。
1 等待 embedderSetupDone
2 等待 daemonReady
3 加载 config js 的depGraphLoaded , 加载kDeps
4 等待 依赖 graph.waitForDeps: lockscreen comp phase1 launch
5 keyManager js 注册 按键事件。
6 setupTelephony
7 addheadphones-status-changed事件
8 等待 manageFTU
9 addgeolocation-status事件。
setupTelephony
1 通过 navigator.b2g?.mobileConnections 控制ril的开启关闭
2 添加事件navigator.b2g.telephony.onincoming
// Open the dialer when we receive an incoming call.
navigator.b2g.telephony.onincoming = () => {
// If the screen is turned off, turn it on.
actionsDispatcher.dispatch("set-screen-on");
// If the screen is locked, launch through the lockscreen.
let url = `http://dialer.localhost:${config.port}/index.html?incoming`;
if (window.lockscreen.isLocked()) {
window.lockscreen.launch(url);
} else {
window.wm.openFrame(url, {
activate: true,
});
}
};
}
manageFTU
1 检查设置的ftu.done标识是否为false
2 通过window.lockscreen.launch 启动ftu
js/embedding.js
// 1 index.html
// 在index 加载了gecke 层 shell 提供的web-embedder脚本,它提供了 WebEmbedder
<!-- embedding API provider -->
<script src="chrome://b2g/content/embedding/web-embedder.js"></script>
// 2 在 中使用了WebEmbedder实例embedder,并放到了window
const embedder = new WebEmbedder({
windowProvider,
processSelector,
notifications,
imeHandler,
activityChooser,
webExtensions,
eme,
});
windowProvider
todo
WindowManager
link [Nutria] - System App 分析 - WindowManager
PowerManagement
link [Nutria] - System App PowerManagement
ContentWindow
[Nutria] - System App 分析 - WindowManager
其他模块 (正在更新)
window 挂载点
config={
platform,
metaOrControl,
ftuDone
}
lockscreen
embedder
wm
processManager
apiDaemon
PowerManagement
QA
Q:System App 是没有csp限制的? or core app 是没有csp限制的?
A:System App 是可以通过ChromeUtils.import方法获取gecko的jsm服务
const { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
let isDevice = AppConstants.platform === "gonk";
(function () {
const { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm"
);
Services.obs.notifyObservers(null, "force-gmp-provider-startup", null);
})();