tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

manifest-state.js (4130B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const {
      8  MANIFEST_CATEGORIES,
      9  MANIFEST_ISSUE_LEVELS,
     10  MANIFEST_MEMBER_VALUE_TYPES,
     11  FETCH_MANIFEST_FAILURE,
     12  FETCH_MANIFEST_START,
     13  FETCH_MANIFEST_SUCCESS,
     14  RESET_MANIFEST,
     15 } = require("resource://devtools/client/application/src/constants.js");
     16 
     17 function _processRawManifestIcons(rawIcons) {
     18  // NOTE: about `rawIcons` array we are getting from platform:
     19  // - Icons that do not comform to the spec are filtered out
     20  // - We will always get a `src`
     21  // - We will always get `purpose` with a value (default is `["any"]`)
     22  // - `sizes` may be undefined
     23  // - `type` may be undefined
     24  return rawIcons.map(icon => {
     25    return {
     26      key: {
     27        sizes: Array.isArray(icon.sizes) ? icon.sizes.join(" ") : icon.sizes,
     28        contentType: icon.type,
     29      },
     30      value: {
     31        src: icon.src,
     32        purpose: icon.purpose.join(" "),
     33      },
     34      type: MANIFEST_MEMBER_VALUE_TYPES.ICON,
     35    };
     36  });
     37 }
     38 
     39 function _processRawManifestMembers(rawManifest) {
     40  function getCategoryForMember(key) {
     41    switch (key) {
     42      case "name":
     43      case "short_name":
     44        return MANIFEST_CATEGORIES.IDENTITY;
     45      default:
     46        return MANIFEST_CATEGORIES.PRESENTATION;
     47    }
     48  }
     49 
     50  function getValueTypeForMember(key) {
     51    switch (key) {
     52      case "start_url":
     53      case "scope":
     54        return MANIFEST_MEMBER_VALUE_TYPES.URL;
     55      case "theme_color":
     56      case "background_color":
     57        return MANIFEST_MEMBER_VALUE_TYPES.COLOR;
     58      default:
     59        return MANIFEST_MEMBER_VALUE_TYPES.STRING;
     60    }
     61  }
     62 
     63  const res = {
     64    [MANIFEST_CATEGORIES.IDENTITY]: [],
     65    [MANIFEST_CATEGORIES.PRESENTATION]: [],
     66  };
     67 
     68  // filter out extra metadata members (those with moz_ prefix) and icons
     69  const rawMembers = Object.entries(rawManifest).filter(
     70    ([key]) => !key.startsWith("moz_") && !(key === "icons")
     71  );
     72 
     73  for (const [key, value] of rawMembers) {
     74    const category = getCategoryForMember(key);
     75    const type = getValueTypeForMember(key);
     76    res[category].push({ key, value, type });
     77  }
     78 
     79  return res;
     80 }
     81 
     82 function _processRawManifestIssues(issues) {
     83  return issues.map(x => {
     84    return {
     85      level: x.warn
     86        ? MANIFEST_ISSUE_LEVELS.WARNING
     87        : MANIFEST_ISSUE_LEVELS.ERROR,
     88      message: x.warn || x.error,
     89      type: x.type || null,
     90    };
     91  });
     92 }
     93 
     94 function _processRawManifest(rawManifest) {
     95  const res = {
     96    url: rawManifest.moz_manifest_url,
     97  };
     98 
     99  // group manifest members by category
    100  Object.assign(res, _processRawManifestMembers(rawManifest));
    101  // process icons
    102  res.icons = _processRawManifestIcons(rawManifest.icons || []);
    103  // process error messages
    104  res.validation = _processRawManifestIssues(rawManifest.moz_validation || []);
    105 
    106  return res;
    107 }
    108 
    109 function ManifestState() {
    110  return {
    111    errorMessage: "",
    112    isLoading: false,
    113    manifest: undefined,
    114  };
    115 }
    116 
    117 function manifestReducer(state = ManifestState(), action) {
    118  switch (action.type) {
    119    case FETCH_MANIFEST_START:
    120      return Object.assign({}, state, {
    121        isLoading: true,
    122        mustLoadManifest: false,
    123      });
    124 
    125    case FETCH_MANIFEST_FAILURE: {
    126      const { error } = action;
    127      // If we add a redux middleware to log errors, we should move the
    128      // console.error below there.
    129      console.error(error);
    130      return Object.assign({}, state, {
    131        errorMessage: error,
    132        isLoading: false,
    133        manifest: null,
    134      });
    135    }
    136 
    137    case FETCH_MANIFEST_SUCCESS: {
    138      // NOTE: we don't get an error when the page does not have a manifest,
    139      // but a `null` value there.
    140      const { manifest } = action;
    141      return Object.assign({}, state, {
    142        errorMessage: "",
    143        isLoading: false,
    144        manifest: manifest ? _processRawManifest(manifest) : null,
    145      });
    146    }
    147 
    148    case RESET_MANIFEST:
    149      return ManifestState();
    150 
    151    default:
    152      return state;
    153  }
    154 }
    155 
    156 module.exports = {
    157  ManifestState,
    158  manifestReducer,
    159 };