diff options
Diffstat (limited to 'devtools/client/application/src/reducers/manifest-state.js')
-rw-r--r-- | devtools/client/application/src/reducers/manifest-state.js | 158 |
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, +}; |