summaryrefslogtreecommitdiffstats
path: root/devtools/client/application/src/reducers/manifest-state.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/application/src/reducers/manifest-state.js158
1 files changed, 158 insertions, 0 deletions
diff --git a/devtools/client/application/src/reducers/manifest-state.js b/devtools/client/application/src/reducers/manifest-state.js
new file mode 100644
index 0000000000..61a2fa6759
--- /dev/null
+++ b/devtools/client/application/src/reducers/manifest-state.js
@@ -0,0 +1,158 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ MANIFEST_CATEGORIES,
+ MANIFEST_ISSUE_LEVELS,
+ MANIFEST_MEMBER_VALUE_TYPES,
+ FETCH_MANIFEST_FAILURE,
+ FETCH_MANIFEST_START,
+ FETCH_MANIFEST_SUCCESS,
+ RESET_MANIFEST,
+} = require("resource://devtools/client/application/src/constants.js");
+
+function _processRawManifestIcons(rawIcons) {
+ // NOTE: about `rawIcons` array we are getting from platform:
+ // - Icons that do not comform to the spec are filtered out
+ // - We will always get a `src`
+ // - We will always get `purpose` with a value (default is `["any"]`)
+ // - `sizes` may be undefined
+ // - `type` may be undefined
+ return rawIcons.map(icon => {
+ return {
+ key: {
+ sizes: Array.isArray(icon.sizes) ? icon.sizes.join(" ") : icon.sizes,
+ contentType: icon.type,
+ },
+ value: {
+ src: icon.src,
+ purpose: icon.purpose.join(" "),
+ },
+ type: MANIFEST_MEMBER_VALUE_TYPES.ICON,
+ };
+ });
+}
+
+function _processRawManifestMembers(rawManifest) {
+ function getCategoryForMember(key) {
+ switch (key) {
+ case "name":
+ case "short_name":
+ return MANIFEST_CATEGORIES.IDENTITY;
+ default:
+ return MANIFEST_CATEGORIES.PRESENTATION;
+ }
+ }
+
+ function getValueTypeForMember(key) {
+ switch (key) {
+ case "start_url":
+ case "scope":
+ return MANIFEST_MEMBER_VALUE_TYPES.URL;
+ case "theme_color":
+ case "background_color":
+ return MANIFEST_MEMBER_VALUE_TYPES.COLOR;
+ default:
+ return MANIFEST_MEMBER_VALUE_TYPES.STRING;
+ }
+ }
+
+ const res = {
+ [MANIFEST_CATEGORIES.IDENTITY]: [],
+ [MANIFEST_CATEGORIES.PRESENTATION]: [],
+ };
+
+ // filter out extra metadata members (those with moz_ prefix) and icons
+ const rawMembers = Object.entries(rawManifest).filter(
+ ([key, value]) => !key.startsWith("moz_") && !(key === "icons")
+ );
+
+ for (const [key, value] of rawMembers) {
+ const category = getCategoryForMember(key);
+ const type = getValueTypeForMember(key);
+ res[category].push({ key, value, type });
+ }
+
+ return res;
+}
+
+function _processRawManifestIssues(issues) {
+ return issues.map(x => {
+ return {
+ level: x.warn
+ ? MANIFEST_ISSUE_LEVELS.WARNING
+ : MANIFEST_ISSUE_LEVELS.ERROR,
+ message: x.warn || x.error,
+ type: x.type || null,
+ };
+ });
+}
+
+function _processRawManifest(rawManifest) {
+ const res = {
+ url: rawManifest.moz_manifest_url,
+ };
+
+ // group manifest members by category
+ Object.assign(res, _processRawManifestMembers(rawManifest));
+ // process icons
+ res.icons = _processRawManifestIcons(rawManifest.icons || []);
+ // process error messages
+ res.validation = _processRawManifestIssues(rawManifest.moz_validation || []);
+
+ return res;
+}
+
+function ManifestState() {
+ return {
+ errorMessage: "",
+ isLoading: false,
+ manifest: undefined,
+ };
+}
+
+function manifestReducer(state = ManifestState(), action) {
+ switch (action.type) {
+ case FETCH_MANIFEST_START:
+ return Object.assign({}, state, {
+ isLoading: true,
+ mustLoadManifest: false,
+ });
+
+ case FETCH_MANIFEST_FAILURE:
+ const { error } = action;
+ // If we add a redux middleware to log errors, we should move the
+ // console.error below there.
+ console.error(error);
+ return Object.assign({}, state, {
+ errorMessage: error,
+ isLoading: false,
+ manifest: null,
+ });
+
+ case FETCH_MANIFEST_SUCCESS:
+ // NOTE: we don't get an error when the page does not have a manifest,
+ // but a `null` value there.
+ const { manifest } = action;
+ return Object.assign({}, state, {
+ errorMessage: "",
+ isLoading: false,
+ manifest: manifest ? _processRawManifest(manifest) : null,
+ });
+
+ case RESET_MANIFEST:
+ const defaultState = ManifestState();
+ return defaultState;
+
+ default:
+ return state;
+ }
+}
+
+module.exports = {
+ ManifestState,
+ manifestReducer,
+};