40 |
--------------------------------------------------------------------------------
/docs/docs/about/current-limitations.md:
--------------------------------------------------------------------------------
1 | # Current Limitations
2 |
3 |
9 |
10 | These are things that I would like to fix eventually, but will currently stay, either
11 | because they are too hard to fix, I don't know how to fix them, or would require modifying
12 | the Firefox source. You can check the full list of issues on [GitHub Projects][link-projects]
13 | page. I will appreciate any help to fix them.
14 |
15 | ## All web apps are merged with the first one that was opened (macOS)
16 |
17 | When some web app is already running, all newly launched web apps will merge with it
18 | and remain merged until all of them are closed. This will cause the app menu to display
19 | all web apps as part of the first web app that has been launched, with its icon and
20 | desktop actions.
21 |
22 | This happens because Apple only allows a process to be associated with a single
23 | application at all times. Perhaps this could be solved by using an IPC link between
24 | a host process and the main Firefox runtime process, the same way the Firefox parent
25 | process handles its content processes. This is just a wild theory though and has to be
26 | investigated further.
27 |
28 | This issue can be prevented by installing each web app into a different profile,
29 | which is the default behavior on macOS.
30 |
31 | Check [this comment][link-merged-comment] and related discussions for ideas
32 | and possible solutions for fixing this. This problem is tracked as issue [#81]
33 | [link-merged-issue].
34 |
35 |
36 | ## Extension cannot detect the native program when using sandboxed Firefox (Linux Flatpak)
37 |
38 | When using Firefox distributed as a Flatpak package, the extension cannot detect the
39 | native program that is used. This is because Flatpak packages are sandboxed and cannot
40 | access/run other programs which is needed for Native Messaging API. This cannot be fixed
41 | until Native Messaging API gets support to work in sandboxed browser packages.
42 |
43 | The workaround for this is to uninstall Flatpak-based Firefox and install a normal DEB
44 | package instead. See [#76][link-flatpak-issue] for more details.
45 |
46 | Previously, this problem was also present on Snap, but it has been fixed recently. If
47 | you still cannot detect the native program, you can check out [the dedicated FAQ entry](../help/faq.md#why-doesnt-the-extension-find-the-native-connector-on-linux)
48 | about common problems on Linux.
49 |
50 | ## Web apps do not remember previous window positions and restore sessions
51 |
52 | When multiple web apps are installed in the same profile, individual web apps do not
53 | remember their previous window positions and sizes. This makes it hard to automatically
54 | open a web app with s specific window position and size.
55 |
56 | This happens because Firefox tracks window positions globally (per profile), and it
57 | is hard to change that using only UserChrome scripts. See [#256][link-session-issue]
58 | for more details.
59 |
60 | The workaround for this is to install each web app into a different profile.
61 |
62 | [link-projects]: https://github.com/users/filips123/projects/1/views/1?filterQuery=status%3A%22On+Hold%22
63 | [link-merged-comment]: https://github.com/filips123/PWAsForFirefox/issues/33#issuecomment-888511078
64 | [link-merged-issue]: https://github.com/filips123/PWAsForFirefox/issues/81
65 | [link-flatpak-issue]: https://github.com/filips123/PWAsForFirefox/issues/76
66 | [link-session-issue]: https://github.com/filips123/PWAsForFirefox/issues/256
67 |
--------------------------------------------------------------------------------
/docs/docs/about/how-it-works.md:
--------------------------------------------------------------------------------
1 | # How It Works
2 |
3 | The project consists of three parts, the browser extension, the native program, and the
4 | UserChrome browser modifications. These parts are seamlessly integrated together to make
5 | the whole project work. The extension provides in-browser instructions for installation
6 | of the native program, which also installs the UserChrome modifications.
7 |
8 | This page can be useful for those who want a bit better understanding of how the project
9 | works and how it is implemented.
10 |
11 | ## Extension
12 |
13 | The browser extension is the main interface users will be facing when using the project.
14 | It provides a convenient way of installing, editing, and removing sites and profiles
15 | directly from their main browser. However, since [browser extensions][link-webextensions]
16 | are limited and cannot directly access the operating system, which is needed for the
17 | installation of web apps, the project uses [Native messaging API][link-native-messaging]
18 | for communication with the native program.
19 |
20 | [link-webextensions]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions
21 | [link-native-messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging
22 |
23 | ## Native Program
24 |
25 | The native program is written in [Rust][link-rust] and handles features that the extension
26 | alone cannot do. It communicates with the extension using a native messaging protocol.
27 | Features of the native program include installing Firefox runtime, patching it with the
28 | UserChrome modifications, installing the sites, applying the system integration, and
29 | launching them.
30 |
31 | The native program also provides a command-line program for users that prefer CLI to GUI.
32 |
33 | [link-rust]: https://www.rust-lang.org/
34 |
35 | ## UserChrome Modifications
36 |
37 | The remaining part of the project is modifying Firefox UI to make a better app-like feel.
38 | This is done using [UserChromeJS (Autoconfig Startup Scripting)][link-userchromejs]
39 | modifications that can execute *low-level* JavaScript code that can modify Firefox UI.
40 | These modifications hide the address bar and tabs, move some browser buttons, provide
41 | additional useful widgets and settings and handle PWA scope and system integration.
42 |
43 | [link-userchromejs]: https://www.userchrome.org/what-is-userchrome-js.html
44 |
--------------------------------------------------------------------------------
/docs/docs/about/privacy-policy.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy
2 |
3 | ## Extension Privacy Policy
4 |
5 | The extension exchanges personal data (current website and manifest URLs, as well as other
6 | PWA details) with the native program when the user initiates the web app installation.
7 | This is necessary in order to correctly obtain and parse the Web Application Manifest and
8 | install the web app. Data are stored on the computer as long as that web app is installed.
9 | No personal data leave the computer or are sent to third parties.
10 |
11 | ## Runtime Privacy Policy
12 |
13 | As installed web apps are running inside a Mozilla Firefox browser, you need to agree
14 | to [the Firefox Privacy Notice](https://www.mozilla.org/privacy/firefox/).
15 |
16 | ## Website Privacy Policy
17 |
18 | This website uses or accesses the following third-party services:
19 |
20 | * [Cloudflare Pages](https://www.cloudflare.com/privacypolicy/)
21 | * [Cloudflare Analytics](https://www.cloudflare.com/privacypolicy/)
22 | * [Google Fonts](https://developers.google.com/fonts/faq/privacy)
23 | * [Contrib.rocks](https://contrib.rocks/)
24 | * [Shields.io](https://shields.io/)
25 | * [GitHub](https://docs.github.com/en/site-policy/privacy-policies)
26 |
27 | When opening a page or interacting with the feedback buttons, a request will be made to
28 | our self-hosted service. This requests only includes a page URL and an action (view or
29 | feedback status), without any personal data. Provided data are stored aggregated per page
30 | and day, also without any personal data, and are used to improve the documentation.
31 |
--------------------------------------------------------------------------------
/docs/docs/about/supported-features.md:
--------------------------------------------------------------------------------
1 | # Supported Features
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Available Features
14 |
15 | * Command-line tool to install, manage and run Progressive Web Apps in Firefox.
16 | * Extension to set up native programs, and install, manage and run PWAs and their profiles directly from the main Firefox browser.
17 | * Isolated Firefox installation and profile(s) that store the PWAs.
18 | * Installed PWAs have their own start/app menu entry and taskbar icon, and live in their own window.
19 | * Installed PWAs have no tabs and address bar for a better app-like feel.
20 | * Support for installing all websites as Progressive Web Apps.
21 | * Support for all Firefox addons/extensions and built-in Firefox features.
22 | * Support for automatic (user-triggered) installation and patching of installation and profile(s).
23 |
24 | ## Planned Features
25 |
26 | * Support for more system-related web app manifest features (once they are standardized).
27 |
28 | ## Not Planned Features
29 |
30 | * **Integration into official Firefox code.** This project currently modifies the browser chrome (UI) at runtime using JS and CSS. Although this works, it is officially unsupported by Mozilla and can break with Firefox updates. To contribute features back into the official Firefox code, they would need to be implemented properly with the new chrome page and browser services. Unfortunately, this requires an almost complete rewrite of the project, and I currently don't have enough knowledge and time to do that.
31 |
32 | * **Using the same installation profile for PWAs and normal browsing.** This could make the main browser installation/profile unstable if things break. It would also prevent customizing the PWA profile to work better as a PWA profile, and installing custom addons. If you want to sync data between your main and PWA profile, I recommend using Firefox Account or a third-party sync solution.
33 |
34 | * **Running PWAs installed as Windows APPX/MSIX packages or from Microsoft Store.** They will always use Chromium-based Edge that is installed on Windows 10/11. I'm not sure if it is possible to override this. If it is not too hard and doesn't cause any problems, I may try this in the future.
35 |
36 | * **Support for Chromium-specific APIs (Filesystem, Bluetooth, NFC, USB...).** This would require forking and directly modifying the Firefox source. Also, I'm not sure if giving websites the same privileges as native apps is the best idea...
37 |
--------------------------------------------------------------------------------
/docs/docs/assets/icons/favicon-maskable.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/docs/assets/icons/favicon-monochrome.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/docs/assets/icons/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/docs/assets/icons/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/docs/assets/javascripts/feedback.js:
--------------------------------------------------------------------------------
1 | function sendFeedback (endpoint, page, value) {
2 | fetch(endpoint, {
3 | method: 'POST',
4 | keepalive: true,
5 | headers: {
6 | 'Content-Type': 'application/json'
7 | },
8 | body: JSON.stringify({
9 | 'page': page,
10 | 'value': value
11 | })
12 | }).catch(() => {})
13 | }
14 |
15 | document.addEventListener('DOMContentLoaded', function () {
16 | // Check if analytics are enabled and get the endpoint
17 | if (!document.getElementById('__analytics')) return
18 | const endpoint = JSON.parse(document.getElementById('__analytics').innerText).feedback
19 |
20 | document$.subscribe(function () {
21 | // Check if the feedback form is displayed
22 | const feedback = document.forms.feedback
23 | if (!feedback) return
24 |
25 | feedback.addEventListener('submit', function (event) {
26 | event.preventDefault()
27 |
28 | // Retrieve page and feedback value
29 | const page = document.location.pathname
30 | const value = parseInt(event.submitter.getAttribute('data-md-value'))
31 |
32 | // Send the feedback value to the server
33 | sendFeedback(endpoint, page, value)
34 |
35 | // Disable form and show note
36 | feedback.firstElementChild.disabled = true
37 | const note = feedback.querySelector(`.md-feedback__note [data-md-value='${value}']`)
38 | if (note) note.hidden = false
39 | })
40 |
41 | // Show the feedback widget
42 | feedback.hidden = false
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/docs/docs/assets/javascripts/statistics.js:
--------------------------------------------------------------------------------
1 | function sendView (endpoint, page) {
2 | fetch(endpoint, {
3 | method: 'POST',
4 | keepalive: true,
5 | headers: {
6 | 'Content-Type': 'application/json'
7 | },
8 | body: JSON.stringify({
9 | 'page': page
10 | })
11 | }).catch(() => {})
12 | }
13 |
14 | document.addEventListener('DOMContentLoaded', function () {
15 | // Check if analytics are enabled and get the endpoint
16 | if (!document.getElementById('__analytics')) return
17 | const endpoint = JSON.parse(document.getElementById('__analytics').innerText).views
18 |
19 | // Send the initial load view
20 | sendView(endpoint, document.location.pathname)
21 |
22 | // Send instant loading views
23 | location$.subscribe((url) => {
24 | sendView(endpoint, url.pathname)
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/docs/docs/assets/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Progressive Web Apps for Firefox",
3 | "short_name": "PWAsForFirefox",
4 | "description": "A tool to install, manage and use Progressive Web Apps (PWAs) in Mozilla Firefox",
5 | "categories": ["reference", "documentation", "network", "utilities"],
6 | "keywords": ["pwas for firefox", "firefoxpwa", "webapp"],
7 | "theme_color": "#cc3e46",
8 | "start_url": "/",
9 | "scope": "/",
10 | "icons": [
11 | {
12 | "src": "./icons/favicon.svg",
13 | "type": "image/svg+xml",
14 | "sizes": "any"
15 | },
16 | {
17 | "src": "./icons/favicon-maskable.svg",
18 | "type": "image/svg+xml",
19 | "sizes": "any",
20 | "purpose": "maskable"
21 | },
22 | {
23 | "src": "./icons/favicon-monochrome.svg",
24 | "type": "image/svg+xml",
25 | "sizes": "any",
26 | "purpose": "monochrome"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/docs/docs/assets/stylesheets/theme.css:
--------------------------------------------------------------------------------
1 | html {
2 | overscroll-behavior-y: none;
3 | }
4 |
5 | .md-header, .md-tabs {
6 | background-color: #cc3e46;
7 | background-image: linear-gradient(90deg, rgb(255, 60, 97) 0%, rgb(254, 124, 56) 100%);
8 | }
9 |
10 | @media screen {
11 | [data-md-color-scheme="slate"] {
12 | --md-hue: 240;
13 | --md-default-fg-color: hsla(var(--md-hue), 25%, 95%, 1);
14 | --md-default-fg-color--light: hsla(var(--md-hue), 25%, 90%, 0.62);
15 | --md-default-fg-color--lighter: hsla(var(--md-hue), 25%, 90%, 0.32);
16 | --md-default-fg-color--lightest: hsla(var(--md-hue), 25%, 90%, 0.12);
17 | --md-default-bg-color: hsla(var(--md-hue), 7%, 13%, 1);
18 | --md-default-bg-color--light: hsla(var(--md-hue), 7%, 13%, 0.54);
19 | --md-default-bg-color--lighter: hsla(var(--md-hue), 7%, 13%, 0.26);
20 | --md-default-bg-color--lightest: hsla(var(--md-hue), 7%, 13%, 0.07);
21 | --md-code-fg-color: hsla(var(--md-hue), 7%, 90%, 1);
22 | --md-code-bg-color: hsla(var(--md-hue), 7%, 17%, 1);
23 | --md-footer-bg-color: hsla(var(--md-hue), 7%, 10%, 0.87);
24 | --md-footer-bg-color--dark: hsla(var(--md-hue), 7%, 8%, 1);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/docs/docs/help/support.md:
--------------------------------------------------------------------------------
1 | # Getting Support
2 |
3 | If you are having problems with the project, please make sure that you have read the
4 | documentation, especially [the FAQ page](faq.md). Before creating bug reports, please
5 | also check for any similar issues or pull requests. If any of them already exists, please
6 | participle in that one.
7 |
8 | If you cannot determine and fix the problem yourself, please read [our guide for reporting
9 | issues](troubleshooting.md#reporting-issues).
10 |
--------------------------------------------------------------------------------
/docs/docs/installation/extension.md:
--------------------------------------------------------------------------------
1 | # Extension Installation
2 |
3 | ## From Addon Store
4 |
5 | It is recommended to install the extension from [the Firefox Add-ons website][link-addon-store].
6 |
7 | ## From Development Artifacts
8 |
9 | You can download and install [the latest build artifact][link-build-artifact] from GitHub Actions builds.
10 |
11 | !!! warning
12 |
13 | These are development versions that may be unstable and are not signed, so you
14 | will need to configure Firefox to accept non-signed extensions or just load it
15 | temporarily. It is generally not recommended to use them, unless you are testing
16 | a specific unreleased feature.
17 |
18 | ## From Source
19 |
20 | You can read the instructions for the installation from source in [the extension README file][link-extension-readme].
21 |
22 | [link-addon-store]: https://addons.mozilla.org/firefox/addon/pwas-for-firefox/
23 | [link-build-artifact]: https://github.com/filips123/PWAsForFirefox/actions/workflows/extension.yaml
24 | [link-extension-readme]: https://github.com/filips123/PWAsForFirefox/blob/main/extension/README.md#from-source
25 |
--------------------------------------------------------------------------------
/docs/docs/installation/native.md:
--------------------------------------------------------------------------------
1 | # Native Installation
2 |
3 | !!! tip
4 |
5 | The extension should automatically display the installation instructions after
6 | installing it and accepting the licence agreement. If it does not, you can click
7 | the extension widget to display them again. The extension will not work properly
8 | without the native component installed.
9 |
10 | You can read the instructions for the installation from package repositories, release
11 | binaries and source in [the native README file][link-native-readme].
12 |
13 | [link-native-readme]: https://github.com/filips123/PWAsForFirefox/blob/main/native/README.md#installation
14 |
--------------------------------------------------------------------------------
/docs/docs/installation/requirements.md:
--------------------------------------------------------------------------------
1 | # Requirements
2 |
3 | ## Supported Systems
4 |
5 | * Windows (pre-built MSI installer)
6 | * Debian-like Linux (pre-built DEB package)
7 | * Red Hat-like Linux (pre-built RPM package)
8 | * Arch-like Linux (package in `[extra]` repository)
9 | * Gentoo-like Linux (ebuild in GURU overlay)
10 | * NixOS Linux (nixpkgs package)
11 | * Other Linux (source installation only)
12 | * macOS (bottled Homebrew formula)
13 | * BSD (source installation only)[^4]
14 |
15 | ## Extension Requirements
16 |
17 | * Last 2 Firefox versions *OR* Firefox ESR
18 | * Other Firefox-based browsers may also work[^1]
19 |
20 | ## Native Requirements
21 |
22 | * Windows: [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads)
23 | * macOS: Xcode Command Line Tools[^2]
24 | * Linux: `glibc` 2.18 or later[^3]
25 |
26 | [^1]: Check [FAQ](../help/faq.md#how-to-use-an-alternative-browser-as-a-main-browser) for additional setup.
27 | [^2]: Automatically installed if using Homebrew.
28 | [^3]: Automatically installed as a package dependency.
29 | [^4]: Support for BSD relies on XDG Desktop Entry Specification and is not regularly tested.
30 |
--------------------------------------------------------------------------------
/docs/docs/installation/updates.md:
--------------------------------------------------------------------------------
1 | # Updates
2 |
3 | The extension and native versions should be kept in sync to avoid potential problems and
4 | missing features. It is recommended to keep them updated to the newest available version,
5 | unless there are known big bugs in that release.
6 |
7 | As the native program cannot perform automatic updates, there are two options for keeping
8 | it up to date. The first one is to manually update the native program when the extension
9 | updates. When extension detects an outdated native program, it will display a notification
10 | with update instructions.
11 |
12 | On supported platforms, you can also install the native program with the supported package
13 | managers and manage updates through it. Please keep in mind that some package managers
14 | might have delayed releases.
15 |
--------------------------------------------------------------------------------
/docs/docs/resources/profile-properties.md:
--------------------------------------------------------------------------------
1 | # Profile Properties
2 |
3 | ## Name
4 |
5 | A profile name. Displayed in the extension and console.
6 |
7 | ## Description
8 |
9 | A profile description. Displayed in the extension and console.
10 |
11 | ## Template
12 |
13 | A template directory. If specified, all contents of the provided template directory will
14 | be copied to a newly-created or edited profile. This is useful if you want to create a
15 | new profile with the same extensions, settings, etc. as an existing one.
16 |
17 | This is not *a real property*. It only exists when creating a new profile or editing an
18 | existing one, and cannot be changed afterward, as copying from a template is a one-time
19 | operation.
20 |
--------------------------------------------------------------------------------
/docs/docs/resources/web-app-properties.md:
--------------------------------------------------------------------------------
1 | # Web App Properties
2 |
3 | ## Name
4 |
5 | A web app name. Used as an application name in the system menus.
6 |
7 | !!! warning
8 |
9 | You cannot re-use the same name for multiple web apps, because newer ones can overwrite
10 | menu entries for existing web apps. You should also be careful not to re-use the name
11 | of an existing native app, because it can also overwrite its menu entry.
12 |
13 | You cannot install multiple instances of the same web app in the same profile,
14 | because they would actually be the same instance. Instead, install each instance
15 | into a separate profile.
16 |
17 | ## Description
18 |
19 | A web app description. Used as an application description in the system menus.
20 |
21 | ## (Menu) Categories
22 |
23 | On Linux, macOS and PortableApps.com, web app categories are mapped to appropriate
24 | categories for that platform. For example, on Linux, the categories determine in which
25 | menu categories the app appears (on DEs that support menu categories). On Windows,
26 | categories are not supported and are ignored, but they can still be used for user
27 | organization. On macOS and PortableApps.com, the application can have only one category,
28 | so only the first one is used.
29 |
30 | ## (Menu) Keywords
31 |
32 | Keywords are used as additional search queries on Linux. On other platforms, keywords
33 | are not supported and are ignored, but they can still be used for user organization.
34 |
35 | ## Start URL
36 |
37 | A URL that is opened when the web app is launched. If not specified, the default start
38 | URL is used.
39 |
40 | ## Icon URL
41 |
42 | A URL of the icon that is used as an application icon. If not specified, the default
43 | icons are used.
44 |
45 | ## Protocol Handlers
46 |
47 | Determine which supported protocol handlers are enabled for that web app.
48 |
49 | By default, all protocol handlers specified in the web app manifest are disabled. Some
50 | websites also dynamically register protocol handlers; those are enabled automatically if
51 | you accept the Firefox prompt.
52 |
53 | ## Auto Launch Settings
54 |
55 | ### Launch this web app on matching website
56 |
57 | If enabled, all URLs that match the scopes of your web app will be automatically
58 | launched as a web app. Specific URLs can also be excluded from being automatically
59 | launched inside web apps with [the exclusion regex option](../user-guide/extension.md#automatic-launching-exclusion)
60 | in the main extension settings.
61 |
62 | This option is only available when [automatic web app launching](../user-guide/extension.md#enable-automatic-web-app-launching)
63 | is enabled in the main extension settings.
64 |
65 | ### Launch this web app on system login
66 |
67 | If enabled, the web app will be automatically launched when you log into the system.
68 |
69 | This option is not available on macOS, as launching on login can easily be enabled directly
70 | from the macOS UI instead.
71 |
72 | ### Launch this web app on browser launch
73 |
74 | If enabled, the web app will be automatically launched when you launch your main browser
75 | (the browser where the extension is installed).
76 |
--------------------------------------------------------------------------------
/docs/docs/robots.txt:
--------------------------------------------------------------------------------
1 | Sitemap: https://pwasforfirefox.filips.si/sitemap.xml
2 | Sitemap: https://pwasforfirefox.filips.si/sitemap.xml.gz
3 |
--------------------------------------------------------------------------------
/docs/hooks/breadcrumbs.py:
--------------------------------------------------------------------------------
1 | """Generate JSON-LD breadcrumbs for documentation pages."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | if TYPE_CHECKING:
8 | from typing import Any
9 | from mkdocs.config.base import MkDocsConfig
10 | from mkdocs.structure.nav import Navigation
11 | from mkdocs.structure.pages import Page
12 |
13 |
14 | def on_page_context(context: dict[str, Any], page: Page, config: MkDocsConfig, nav: Navigation):
15 | if not page.ancestors:
16 | return
17 |
18 | elements = [{
19 | "@type": "ListItem",
20 | "position": 1,
21 | "name": "Home",
22 | "item": config.site_url,
23 | }]
24 |
25 | position = 2
26 |
27 | for ancestor in page.ancestors[::-1]:
28 | name = ancestor.title
29 |
30 | while ancestor.children:
31 | ancestor = ancestor.children[0]
32 |
33 | url = ancestor.canonical_url
34 |
35 | elements.append({
36 | "@type": "ListItem",
37 | "position": position,
38 | "name": name,
39 | "item": url,
40 | })
41 |
42 | position += 1
43 |
44 | elements.append({
45 | "@type": "ListItem",
46 | "position": position,
47 | "name": page.title,
48 | "item": page.canonical_url,
49 | })
50 |
51 | if "schema" not in page.meta:
52 | page.meta["schema"] = []
53 |
54 | if not isinstance(page.meta["schema"], list):
55 | page.meta["schema"] = [page.meta["schema"]]
56 |
57 | page.meta["schema"].append({
58 | "@context": "https://schema.org",
59 | "@type": "BreadcrumbList",
60 | "itemListElement": elements,
61 | })
62 |
--------------------------------------------------------------------------------
/docs/hooks/faq.py:
--------------------------------------------------------------------------------
1 | """Generate the microdata schema for the FAQ page."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from bs4 import BeautifulSoup
8 |
9 | if TYPE_CHECKING:
10 | from typing import Any
11 | from mkdocs.config.base import MkDocsConfig
12 | from mkdocs.structure.nav import Navigation
13 | from mkdocs.structure.pages import Page
14 |
15 |
16 | def construct(document, container, question, answer):
17 | if not question or not answer:
18 | return
19 |
20 | # Move question text into span, so the paragraph sign is not copied to microdata
21 | name = document.new_tag("span", itemprop="name")
22 | for child in list(question.children):
23 | if child.name == "a" and "headerlink" in child.get("class", []):
24 | continue
25 | name.append(child.extract())
26 | question.insert(0, name)
27 |
28 | # Construct the accepted answer from the source elements
29 | accepted = document.new_tag("div", itemscope="", itemprop="acceptedAnswer", itemtype="https://schema.org/Answer")
30 | text = document.new_tag("div", itemprop="text")
31 | text.extend(answer)
32 | accepted.append(text)
33 |
34 | # Create an question entry element and append question and accepted answer
35 | entry = document.new_tag("div", itemscope="", itemprop="mainEntity", itemtype="https://schema.org/Question")
36 | entry.append(question)
37 | entry.append(accepted)
38 | container.append(entry)
39 |
40 |
41 | def on_page_context(context: dict[str, Any], page: Page, config: MkDocsConfig, nav: Navigation):
42 | if not page.url == "help/faq/":
43 | return
44 |
45 | original = BeautifulSoup(page.content, features="lxml")
46 | modified = BeautifulSoup("", features="lxml")
47 |
48 | # All questions and answers need to be inside the FAQPage container
49 | container = modified.new_tag("div", itemscope="", itemtype="https://schema.org/FAQPage")
50 | modified.append(container)
51 |
52 | question = None
53 | answer = []
54 |
55 | for element in list(original.body.children):
56 | # Copy styles and scripts to the target
57 | if element.name in ("style", "script", "h1"):
58 | container.insert_before(element)
59 |
60 | # Parse section and question headings
61 | if element.name in ("h2", "h3"):
62 | # Construct the previous question and reset parser
63 | construct(modified, container, question, answer)
64 | question = None
65 | answer = []
66 |
67 | if element.name == "h2":
68 | # Copy the section heading to the container
69 | container.append(element)
70 |
71 | elif element.name == "h3":
72 | # Copy the question to the parser
73 | question = element
74 |
75 | continue
76 |
77 | # Copy the answer to the parser
78 | answer.append(element)
79 |
80 | # Construct the final question
81 | construct(modified, container, question, answer)
82 |
83 | # Replace the page content
84 | page.content = str(modified)
85 |
--------------------------------------------------------------------------------
/docs/hooks/home.py:
--------------------------------------------------------------------------------
1 | """Generate JSON-LD schema for the homepage."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 | from urllib.parse import urljoin
7 |
8 | if TYPE_CHECKING:
9 | from typing import Any
10 | from mkdocs.config.base import MkDocsConfig
11 | from mkdocs.structure.nav import Navigation
12 | from mkdocs.structure.pages import Page
13 |
14 |
15 | def on_page_context(context: dict[str, Any], page: Page, config: MkDocsConfig, nav: Navigation):
16 | if not page.is_homepage:
17 | return
18 |
19 | common = {
20 | "name": "Progressive Web Apps for Firefox",
21 | "alternateName": ["PWAsForFirefox", "FirefoxPWA"],
22 | "description": config.site_description,
23 | "image": urljoin(config.site_url, "assets/icons/favicon.svg"),
24 | "url": config.site_url,
25 | "sameAs": [
26 | "https://github.com/filips123/PWAsForFirefox",
27 | "https://addons.mozilla.org/firefox/addon/pwas-for-firefox",
28 | ],
29 | }
30 |
31 | website = {
32 | "@context": "https://schema.org",
33 | "@type": "WebSite",
34 | **common,
35 | "potentialAction": {
36 | "@type": "SearchAction",
37 | "target": {
38 | "@type": "EntryPoint",
39 | "urlTemplate": urljoin(config.site_url, "?q={search_term_string}"),
40 | },
41 | "query-input": "required name=search_term_string",
42 | },
43 | }
44 |
45 | application = {
46 | "@context": "https://schema.org",
47 | "@type": "SoftwareApplication",
48 | **common,
49 | "installUrl": "https://addons.mozilla.org/firefox/addon/pwas-for-firefox",
50 | "releaseNotes": "https://github.com/filips123/PWAsForFirefox/releases",
51 | "license": "https://github.com/filips123/PWAsForFirefox#license",
52 | "applicationCategory": ["UtilitiesApplication", "BrowserApplication"],
53 | "operatingSystem": ["Windows", "Linux", "macOS"],
54 | "softwareHelp": [
55 | {
56 | "@type": "Webpage",
57 | "url": config.site_url,
58 | },
59 | {
60 | "@type": "Webpage",
61 | "url": "https://github.com/filips123/PWAsForFirefox",
62 | }
63 | ],
64 | "hasPart": [
65 | {
66 | "@type": "CreativeWork",
67 | "name": "PWAsForFirefox Extension",
68 | "url": [
69 | "https://addons.mozilla.org/firefox/addon/pwas-for-firefox",
70 | "https://github.com/filips123/PWAsForFirefox/tree/main/extension",
71 | ]
72 | },
73 | {
74 | "@type": "CreativeWork",
75 | "name": "PWAsForFirefox Native",
76 | "url": [
77 | "https://repology.org/project/firefoxpwa",
78 | "https://packagecloud.io/filips/FirefoxPWA",
79 | "https://github.com/filips123/PWAsForFirefox/tree/main/native",
80 | ]
81 | }
82 | ],
83 | "offers": {
84 | "@type": "Offer",
85 | "price": "0",
86 | "priceCurrency": "USD",
87 | },
88 | "subjectOf": {
89 | "@type": "WebSite",
90 | "url": "./",
91 | },
92 | }
93 |
94 | if "schema" not in page.meta:
95 | page.meta["schema"] = []
96 |
97 | if not isinstance(page.meta["schema"], list):
98 | page.meta["schema"] = [page.meta["schema"]]
99 |
100 | page.meta["schema"].extend([
101 | website,
102 | application,
103 | ])
104 |
--------------------------------------------------------------------------------
/docs/overrides/404.html:
--------------------------------------------------------------------------------
1 | {% extends "main.html" %}
2 |
3 | {% block htmltitle %}
4 | Not Found - {{ config.site_name }}
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
404 - Not Found
9 |
The page that you requested was not found. The page might have been moved or deleted. You can try to find it with the search or return to the homepage.
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/docs/overrides/main.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block extrahead %}
4 | {# Include web app manifest #}
5 |
6 |
7 | {# Include releases and commits feeds #}
8 |
9 |
10 |
11 | {% if page and page.is_homepage %}
12 | {# Prececonnect to the shields.io website for badges #}
13 |
14 |
15 | {# Set custom social title for the homepage #}
16 |
17 |
18 | {% endif %}
19 |
20 | {% if page and page.meta and page.meta.schema %}
21 | {# Support including JSON-LD schema #}
22 |
23 | {% endif %}
24 |
25 | {% if config.extra.analytics.enabled %}
26 | {# Store configuration for page view analytics #}
27 |
28 | {% endif %}
29 | {% endblock %}
30 |
--------------------------------------------------------------------------------
/docs/requirements.in:
--------------------------------------------------------------------------------
1 | mkdocs
2 | mkdocs-material
3 | mkdocs-minify-plugin
4 | mkdocs-macros-plugin
5 | beautifulsoup4[lxml]
6 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by pip-compile with Python 3.12
3 | # by the following command:
4 | #
5 | # pip-compile
6 | #
7 | babel==2.16.0
8 | # via mkdocs-material
9 | beautifulsoup4[lxml]==4.12.3
10 | # via -r requirements.in
11 | certifi==2024.12.14
12 | # via requests
13 | charset-normalizer==3.4.1
14 | # via requests
15 | click==8.1.8
16 | # via mkdocs
17 | colorama==0.4.6
18 | # via
19 | # click
20 | # mkdocs
21 | # mkdocs-material
22 | csscompressor==0.9.5
23 | # via mkdocs-minify-plugin
24 | ghp-import==2.1.0
25 | # via mkdocs
26 | hjson==3.1.0
27 | # via
28 | # mkdocs-macros-plugin
29 | # super-collections
30 | htmlmin2==0.1.13
31 | # via mkdocs-minify-plugin
32 | idna==3.10
33 | # via requests
34 | jinja2==3.1.5
35 | # via
36 | # mkdocs
37 | # mkdocs-macros-plugin
38 | # mkdocs-material
39 | jsmin==3.0.1
40 | # via mkdocs-minify-plugin
41 | lxml==5.3.0
42 | # via beautifulsoup4
43 | markdown==3.7
44 | # via
45 | # mkdocs
46 | # mkdocs-material
47 | # pymdown-extensions
48 | markupsafe==3.0.2
49 | # via
50 | # jinja2
51 | # mkdocs
52 | mergedeep==1.3.4
53 | # via
54 | # mkdocs
55 | # mkdocs-get-deps
56 | mkdocs==1.6.1
57 | # via
58 | # -r requirements.in
59 | # mkdocs-macros-plugin
60 | # mkdocs-material
61 | # mkdocs-minify-plugin
62 | mkdocs-get-deps==0.2.0
63 | # via mkdocs
64 | mkdocs-macros-plugin==1.3.7
65 | # via -r requirements.in
66 | mkdocs-material==9.5.49
67 | # via -r requirements.in
68 | mkdocs-material-extensions==1.3.1
69 | # via mkdocs-material
70 | mkdocs-minify-plugin==0.8.0
71 | # via -r requirements.in
72 | packaging==24.2
73 | # via
74 | # mkdocs
75 | # mkdocs-macros-plugin
76 | paginate==0.5.7
77 | # via mkdocs-material
78 | pathspec==0.12.1
79 | # via
80 | # mkdocs
81 | # mkdocs-macros-plugin
82 | platformdirs==4.3.6
83 | # via mkdocs-get-deps
84 | pygments==2.18.0
85 | # via mkdocs-material
86 | pymdown-extensions==10.13
87 | # via mkdocs-material
88 | python-dateutil==2.9.0.post0
89 | # via
90 | # ghp-import
91 | # mkdocs-macros-plugin
92 | pyyaml==6.0.2
93 | # via
94 | # mkdocs
95 | # mkdocs-get-deps
96 | # mkdocs-macros-plugin
97 | # pymdown-extensions
98 | # pyyaml-env-tag
99 | pyyaml-env-tag==0.1
100 | # via mkdocs
101 | regex==2024.11.6
102 | # via mkdocs-material
103 | requests==2.32.3
104 | # via mkdocs-material
105 | six==1.17.0
106 | # via python-dateutil
107 | soupsieve==2.6
108 | # via beautifulsoup4
109 | super-collections==0.5.3
110 | # via mkdocs-macros-plugin
111 | termcolor==2.5.0
112 | # via mkdocs-macros-plugin
113 | urllib3==2.3.0
114 | # via requests
115 | watchdog==6.0.0
116 | # via mkdocs
117 |
--------------------------------------------------------------------------------
/extension/.browserslistrc:
--------------------------------------------------------------------------------
1 | last 2 Firefox version
2 | Firefox ESR
3 |
--------------------------------------------------------------------------------
/extension/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "webextensions": true,
4 | "browser": true,
5 | "es2021": true
6 | },
7 | "extends": [
8 | "standard"
9 | ],
10 | "parserOptions": {
11 | "ecmaVersion": 12,
12 | "sourceType": "module"
13 | },
14 | "plugins": [
15 | "simple-import-sort"
16 | ],
17 | "rules": {
18 | "simple-import-sort/imports": "error",
19 | "simple-import-sort/exports": "error"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/extension/.parcelrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@parcel/config-webextension",
3 | "resolvers": ["@parcel/resolver-glob", "..."],
4 | "transformers": {
5 | "filename:*": ["./tools/transformers/filename", "..."],
6 | "locale:*": ["./tools/transformers/locale", "@parcel/transformer-json", "@parcel/transformer-js"],
7 | "raw:messages.json": ["./tools/transformers/locale", "./tools/transformers/treeshake"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/extension/README.md:
--------------------------------------------------------------------------------
1 | Progressive Web Apps for Firefox - Extension
2 | ============================================
3 |
4 | The extension part of the PWAsForFirefox project.
5 |
6 | ## Description
7 |
8 | The extension part of the project makes it easier to install and manage Progressive Web Apps directly from the main Firefox browser. It supports installing supported PWAs with just a few clicks, managing and launching them, and creating and managing app profiles directly from the UI.
9 |
10 | Read [the main README file](../README.md) for more details about the project.
11 |
12 | ## Installation
13 |
14 | ### From Addon Store
15 |
16 | It is recommended to install the extension from [the Firefox Add-ons website](https://addons.mozilla.org/firefox/addon/pwas-for-firefox/).
17 |
18 | ### From Development Artifacts
19 |
20 | You can download and install [the latest build artifact](https://github.com/filips123/PWAsForFirefox/actions/workflows/extension.yaml) from GitHub Actions builds.
21 |
22 | Note that these are development versions that may be unstable and are not signed, so you will need to configure Firefox to accept non-signed extensions or just load it temporarily. It is generally not recommended to use them, unless you are testing a specific unreleased feature.
23 |
24 | ### From Source
25 |
26 | 1. Install Node.js and Yarn package manager.
27 |
28 | 2. Clone the repository and cd into the `extension` (this) directory.
29 |
30 | 3. Run `yarn install` to install the dependencies.
31 |
32 | 4. If building a specific version:
33 | 1. Checkout the correct Git tag.
34 | 2. Run `yarn set-version` to add the version information to the configuration files.
35 |
36 | 5. Either:
37 |
38 | a. Run `yarn build` to build the extension in release mode and package it.
39 |
40 | b. Run `yarn watch` to build the extension in development mode and automatically rebuild it on any changes.
41 |
42 | 6. Either:
43 |
44 | a. Install the packaged extension from `dist/firefoxpwa-{version}-compiled.zip` in `about:debugging`.
45 |
46 | b. Install the development extension from `dist/manifest.json` in `about:debugging`.
47 |
48 | ## Usage
49 |
50 | You can read [our documentation website](https://pwasforfirefox.filips.si/user-guide/extension/) for usage instructions.
51 |
52 | ## Contributing
53 |
54 | Please make sure that your JS code is properly linted and formatted using `yarn lint` (to check the code) and `yarn fix` (to automatically apply some fixes).
55 |
--------------------------------------------------------------------------------
/extension/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "firefoxpwa",
3 | "description": "The browser extension part of the PWAsForFirefox project",
4 | "license": "MPL-2.0",
5 | "version": "0.0.0",
6 | "homepage": "https://pwasforfirefox.filips.si/",
7 | "repository": "https://github.com/filips123/PWAsForFirefox",
8 | "bugs": "https://github.com/filips123/PWAsForFirefox/issues",
9 | "funding": "https://github.com/filips123/PWAsForFirefox?sponsor=1",
10 | "author": "filips ",
11 | "private": true,
12 | "keywords": [
13 | "firefox",
14 | "progressive-web-app",
15 | "site-specific-browser",
16 | "pwa"
17 | ],
18 | "scripts": {
19 | "watch": "run-s prepare:* watch:*",
20 | "watch:parcel": "parcel watch src/manifest.json src/{background,content}.js src/**/*.{html,svg} --no-content-hash",
21 | "build": "run-s prepare:* build:*",
22 | "build:parcel": "parcel build src/manifest.json src/{background,content}.js src/**/*.{html,svg} --no-content-hash --no-source-maps",
23 | "build:webext": "web-ext build -s dist -a dist -n firefoxpwa-{version}-compiled.zip",
24 | "lint": "run-s -c lint:*",
25 | "lint:eslint": "eslint src tools",
26 | "lint:webext": "web-ext lint -s src",
27 | "fix": "run-s -c fix:*",
28 | "fix:eslint": "eslint --fix src tools",
29 | "prepare:clean": "rimraf dist .parcel-cache",
30 | "prepare:icons": "node ./tools/icons/generate.js",
31 | "set-version": "node ./tools/set-version.js"
32 | },
33 | "packageManager": "yarn@1.22.22",
34 | "dependencies": {
35 | "@popperjs/core": "^2.11.8",
36 | "base64-js": "^1.5.1",
37 | "bootstrap": "^5.3.3",
38 | "bootstrap-icons": "^1.11.3",
39 | "bootstrap5-tags": "^1.7.6",
40 | "dompurify": "^3.2.4",
41 | "iframe-resizer": "4.4.2",
42 | "semver": "^7.7.1"
43 | },
44 | "devDependencies": {
45 | "@parcel/config-webextension": "^2.13.3",
46 | "@parcel/plugin": "^2.13.3",
47 | "@parcel/resolver-glob": "^2.13.3",
48 | "@parcel/transformer-raw": "^2.13.3",
49 | "@parcel/transformer-sass": "^2.13.3",
50 | "@twbs/fantasticon": "^3.0.0",
51 | "eslint": "^8.57.1",
52 | "eslint-config-standard": "^17.1.0",
53 | "eslint-plugin-import": "^2.31.0",
54 | "eslint-plugin-n": "^17.15.1",
55 | "eslint-plugin-promise": "^7.2.1",
56 | "eslint-plugin-simple-import-sort": "^12.1.1",
57 | "npm-run-all": "^4.1.5",
58 | "parcel": "^2.13.3",
59 | "rimraf": "^6.0.1",
60 | "svgo": "^3.3.2",
61 | "web-ext": "^8.4.0"
62 | },
63 | "resolutions": {
64 | "jackspeak": "2.1.1",
65 | "sass": "1.77.6"
66 | },
67 | "icons": [
68 | "box-arrow-up-right",
69 | "check",
70 | "clipboard-check",
71 | "cloud-download",
72 | "download",
73 | "gear-fill",
74 | "grid-3x3-gap-fill",
75 | "pencil-square",
76 | "plus-lg",
77 | "trash"
78 | ],
79 | "messages": [
80 | "appName",
81 | "appShortName",
82 | "appDescription",
83 | "actionInstallSite",
84 | "actionLaunchSite",
85 | "updateNotificationTitle",
86 | "updateNotificationMessage"
87 | ],
88 | "alias": {
89 | "process": false
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/extension/src/_locales/uk/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appName": {
3 | "message": "Progressive Web Apps for Firefox",
4 | "description": "The name of the application, should not be translated"
5 | },
6 | "appShortName": {
7 | "message": "PWAsForFirefox",
8 | "description": "The short name of the application, should not be translated"
9 | },
10 | "appDescription": {
11 | "message": "Інструмент для встановлення, керування та використання прогресивних вебзастосунків (Progressive Web Apps) у Mozilla Firefox",
12 | "description": "The description of the application"
13 | },
14 | "actionInstallSite": {
15 | "message": "Встановити цей сайт",
16 | "description": "Instruct users that they can install the current site here"
17 | },
18 | "actionLaunchSite": {
19 | "message": "Запустити цей сайт",
20 | "description": "Instruct users that they can launch the current site here"
21 | },
22 | "updateNotificationTitle": {
23 | "message": "Оновлення PWAsForFirefox",
24 | "description": "The title of the update notification, displayed when an update is available"
25 | },
26 | "updateNotificationMessage": {
27 | "message": "Доступне PWAsForFirefox. Натисніть на сповіщення, щоб показати інструкції оновлення.",
28 | "description": "The message of the update notification, displayed when an update is available"
29 | },
30 | "commonError": {
31 | "message": "Помилка",
32 | "description": "Displayed before error messages or as a popup title"
33 | },
34 | "commonWarning": {
35 | "message": "Попередження",
36 | "description": "Displayed before warning messages or as a popup title"
37 | },
38 | "commonNote": {
39 | "message": "Примітка",
40 | "description": "Displayed before note messages or as a popup title"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/extension/src/content.js:
--------------------------------------------------------------------------------
1 | const isAppleMaskIcon = link => link.getAttribute('rel').toLowerCase().includes('mask-icon')
2 |
3 | function getIconType (link) {
4 | const type = link.getAttribute('type')
5 | if (type) return type.includes('/') ? type : `image/${type}`
6 | else return isAppleMaskIcon(link) ? 'image/svg+xml' : null
7 | }
8 |
9 | function getIconPurpose (link) {
10 | return isAppleMaskIcon(link) ? 'monochrome' : 'any'
11 | }
12 |
13 | // Obtain the initial web app manifest URL
14 | const manifestElement = document.querySelector('link[rel=manifest]')
15 | const manifestUrl = manifestElement ? new URL(manifestElement.getAttribute('href'), document.baseURI) : null
16 |
17 | // Send the secure context state, initial manifest and document URLs on the page load
18 | browser.runtime.sendMessage({ manifestUrl: manifestUrl?.href, documentUrl: document.location.href, isSecureContext })
19 |
20 | // Send the current manifest and document URLs on request
21 | browser.runtime.onMessage.addListener((message, _, sendResponse) => {
22 | // Ignore invalid messages
23 | if (message !== 'ObtainUrls') return
24 |
25 | // Collect the current web app manifest URL
26 | const manifestElement = document.querySelector('link[rel=manifest]')
27 | const manifestUrl = manifestElement ? new URL(manifestElement.getAttribute('href'), document.baseURI) : null
28 |
29 | // Collect page info that can be used if the manifest does not exist
30 | const pageInfo = {
31 | name: document.querySelector('meta[name=application-name]')?.content || document.title,
32 | description: document.querySelector('meta[name=description]')?.content,
33 | icons: [...document.getElementsByTagName('link')]
34 | .filter(link => link.getAttribute('rel')?.toLowerCase().includes('icon'))
35 | .map(link => ({
36 | src: new URL(link.getAttribute('href'), document.baseURI).href,
37 | type: getIconType(link),
38 | purpose: getIconPurpose(link),
39 | sizes: link.getAttribute('sizes') || ''
40 | }))
41 | }
42 |
43 | // Send a response with the URLs and page info
44 | sendResponse({ manifestUrl: manifestUrl?.href, documentUrl: document.location.href, pageInfo })
45 | })
46 |
--------------------------------------------------------------------------------
/extension/src/images/addon-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/extension/src/images/browser-action.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/extension/src/images/page-action-install.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/extension/src/images/page-action-launch.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/extension/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "__MSG_appName__",
4 | "short_name": "__MSG_appShortName__",
5 | "description": "__MSG_appDescription__",
6 | "homepage_url": "https://pwasforfirefox.filips.si/",
7 | "version": "0.0.0",
8 | "default_locale": "en",
9 | "browser_specific_settings": {
10 | "gecko": {
11 | "id": "firefoxpwa@filips.si"
12 | }
13 | },
14 | "icons": {
15 | "48": "images/addon-logo.svg",
16 | "96": "images/addon-logo.svg",
17 | "192": "images/addon-logo.svg"
18 | },
19 | "background": {
20 | "scripts": ["background.js"]
21 | },
22 | "content_scripts": [
23 | {
24 | "js": ["content.js"],
25 | "matches": ["http://*/*", "https://*/*"],
26 | "run_at": "document_end"
27 | }
28 | ],
29 | "browser_action": {
30 | "default_icon": "images/browser-action.svg",
31 | "default_popup": "sites/manage.html"
32 | },
33 | "page_action": {},
34 | "permissions": [
35 | "http://*/*",
36 | "https://*/*",
37 | "nativeMessaging",
38 | "notifications",
39 | "storage"
40 | ],
41 | "optional_permissions": [
42 | "webNavigation",
43 | "webRequest",
44 | "webRequestBlocking"
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/extension/src/setup/install.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////
2 | // Setup Styles
3 | //////////////////////////////
4 |
5 | @import "setup.scss";
6 | @import "../icons/bootstrap-icons.css";
7 |
8 | //////////////////////////////
9 | // Progress Bar
10 | //////////////////////////////
11 |
12 | #progressbar {
13 | margin-top: 20px;
14 | margin-bottom: 30px;
15 | padding: 0;
16 | overflow: hidden;
17 | color: #495057;
18 | @media (prefers-color-scheme: dark) { color: #e1e1e1; }
19 | }
20 |
21 | #progressbar li {
22 | position: relative;
23 | float: left;
24 | width: 25%;
25 | list-style: none;
26 | font-size: 12px;
27 | }
28 |
29 | #progressbar li:before {
30 | display: block;
31 | width: 50px;
32 | height: 50px;
33 | line-height: 45px;
34 | font-size: 18px;
35 | color: white;
36 | border-radius: 50%;
37 | margin: 0 auto 10px auto;
38 | padding: 2px;
39 | }
40 |
41 | #progressbar li:after {
42 | position: absolute;
43 | left: 0;
44 | top: 25px;
45 | content: '';
46 | width: 100%;
47 | height: 2px;
48 | z-index: -1;
49 | }
50 |
51 | #progressbar li:before, #progressbar li:after {
52 | background-color: #6c757d;
53 | }
54 |
55 | #progressbar li.active:before, #progressbar li.active:after {
56 | background-color: #0d6efd;
57 | }
58 |
59 | //////////////////////////////
60 | // Text Utilities
61 | //////////////////////////////
62 |
63 | .text-justify {
64 | text-align: justify;
65 | text-justify: inter-word;
66 | }
67 |
--------------------------------------------------------------------------------
/extension/src/setup/instructions.js:
--------------------------------------------------------------------------------
1 | import 'iframe-resizer/js/iframeResizer.contentWindow'
2 | import '../utils/i18nHtml'
3 |
4 | import Tab from 'bootstrap/js/src/tab'
5 |
6 | import { EVENT_LOCALIZATION_READY } from '../utils'
7 |
8 | async function prepareInstallInstructions () {
9 | const version = browser.runtime.getManifest().version
10 | const { os, arch } = await browser.runtime.getPlatformInfo()
11 |
12 | // Set CRT download URL based on system arch
13 | document.getElementById('connector-download-url-crt').setAttribute('href', `https://aka.ms/vs/16/release/vc_redist.${arch === 'x86-32' ? 'x86' : 'x64'}.exe`)
14 |
15 | // Set MSI download URL based on system arch and extension version
16 | // Currently just relying on x86 emulation for Windows ARM
17 | const msiArch = arch === 'x86-64' ? 'x86_64' : 'x86'
18 | document.getElementById('connector-download-url-msi').setAttribute('href', `https://github.com/filips123/PWAsForFirefox/releases/download/v${version}/firefoxpwa-${version}-${msiArch}.msi`)
19 |
20 | // Set PAF download url based on extension version
21 | document.getElementById('connector-download-url-paf').setAttribute('href', `https://github.com/filips123/PWAsForFirefox/releases/download/v${version}/firefoxpwa_${version}_online.paf.exe`)
22 |
23 | // Set DEB download URL based on system arch and extension version
24 | const debArch = (() => {
25 | switch (arch) {
26 | case 'x86-32':
27 | return 'i386'
28 | case 'x86-64':
29 | return 'amd64'
30 | case 'arm':
31 | return 'armhf'
32 | case 'arm64':
33 | case 'aarch64':
34 | return 'arm64'
35 | default:
36 | return null
37 | }
38 | })()
39 | document.getElementById('connector-download-url-deb').setAttribute('href', `https://github.com/filips123/PWAsForFirefox/releases/download/v${version}/firefoxpwa_${version}_${debArch}.deb`)
40 |
41 | // Set RPM download URL based on system arch and extension version
42 | const rpmArch = (() => {
43 | switch (arch) {
44 | case 'x86-32':
45 | return 'i686'
46 | case 'x86-64':
47 | return 'x86_64'
48 | case 'arm':
49 | return 'armv7hl'
50 | case 'arm64':
51 | case 'aarch64':
52 | return 'aarch64'
53 | default:
54 | return null
55 | }
56 | })()
57 | document.getElementById('connector-download-url-rpm').setAttribute('href', `https://github.com/filips123/PWAsForFirefox/releases/download/v${version}/firefoxpwa-${version}-1.${rpmArch}.rpm`)
58 |
59 | // Set repository info based on extension version
60 | for (const elem of document.getElementsByClassName('connector-repository-tag')) elem.innerText = `v${version}`
61 | for (const elem of document.getElementsByClassName('connector-project-version')) elem.innerText = version
62 |
63 | // Link to the specific version for the install script
64 | const branchName = version === '0.0.0' ? 'main' : `v${version}`
65 | document.getElementById('connector-source-install').setAttribute('href', `https://github.com/filips123/PWAsForFirefox/tree/${branchName}/native#from-source`)
66 |
67 | // Hide DEB and RPM tabs on unsupported platforms
68 | if (debArch === null) document.getElementById('linux-deb-install-tab').classList.add('d-none')
69 | if (rpmArch === null) document.getElementById('linux-rpm-install-tab').classList.add('d-none')
70 |
71 | // Set the default tab to the current OS
72 | let defaultTab
73 |
74 | if (os === 'win') {
75 | defaultTab = 'windows'
76 | } else if (os === 'linux') {
77 | defaultTab = debArch ? 'linux-deb' : 'source'
78 | } else if (os === 'mac') {
79 | defaultTab = 'macos'
80 | } else if (os === 'openbsd') {
81 | defaultTab = 'bsd'
82 | } else {
83 | defaultTab = 'other'
84 | }
85 |
86 | new Tab(document.getElementById(`${defaultTab}-install-tab`)).show()
87 | }
88 |
89 | document.addEventListener(EVENT_LOCALIZATION_READY, prepareInstallInstructions)
90 |
--------------------------------------------------------------------------------
/extension/src/setup/instructions.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////
2 | // Bootstrap
3 | //////////////////////////////
4 |
5 | @import "../styles/bootstrap.css";
6 |
7 | //////////////////////////////
8 | // Various Modifications
9 | //////////////////////////////
10 |
11 | .nav-link {
12 | text-align: left;
13 | min-width: 13em;
14 | }
15 |
16 | ol > li {
17 | padding: 3px;
18 | }
19 |
20 | ul {
21 | padding-left: 1rem;
22 | }
23 |
24 | .snippet {
25 | display: block;
26 | background-color: #343a40;
27 | color: #fff;
28 | border-radius: .25rem;
29 | padding: .1875rem .375rem;
30 | margin-top: .4rem;
31 | margin-bottom: .4rem;
32 | }
33 |
--------------------------------------------------------------------------------
/extension/src/setup/setup.scss:
--------------------------------------------------------------------------------
1 | //////////////////////////////
2 | // Bootstrap
3 | //////////////////////////////
4 |
5 | @import "../styles/bootstrap.css";
6 |
7 | //////////////////////////////
8 | // Content Card
9 | //////////////////////////////
10 |
11 | .wrapper {
12 | max-width: 67rem;
13 | }
14 |
15 | .card {
16 | z-index: 0;
17 | border: none;
18 | border-radius: 0.5rem;
19 | }
20 |
21 | //////////////////////////////
22 | // Instructions Iframe
23 | //////////////////////////////
24 |
25 | iframe {
26 | border: 0;
27 | margin: 0;
28 | padding: 0;
29 | width: 100%;
30 | }
31 |
--------------------------------------------------------------------------------
/extension/src/setup/update.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Progressive Web Apps (PWAs) are web apps that use web APIs and features along with progressive enhancement strategy to bring a native app-like user experience to cross-platform web applications. Although Firefox supports many of Progressive Web App APIs, it does not support functionality to install them as a standalone system app with an app-like experience.
26 |
This project creates a custom modified Firefox runtime to allow websites to be installed as standalone apps and provides a console tool and browser extension to install, manage and use them.
27 |
This package contains only the native part of the PWAsForFirefox project. You should also install the browser extension if you haven't already. You can download it from <https://addons.mozilla.org/firefox/addon/pwas-for-firefox/>.
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | Network
44 | Utility
45 | WebBrowser
46 |
47 |
48 |
49 | pwas for firefox
50 | firefoxpwa
51 | firefox
52 | progressive web app
53 | webapp
54 | web
55 |
56 |
57 |
58 | firefoxpwa
59 |
60 |
61 |
62 | org.mozilla.firefox
63 | always
64 |
65 |
66 |
67 | pointing
68 | keyboard
69 | touch
70 |
71 |
72 |
73 | #fe6d45
74 | #cc3e46
75 |
76 |
77 |
78 | [(254, 109, 69), (204, 62, 70)]
79 |
80 |
81 |
--------------------------------------------------------------------------------
/native/packages/appstream/si.filips.FirefoxPWA.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/native/packages/brew/configure.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 |
4 | # Internal script used by Homebrew formula to prepare project for Homebrew installation
5 | # Needs to be run in the "native" directory of the repository
6 | # Usage: ./configure.sh {VERSION} {BIN} {LIBEXEC}
7 |
8 | if [ "$#" -ne 3 ]; then
9 | echo "Usage: $0 {VERSION} {BIN} {LIBEXEC}" > /dev/stderr
10 | exit 1
11 | fi
12 |
13 | VERSION=$1
14 | BIN=$2
15 | LIBEXEC=$3
16 |
17 | # Set the correct version in the source files
18 | sed -i"" -e "s/version = \"0.0.0\"/version = \"$VERSION\"/g" Cargo.toml
19 | sed -i"" -e "s/DISTRIBUTION_VERSION = '0.0.0'/DISTRIBUTION_VERSION = '$VERSION'/g" userchrome/profile/chrome/pwa/chrome.sys.mjs
20 |
21 | # Set the path in the manifest to the Homebrew libexec directory
22 | cp manifests/macos.json manifests/brew.json
23 | sed -i"" -e "s@/usr/local/libexec/firefoxpwa-connector@$LIBEXEC/firefoxpwa-connector@g" manifests/brew.json
24 |
--------------------------------------------------------------------------------
/native/packages/choco/firefoxpwa.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | firefoxpwa
6 | Progressive Web Apps for Firefox
7 | {{PackageVersion}}
8 | filips
9 | filips
10 |
11 | https://github.com/filips123/PWAsForFirefox/tree/main/native/packages/choco
12 | https://github.com/filips123/PWAsForFirefox
13 | https://pwasforfirefox.filips.si/
14 | https://github.com/filips123/PWAsForFirefox/issues
15 | https://pwasforfirefox.filips.si/
16 | https://github.com/filips123/PWAsForFirefox/blob/main/LICENSE
17 | https://rawcdn.githack.com/wiki/filips123/PWAsForFirefox/images/icon.png
18 | false
19 |
20 | pwas-for-firefox firefoxpwa firefox progressive-web-app webapp web foss open-source cross-platform
21 | You can read release notes on [the repository releases page](https://github.com/filips123/PWAsForFirefox/releases/tag/v{{PackageVersion}}).
22 | A tool to install, manage and use Progressive Web Apps (PWAs) in Mozilla Firefox (native component)
23 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/native/packages/choco/legal/LICENSE.txt:
--------------------------------------------------------------------------------
1 | From: https://github.com/filips123/PWAsForFirefox#license
2 |
3 | LICENSE
4 |
5 | The project is licensed under the Mozilla Public License 2.0 .
6 | By using, redistributing, or modifying it, you must agree to the license, and the additional
7 | clauses provided below. See the LICENSE file
8 | in the project repository for the full MPL 2.0 license text.
9 |
10 | The project uses additional third-party assets and code:
11 |
12 | - The project logo is based on the "Fox SVG Vector" icon
13 | and the community-introduced PWA logo ,
14 | both dedicated to the public domain using CC0 .
15 |
16 | - Browser chrome modifications were inspired by and partially derived from the
17 | `xiaoxiaoflood/firefox-scripts`
18 | repository on GitHub, licensed under the Mozilla Public License 2.0. Detailed
19 | information can be found in the respective files.
20 |
21 | - Browser chrome modifications partially use code derived from the `black7375/Firefox-UI-Fix`
22 | repository on GitHub, licensed under the
23 | Mozilla Public License 2.0. Detailed information can be found in the respective files.
24 |
25 | - Browser chrome modifications partially use code and icons derived from the original
26 | Firefox source , licensed under the Mozilla Public
27 | License 2.0. Detailed information can be found in the respective files.
28 |
29 | - Native programs contain the Metropolis Semi Bold typeface
30 | by Chris Simpson, released into the public domain using the Unlicense .
31 |
32 | - Windows installer contains Bootstrap Icons , licensed under the
33 | MIT License . Detailed license information can be found in
34 | the WiX configuration file .
35 |
36 | Additional open source software will be downloaded and installed at runtime when initiated by the user:
37 |
38 | - Installing the runtime on Windows will install 7-Zip if it is not
39 | already installed. The 7-Zip project is made by Igor Pavlov and licensed under the GNU
40 | LGPL license and others . This project is not affiliated
41 | with the 7-Zip project or its developers in any way.
42 |
43 | - Installing the runtime on any system will download the unmodified Mozilla Firefox
44 | , and locally modify it. By using this project you also
45 | agree to the Firefox Privacy Notice . Firefox is
46 | licensed under the Mozilla Public License 2.0. Firefox and the Firefox logo are trademarks
47 | of the Mozilla Foundation in the U.S. and other countries. This project is not affiliated
48 | with the Mozilla Foundation in any way.
49 |
--------------------------------------------------------------------------------
/native/packages/choco/legal/VERIFICATION.txt:
--------------------------------------------------------------------------------
1 | VERIFICATION
2 |
3 | I am the author of the PWAsForFirefox project.
4 |
5 | Both Windows installers are built automatically on every release using GitHub Actions from
6 | the project source, published as workflow artifacts, and then added to a new GitHub release.
7 | After the installers are built, another automated script downloads installers from artifacts,
8 | automatically updates the version in the `.nuspec` file, calculates installer checksums and
9 | saves them into this file, and publishes a new version to Chocolatey.
10 |
11 | Installer checksums can be verified by downloading MSI installers from the correct GitHub
12 | release on the repository, generating their SHA-256 checksums (for example, using sha256sum),
13 | and comparing them to the checksums provided below.
14 |
15 | The source for building and publishing process can be found in the GitHub Actions workflow
16 | file for the native component in the GitHub repository.
17 |
18 | INSTALLER CHECKSUMS
19 |
20 |
--------------------------------------------------------------------------------
/native/packages/choco/tools/chocolateyinstall.ps1:
--------------------------------------------------------------------------------
1 | $ErrorActionPreference = "Stop";
2 |
3 | $toolsPath = Split-Path $MyInvocation.MyCommand.Definition
4 | $filePath32 = "$toolsPath\firefoxpwa-$($env:ChocolateyPackageVersion)-x86.msi"
5 | $filePath64 = "$toolsPath\firefoxpwa-$($env:ChocolateyPackageVersion)-x86_64.msi"
6 |
7 | $packageArgs = @{
8 | PackageName = "$($env:ChocolateyPackageName)"
9 | SoftwareName = "$($env:ChocolateyPackageTitle)"
10 | FileType = "msi"
11 | SilentArgs = "/quiet"
12 | File = $filePath32
13 | File64 = $filePath64
14 | }
15 |
16 | Install-ChocolateyInstallPackage @packageArgs
17 | Remove-Item -Force $filePath32, $filePath64 -ea 0
18 |
--------------------------------------------------------------------------------
/native/packages/deb/description:
--------------------------------------------------------------------------------
1 | Progressive Web Apps (PWAs) are web apps that use web APIs and features along
2 | with progressive enhancement strategy to bring a native app-like user
3 | experience to cross-platform web applications. Although Firefox supports many
4 | of Progressive Web App APIs, it does not support functionality to install them
5 | as a standalone system app with an app-like experience.
6 |
7 | This project creates a custom modified Firefox runtime to allow websites to be
8 | installed as standalone apps and provides a console tool and browser extension
9 | to install, manage and use them.
10 |
11 | This package contains only the native part of the PWAsForFirefox project. You
12 | should also install the browser extension if you haven't already. You can
13 | download it from .
14 |
--------------------------------------------------------------------------------
/native/packages/deb/postinst:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | # Duplicate the manifest file over lib and lib64 directories
5 | # Needed because otherwise the manifest may not be detected on some platforms
6 | # Needed here because packaging it normally breaks when lib64 is a symlink to lib
7 | mkdir -p /usr/lib64/mozilla/native-messaging-hosts || true
8 | cp -f /usr/lib/mozilla/native-messaging-hosts/firefoxpwa.json /usr/lib64/mozilla/native-messaging-hosts/firefoxpwa.json || true
9 |
10 | # Make shell completions executable
11 | # We cannot do this in Cargo.toml because of cargo-deb bug
12 | # See: https://github.com/mmstick/cargo-deb/issues/67
13 | chmod 755 /usr/share/bash-completion/completions/firefoxpwa
14 | chmod 755 /usr/share/fish/vendor_completions.d/firefoxpwa.fish
15 | chmod 755 /usr/share/zsh/vendor-completions/_firefoxpwa
16 |
17 | # Add notice that it is recommended to also install the extension
18 | if [ -z "$2" ]
19 | then
20 | echo "You have successfully installed the native part of the PWAsForFirefox project"
21 | echo "You should also install the Firefox extension if you haven't already"
22 | echo "Download: https://addons.mozilla.org/firefox/addon/pwas-for-firefox/"
23 | fi
24 |
--------------------------------------------------------------------------------
/native/packages/deb/postrm:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | # Remove the duplicated manifest files
5 | if [ "$1" = "remove" ]
6 | then
7 | rm /usr/lib/mozilla/native-messaging-hosts/firefoxpwa.json || true
8 | rm /usr/lib64/mozilla/native-messaging-hosts/firefoxpwa.json || true
9 | fi
10 |
11 | # Add warning that runtime, profiles and web apps are still installed
12 | if [ "$1" = "remove" ]
13 | then
14 | echo "Runtime, profiles and web apps are still installed in user directories"
15 | echo "You can remove them manually after this package is uninstalled"
16 | echo "Doing that will remove all installed web apps and their data"
17 | fi
18 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxHelpers/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "firefoxpwa-background"
3 | version = "0.0.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [profile.release]
8 | codegen-units = 1
9 | lto = true
10 |
11 | [dependencies]
12 | tauri-winrt-notification = { version = "0.6.0", default-features = false }
13 | trayicon = { version = "0.2.0", default-features = false }
14 | winit = { version = "0.30.5", default-features = false }
15 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxHelpers/src/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxHelpers/src/icon.ico
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxHelpers/src/main.rs:
--------------------------------------------------------------------------------
1 | #![windows_subsystem = "windows"]
2 |
3 | use tauri_winrt_notification::Toast;
4 | use trayicon::{MenuBuilder, TrayIconBuilder};
5 | use winit::event::Event;
6 | use winit::event_loop::{ControlFlow, EventLoop};
7 |
8 | #[derive(Clone, Eq, PartialEq)]
9 | enum Events {
10 | Exit,
11 | ShowMenu,
12 | }
13 |
14 | #[allow(deprecated)]
15 | fn main() {
16 | let events = EventLoop::::with_user_event().build().unwrap();
17 | let proxy = events.create_proxy();
18 | let icon = include_bytes!("icon.ico");
19 |
20 | let sender = move |event: &Events| {
21 | let _ = proxy.send_event(event.clone());
22 | };
23 |
24 | Toast::new(Toast::POWERSHELL_APP_ID)
25 | .title("PWAsForFirefox Portable is running")
26 | .text1("It is now possible to use it from the extension")
27 | .text2("You can stop the program from the tray menu")
28 | .show()
29 | .unwrap_or_default();
30 |
31 | let mut tray = TrayIconBuilder::new()
32 | .sender(sender)
33 | .icon_from_buffer(icon)
34 | .tooltip("PWAsForFirefox")
35 | .menu(MenuBuilder::new().item("E&xit", Events::Exit))
36 | .on_click(Events::ShowMenu)
37 | .on_right_click(Events::ShowMenu)
38 | .build()
39 | .unwrap();
40 |
41 | events
42 | .run(move |event, target| {
43 | target.set_control_flow(ControlFlow::Wait);
44 | let _ = tray;
45 |
46 | if let Event::UserEvent(event) = event {
47 | match event {
48 | Events::Exit => target.exit(),
49 | Events::ShowMenu => tray.show_menu().unwrap(),
50 | }
51 | }
52 | })
53 | .unwrap();
54 | }
55 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/EULA.txt:
--------------------------------------------------------------------------------
1 | The project is licensed under the Mozilla Public License 2.0 . By using, redistributing, or modifying it, you must agree to the license, and the additional clauses provided below. See the LICENSE file in the project repository for the full MPL 2.0 license text.
2 |
3 | The project uses additional third-party assets and code:
4 |
5 | - The project logo is based on the "Fox SVG Vector" icon and the community-introduced PWA logo , both dedicated to the public domain using CC0 .
6 |
7 | - Browser chrome modifications were inspired by and partially derived from the `xiaoxiaoflood/firefox-scripts` repository on GitHub, licensed under the Mozilla Public License 2.0. Detailed information can be found in the respective files.
8 |
9 | - Browser chrome modifications partially use code derived from the `black7375/Firefox-UI-Fix` repository on GitHub, licensed under the Mozilla Public License 2.0. Detailed information can be found in the respective files.
10 |
11 | - Browser chrome modifications partially use code and icons derived from the original Firefox source , licensed under the Mozilla Public License 2.0. Detailed information can be found in the respective files.
12 |
13 | - Native programs contain the Metropolis Semi Bold typeface by Chris Simpson, released into the public domain using the Unlicense .
14 |
15 | - Windows installer contains Bootstrap Icons , licensed under the MIT License . Detailed license information can be found in the WiX configuration file .
16 |
17 | Additional open source software will be downloaded if you continue with the installation:
18 |
19 | - Proceeding with the installation will automatically download the unmodified Mozilla Firefox , and locally modify it. By using this project you also agree to the Firefox Privacy Notice . Firefox is licensed under the Mozilla Public License 2.0. Firefox and the Firefox logo are trademarks of the Mozilla Foundation in the U.S. and other countries. This project is not affiliated with the Mozilla Foundation in any way.
20 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/Launcher/PWAsForFirefoxPortable.ini:
--------------------------------------------------------------------------------
1 | [Launch]
2 | ProgramExecutable=PWAsForFirefox/firefoxpwa-background.exe
3 | SinglePortableAppInstance=true
4 | SingleAppInstance=true
5 |
6 | [Activate]
7 | Registry=true
8 |
9 | [RegistryKeys]
10 | -=HKCU\Software\Mozilla\NativeMessagingHosts\firefoxpwa
11 |
12 | [RegistryValueWrite]
13 | HKCU\Software\Mozilla\NativeMessagingHosts\firefoxpwa\=REG_SZ:%PAL:AppDir%\PWAsForFirefox\firefoxpwa.json
14 |
15 | [RegistryCleanupIfEmpty]
16 | 1=HKCU\Software\filips\FirefoxPWA
17 | 2=HKCU\Software\filips
18 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon.ico
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_128.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_16.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_256.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_32.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appicon_75.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/appinfo.ini:
--------------------------------------------------------------------------------
1 | [Format]
2 | Type=PortableAppsFormat
3 | Version=3.7
4 |
5 | [Details]
6 | Name=PWAsForFirefox Portable
7 | AppId=PWAsForFirefoxPortable
8 | Publisher=filips
9 | Homepage=https://pwasforfirefox.filips.si/
10 | Donate=https://github.com/filips123/PWAsForFirefox?sponsor=1
11 | Category=Internet
12 | Description=A tool to install, manage and use Progressive Web Apps (PWAs) in Mozilla Firefox (native component)
13 | Trademarks=Firefox and the Firefox logo are trademarks of the Mozilla Foundation in the U.S. and other countries. This project is not affiliated with the Mozilla Foundation in any way.
14 | Language=Multilingual
15 |
16 | [License]
17 | Shareable=true
18 | OpenSource=true
19 | Freeware=true
20 | CommercialUse=true
21 |
22 | [Version]
23 | PackageVersion=0.0.0.0
24 | DisplayVersion=0.0.0
25 |
26 | [Dependencies]
27 | Requires64bitOS=yes
28 |
29 | [Control]
30 | Icons=1
31 | Start=PWAsForFirefoxPortable.exe
32 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/App/AppInfo/installer.ini:
--------------------------------------------------------------------------------
1 | [DirectoriesToPreserve]
2 | PreserveDirectory1=App\PWAsForFirefox\runtime
3 |
4 | [DownloadFiles]
5 | DownloadURL=https://download.mozilla.org/?product=firefox-latest-ssl&os=win64
6 | DownloadName=Mozilla Firefox
7 | DownloadFilename=firefox-setup.exe
8 | AdvancedExtract1To=App\PWAsForFirefox\extracted
9 | AdvancedExtract1Filter=core\**
10 | AdditionalInstallSize=60000
11 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Donation_Button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Donation_Button.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Favicon.ico
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Help_Background_Footer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Help_Background_Footer.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Help_Background_Header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Help_Background_Header.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Help_Logo_Top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/paf/PWAsForFirefoxPortable/Other/Help/Images/Help_Logo_Top.png
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Source/AppNamePortable.ini:
--------------------------------------------------------------------------------
1 | AdditionalParameters=
2 | DisableSplashScreen=false
3 | RunLocally=false
4 |
5 | # The above options are explained in the included launcher readme
6 | # This INI file is an example only and is not used unless it is placed as described in the included readme
7 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Source/LauncherReadme.txt:
--------------------------------------------------------------------------------
1 | The base application's source code is available from the portable app's
2 | repository listed in the help.html file (if applicable).
3 |
4 | Details of most other things are available there as well.
5 |
6 | LICENSE
7 | =======
8 |
9 | This package's installer and launcher are released under the GPL. The launcher
10 | is the PortableApps.com Launcher, available with full source and documentation
11 | from https://portableapps.com/development. We request that developers using the
12 | PortableApps.com Launcher please leave this directory intact and unchanged.
13 |
14 | USER CONFIGURATION
15 | ==================
16 |
17 | Some configuration in the PortableApps.com Launcher can be overridden by the
18 | user in an INI file next to PWAsForFirefoxPortable.exe called PWAsForFirefoxPortable.ini.
19 | If you are happy with the default options, it is not necessary, though. There
20 | is an example INI included with this package to get you started. To use it,
21 | copy AppNamePortable.ini from this directory to PWAsForFirefoxPortable.ini next
22 | to PWAsForFirefoxPortable.exe. The options in the INI file are as follows:
23 |
24 | AdditionalParameters=
25 | DisableSplashScreen=false
26 | RunLocally=false
27 |
28 | (There is no need for an INI header in this file; if you have one, though, it
29 | won't damage anything.)
30 |
31 | The AdditionalParameters entry allows you to pass additional command-line
32 | parameters to the application.
33 |
34 | The DisableSplashScreen entry allows you to run the launcher without the splash
35 | screen showing up. The default is false.
36 |
37 | The RunLocally entry allows you to run the portable application from a read-
38 | only medium. This is known as Live mode. It copies what it needs to a
39 | temporary directory on the host computer, runs the application, and then
40 | deletes it afterwards, leaving nothing behind. This can be useful for running
41 | the application from a CD or if you work on a computer that may have spyware or
42 | viruses and you'd like to keep your device set to read-only. As a consequence
43 | of this technique, any changes you make during the Live mode session aren't
44 | saved back to your device. The default is false.
45 |
46 | There may be other values also permitted in the user configuration file by the
47 | portable application; refer to help.html for any details of them.
48 |
--------------------------------------------------------------------------------
/native/packages/paf/PWAsForFirefoxPortable/Other/Source/PortableApps.comInstallerCustom.nsh:
--------------------------------------------------------------------------------
1 | !include PortableApps.comInstallerMoveFiles.nsh
2 |
3 | !macro CustomCodePostInstall
4 | IfFileExists "$INSTDIR\App\PWAsForFirefox\runtime\firefox.exe" remove copy
5 |
6 | copy:
7 | ; Copy only if runtime does not exist yet
8 | CreateDirectory "$INSTDIR\App\PWAsForFirefox\runtime"
9 | ${MoveFiles} DIR+FORCE "*" "$INSTDIR\App\PWAsForFirefox\extracted\core" "$INSTDIR\App\PWAsForFirefox\runtime"
10 |
11 | remove:
12 | ; Then remove the temporary extracted directory
13 | RMDir /r "$INSTDIR\App\PWAsForFirefox\extracted"
14 | !macroend
15 |
--------------------------------------------------------------------------------
/native/packages/wix/assets/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/banner.png
--------------------------------------------------------------------------------
/native/packages/wix/assets/dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/dialog.png
--------------------------------------------------------------------------------
/native/packages/wix/assets/exclamation.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/exclamation.ico
--------------------------------------------------------------------------------
/native/packages/wix/assets/information.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/information.ico
--------------------------------------------------------------------------------
/native/packages/wix/assets/new.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/new.ico
--------------------------------------------------------------------------------
/native/packages/wix/assets/product.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/product.ico
--------------------------------------------------------------------------------
/native/packages/wix/assets/up.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filips123/PWAsForFirefox/71826df22c8d6203158181fae60636b68edd40c0/native/packages/wix/assets/up.ico
--------------------------------------------------------------------------------
/native/rustfmt.toml:
--------------------------------------------------------------------------------
1 | group_imports = "StdExternalCrate"
2 | imports_granularity = "Module"
3 | imports_layout = "HorizontalVertical"
4 |
5 | newline_style = "Unix"
6 |
7 | overflow_delimited_expr = true
8 | use_field_init_shorthand = true
9 | use_try_shorthand = true
10 | use_small_heuristics = "Max"
11 |
--------------------------------------------------------------------------------
/native/scripts/manifest.scm:
--------------------------------------------------------------------------------
1 | !/usr/bin/env -S guix shell -m
2 | !#
3 |
4 | ;;; This is a manifest file for GNU Guix to provide all dependencies needed to build the project
5 |
6 | (use-modules (guix channels))
7 |
8 | ;; NOTE(Krey): This is used to establish reproducibility, but I decided to not use it in this repo as it would require additional maintenance to update the commit over time. Kept in case it's needed in the future.
9 | ;; (list (channel
10 | ;; (name 'guix)
11 | ;; (url "https://git.savannah.gnu.org/git/guix.git")
12 | ;; (commit
13 | ;; "f1bfd9f1948a5ff336d737c0614b9a30c2bb3097")
14 | ;; (introduction
15 | ;; (make-channel-introduction
16 | ;; "9edb3f66fd807b096b48283debdcddccfea34bad"
17 | ;; (openpgp-fingerprint
18 | ;; "BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))))
19 |
20 | (specifications->manifest (list
21 | "rust"
22 | "rust-cargo"
23 | ;; NOTE(Krey): clang can also be used if needed
24 | "gcc"
25 | "openssl"
26 | "rust-pkg-config"
27 | "pkg-config"))
28 |
--------------------------------------------------------------------------------
/native/scripts/set-version.ds:
--------------------------------------------------------------------------------
1 | # Called from Makefile.toml, but could be run on its own
2 | # Sets version strings in configuration files to first argument or git tag
3 |
4 | fn replace_version
5 | content = set ${1}
6 | version_find = set ${2}
7 | pwa_ver = set ${3}
8 | quote_find = set ${4}
9 | version_find_length = strlen ${version_find}
10 | back_index = indexof ${content} ${version_find}
11 | back_index = calc ${back_index} + ${version_find_length}
12 | back = substring ${content} ${back_index}
13 | back_length = strlen ${back}
14 | front = substring ${content} -${back_length}
15 | quote_find_index = indexof ${back} ${quote_find}
16 | back = substring ${back} ${quote_find_index}
17 | content = concat ${front} ${pwa_ver} ${back}
18 | return ${content}
19 | end
20 |
21 | if ${1}
22 | # Use first argument
23 | pwa_ver = set ${1}
24 | else
25 | # No argument, find tag from git
26 | git_tag = exec git describe --tags --abbrev=0
27 | assert_eq ${git_tag.code} 0 "No version provided to task and unable to retrieve git tag"
28 | pwa_ver = trim ${git_tag.stdout}
29 | release git_tag
30 | unset git_tag
31 | end
32 |
33 | # Remove single leading v if it exists
34 | if starts_with ${pwa_ver} "v"
35 | pwa_ver = substring ${pwa_ver} 1
36 | end
37 |
38 | # Replace versions in files
39 | cargo_toml_path = set "./Cargo.toml"
40 | cargo_lock_path = set "./Cargo.lock"
41 | chrome_mjs_path = set "./userchrome/profile/chrome/pwa/chrome.sys.mjs"
42 | cargo_toml_exists = is_file ${cargo_toml_path}
43 | cargo_lock_exists = is_file ${cargo_lock_path}
44 | chrome_mjs_exists = is_file ${chrome_mjs_path}
45 | if ${cargo_toml_exists} and ${cargo_lock_exists} and ${chrome_mjs_exists}
46 | echo "Setting version in Cargo.toml to \"${pwa_ver}\""
47 | cargo_toml = readfile ${cargo_toml_path}
48 | cargo_toml = replace_version ${cargo_toml} "# Version will be set by CI from the Git tag when building and releasing\nversion = \"" ${pwa_ver} "\""
49 | writefile ${cargo_toml_path} ${cargo_toml}
50 | echo "Setting version in Cargo.lock to \"${pwa_ver}\""
51 | cargo_lock = readfile ${cargo_lock_path}
52 | cargo_lock = replace_version ${cargo_lock} "name = \"firefoxpwa\"\nversion = \"" ${pwa_ver} "\""
53 | writefile ${cargo_lock_path} ${cargo_lock}
54 | echo "Setting version in chrome.sys.mjs to \"${pwa_ver}\""
55 | chrome_mjs = readfile ${chrome_mjs_path}
56 | chrome_mjs = replace_version ${chrome_mjs} "DISTRIBUTION_VERSION = '" ${pwa_ver} "'"
57 | writefile ${chrome_mjs_path} ${chrome_mjs}
58 | else
59 | assert_fail "Unable to locate ./Cargo.toml, ./Cargo.lock and ./userchrome/profile/chrome/pwa/chrome.sys.mjs"
60 | end
61 |
--------------------------------------------------------------------------------
/native/src/bin/firefoxpwa-connector.rs:
--------------------------------------------------------------------------------
1 | use std::fs::OpenOptions;
2 | use std::process::exit;
3 |
4 | use anyhow::Result;
5 | use log::{error, LevelFilter};
6 | use simplelog::{ColorChoice, CombinedLogger, Config, TermLogger, TerminalMode, WriteLogger};
7 |
8 | #[rustfmt::skip]
9 | use firefoxpwa::{connector::Connection, directories::ProjectDirs};
10 |
11 | fn main() -> Result<()> {
12 | let dirs = ProjectDirs::new()?;
13 |
14 | let debugmode = dirs.userdata.join("DEBUG").exists();
15 | let loglevel = if debugmode { LevelFilter::Debug } else { LevelFilter::Warn };
16 |
17 | let logfile = dirs.userdata.join("firefoxpwa.log");
18 | let logfile = OpenOptions::new().create(true).append(true).open(logfile)?;
19 |
20 | CombinedLogger::init(vec![
21 | TermLogger::new(loglevel, Config::default(), TerminalMode::Stderr, ColorChoice::Auto),
22 | WriteLogger::new(loglevel, Config::default(), logfile),
23 | ])?;
24 |
25 | if let Err(error) = Connection::start(&dirs, debugmode) {
26 | error!("{:?}", error);
27 | exit(1);
28 | }
29 |
30 | Ok(())
31 | }
32 |
--------------------------------------------------------------------------------
/native/src/bin/firefoxpwa.rs:
--------------------------------------------------------------------------------
1 | use std::process::exit;
2 |
3 | use anyhow::Result;
4 | use clap::Parser;
5 | use log::{error, LevelFilter};
6 | use simplelog::{ColorChoice, Config, TermLogger, TerminalMode};
7 |
8 | #[rustfmt::skip]
9 | use firefoxpwa::console::{App, Run};
10 |
11 | fn main() -> Result<()> {
12 | TermLogger::init(LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto)?;
13 |
14 | let app = App::parse();
15 | if let Err(error) = app.run() {
16 | error!("{:?}", error);
17 | exit(1);
18 | }
19 |
20 | Ok(())
21 | }
22 |
--------------------------------------------------------------------------------
/native/src/components/mod.rs:
--------------------------------------------------------------------------------
1 | #[cfg(platform_windows)]
2 | pub mod _7zip;
3 |
4 | pub mod profile;
5 | pub mod runtime;
6 | pub mod site;
7 |
--------------------------------------------------------------------------------
/native/src/components/profile.rs:
--------------------------------------------------------------------------------
1 | use std::fs::{create_dir_all, remove_dir_all};
2 |
3 | use anyhow::{Context, Result};
4 | use fs_extra::dir::{copy, CopyOptions};
5 | use log::info;
6 | use serde::{Deserialize, Serialize};
7 | use ulid::Ulid;
8 |
9 | use crate::directories::ProjectDirs;
10 |
11 | #[non_exhaustive]
12 | #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
13 | pub struct Profile {
14 | /// A profile ID.
15 | ///
16 | /// Stored as the ULID format. Unique for each profile
17 | /// and auto-generated when a profile is created.
18 | ///
19 | /// One profile with zero/nil ULID always exists and is treated
20 | /// as a default profile for all web apps. This profile cannot
21 | /// be completely removed. When trying to remove it, web apps
22 | /// and data will be cleared, but the profile will stay.
23 | pub ulid: Ulid,
24 |
25 | /// A profile name.
26 | pub name: Option,
27 |
28 | /// A profile description.
29 | pub description: Option,
30 |
31 | /// A list of web app IDs installed within this profile.
32 | #[serde(default)]
33 | pub sites: Vec,
34 | }
35 |
36 | impl Default for Profile {
37 | #[inline]
38 | fn default() -> Self {
39 | Self {
40 | ulid: Ulid::nil(),
41 | name: Some("Default".into()),
42 | description: Some("Default profile for all web apps".into()),
43 | sites: vec![],
44 | }
45 | }
46 | }
47 |
48 | impl Profile {
49 | #[inline]
50 | pub fn new(name: Option, description: Option) -> Self {
51 | Self { ulid: Ulid::new(), name, description, sites: vec![] }
52 | }
53 |
54 | pub fn patch(&self, dirs: &ProjectDirs) -> Result<()> {
55 | let source = dirs.sysdata.join("userchrome/profile");
56 | let profile = dirs.userdata.join("profiles").join(self.ulid.to_string());
57 |
58 | let mut options = CopyOptions::new();
59 | options.content_only = true;
60 | options.overwrite = true;
61 |
62 | if !profile.exists() {
63 | info!("Creating a profile directory");
64 | create_dir_all(&profile).context("Failed to create a profile directory")?;
65 | }
66 |
67 | info!("Patching the profile");
68 | let _ = remove_dir_all(profile.join("startupCache"));
69 | let _ = remove_dir_all(profile.join("chrome/pwa"));
70 | copy(source, profile, &options).context("Failed to patch the profile")?;
71 |
72 | info!("Profile patched!");
73 | Ok(())
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/native/src/connector/response.rs:
--------------------------------------------------------------------------------
1 | use std::collections::BTreeMap;
2 |
3 | use serde::Serialize;
4 | use ulid::Ulid;
5 |
6 | use crate::components::profile::Profile;
7 | use crate::components::site::Site;
8 | use crate::storage::Config;
9 |
10 | /// TODO: Docs
11 | #[derive(Serialize, Debug, PartialEq, Clone)]
12 | #[serde(tag = "type", content = "data")]
13 | pub enum ConnectorResponse {
14 | /// Versions of the installed system components.
15 | SystemVersions {
16 | /// Version of the PWAsForFirefox native program.
17 | ///
18 | /// Always set. When using a development version,
19 | /// commonly set to `0.0.0`.
20 | firefoxpwa: Option,
21 |
22 | /// Version of the Firefox runtime.
23 | ///
24 | /// Only set if the runtime is installed.
25 | firefox: Option,
26 |
27 | /// Version of the 7-Zip program.
28 | ///
29 | /// Only set on Windows, and if 7-Zip is installed.
30 | /// May also be `0.0.0` if 7-Zip was located through
31 | /// the `PATH` environment variable.
32 | _7zip: Option,
33 | },
34 |
35 | /// Config of the native program.
36 | Config(Config),
37 |
38 | /// Config of the native program has been set.
39 | ConfigSet,
40 |
41 | /// Runtime has been installed.
42 | RuntimeInstalled,
43 |
44 | /// Runtime has been uninstalled.
45 | RuntimeUninstalled,
46 |
47 | /// List of all installed web apps.
48 | SiteList(BTreeMap),
49 |
50 | /// Web app has been launched.
51 | SiteLaunched,
52 |
53 | /// Web app has been installed.
54 | SiteInstalled(Ulid),
55 |
56 | /// Web app has been uninstalled.
57 | SiteUninstalled,
58 |
59 | /// Web app has been updated.
60 | SiteUpdated,
61 |
62 | /// All web apps have been updated.
63 | AllSitesUpdated,
64 |
65 | /// List of all available profiles.
66 | ProfileList(BTreeMap),
67 |
68 | /// Profile has been created.
69 | ProfileCreated(Ulid),
70 |
71 | /// Profile has been removed.
72 | ProfileRemoved,
73 |
74 | /// Profile has been updated.
75 | ProfileUpdated,
76 |
77 | /// All profiles and runtime have been patched.
78 | AllProfilesPatched,
79 |
80 | /// Protocol handler has been registered.
81 | ProtocolHandlerRegistered,
82 |
83 | /// Protocol handler has been unregistered.
84 | ProtocolHandlerUnregistered,
85 |
86 | /// Something went wrong...
87 | Error(String),
88 | }
89 |
--------------------------------------------------------------------------------
/native/src/console/mod.rs:
--------------------------------------------------------------------------------
1 | use anyhow::Result;
2 |
3 | pub use crate::console::app::App;
4 | use crate::console::app::{ProfileCommand, RuntimeCommand, SiteCommand};
5 |
6 | pub mod app;
7 | pub mod profile;
8 | pub mod runtime;
9 | pub mod site;
10 |
11 | /// Parses and stores `Option