Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/browser/components/extensions/parent/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 13 kB image not shown  

Quelle  ext-bookmarks.js   Sprache: JAVA

 
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
/* 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";

ChromeUtils.defineESModuleGetters(this, {
  PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});

var { ExtensionError } = ExtensionUtils;

const { TYPE_BOOKMARK, TYPE_FOLDER, TYPE_SEPARATOR } = PlacesUtils.bookmarks;

const BOOKMARKS_TYPES_TO_API_TYPES_MAP = new Map([
  [TYPE_BOOKMARK, "bookmark"],
  [TYPE_FOLDER, "folder"],
  [TYPE_SEPARATOR, "separator"],
]);

const BOOKMARK_SEPERATOR_URL = "data:";

ChromeUtils.defineLazyGetter(this"API_TYPES_TO_BOOKMARKS_TYPES_MAP", () => {
  let theMap = new Map();

  for (let [code, name] of BOOKMARKS_TYPES_TO_API_TYPES_MAP) {
    theMap.set(name, code);
  }
  return theMap;
});

let listenerCount = 0;

function getUrl(type, url) {
  switch (type) {
    case TYPE_BOOKMARK:
      return url;
    case TYPE_SEPARATOR:
      return BOOKMARK_SEPERATOR_URL;
    default:
      return undefined;
  }
}

const getTree = (rootGuid, onlyChildren) => {
  function convert(node, parent) {
    let treenode = {
      id: node.guid,
      title: PlacesUtils.bookmarks.getLocalizedTitle(node) || "",
      index: node.index,
      dateAdded: node.dateAdded / 1000,
      type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(node.typeCode),
      url: getUrl(node.typeCode, node.uri),
    };

    if (parent && node.guid != PlacesUtils.bookmarks.rootGuid) {
      treenode.parentId = parent.guid;
    }

    if (node.typeCode == TYPE_FOLDER) {
      treenode.dateGroupModified = node.lastModified / 1000;

      if (!onlyChildren) {
        treenode.children = node.children
          ? node.children.map(child => convert(child, node))
          : [];
      }
    }

    return treenode;
  }

  return PlacesUtils.promiseBookmarksTree(rootGuid)
    .then(root => {
      if (onlyChildren) {
        let children = root.children || [];
        return children.map(child => convert(child, root));
      }
      let treenode = convert(root, null);
      treenode.parentId = root.parentGuid;
      // It seems like the array always just contains the root node.
      return [treenode];
    })
    .catch(e => Promise.reject({ message: e.message }));
};

const convertBookmarks = result => {
  let node = {
    id: result.guid,
    title: PlacesUtils.bookmarks.getLocalizedTitle(result) || "",
    index: result.index,
    dateAdded: result.dateAdded.getTime(),
    type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(result.type),
    url: getUrl(result.type, result.url && result.url.href),
  };

  if (result.guid != PlacesUtils.bookmarks.rootGuid) {
    node.parentId = result.parentGuid;
  }

  if (result.type == TYPE_FOLDER) {
    node.dateGroupModified = result.lastModified.getTime();
  }

  return node;
};

const throwIfRootId = id => {
  if (id == PlacesUtils.bookmarks.rootGuid) {
    throw new ExtensionError("The bookmark root cannot be modified");
  }
};

let observer = new (class extends EventEmitter {
  constructor() {
    super();
    this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
  }

  handlePlacesEvents(events) {
    for (let event of events) {
      switch (event.type) {
        case "bookmark-added":
          if (event.isTagging) {
            continue;
          }
          let bookmark = {
            id: event.guid,
            parentId: event.parentGuid,
            index: event.index,
            title: event.title,
            dateAdded: event.dateAdded,
            type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(event.itemType),
            url: getUrl(event.itemType, event.url),
          };

          if (event.itemType == TYPE_FOLDER) {
            bookmark.dateGroupModified = bookmark.dateAdded;
          }

          this.emit("created", bookmark);
          break;
        case "bookmark-removed":
          if (event.isTagging || event.isDescendantRemoval) {
            continue;
          }
          let node = {
            id: event.guid,
            parentId: event.parentGuid,
            index: event.index,
            type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(event.itemType),
            url: getUrl(event.itemType, event.url),
            title: event.title,
          };

          this.emit("removed", {
            guid: event.guid,
            info: { parentId: event.parentGuid, index: event.index, node },
          });
          break;
        case "bookmark-moved":
          this.emit("moved", {
            guid: event.guid,
            info: {
              parentId: event.parentGuid,
              index: event.index,
              oldParentId: event.oldParentGuid,
              oldIndex: event.oldIndex,
            },
          });
          break;
        case "bookmark-title-changed":
          if (event.isTagging) {
            continue;
          }

          this.emit("changed", {
            guid: event.guid,
            info: { title: event.title },
          });
          break;
        case "bookmark-url-changed":
          if (event.isTagging) {
            continue;
          }

          this.emit("changed", {
            guid: event.guid,
            info: { url: event.url },
          });
          break;
      }
    }
  }
})();

const decrementListeners = () => {
  listenerCount -= 1;
  if (!listenerCount) {
    PlacesUtils.observers.removeListener(
      [
        "bookmark-added",
        "bookmark-removed",
        "bookmark-moved",
        "bookmark-title-changed",
        "bookmark-url-changed",
      ],
      observer.handlePlacesEvents
    );
  }
};

const incrementListeners = () => {
  listenerCount++;
  if (listenerCount == 1) {
    PlacesUtils.observers.addListener(
      [
        "bookmark-added",
        "bookmark-removed",
        "bookmark-moved",
        "bookmark-title-changed",
        "bookmark-url-changed",
      ],
      observer.handlePlacesEvents
    );
  }
};

this.bookmarks = class extends ExtensionAPIPersistent {
  PERSISTENT_EVENTS = {
    onCreated({ fire }) {
      let listener = (event, bookmark) => {
        fire.sync(bookmark.id, bookmark);
      };

      observer.on("created", listener);
      incrementListeners();
      return {
        unregister() {
          observer.off("created", listener);
          decrementListeners();
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },

    onRemoved({ fire }) {
      let listener = (event, data) => {
        fire.sync(data.guid, data.info);
      };

      observer.on("removed", listener);
      incrementListeners();
      return {
        unregister() {
          observer.off("removed", listener);
          decrementListeners();
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },

    onChanged({ fire }) {
      let listener = (event, data) => {
        fire.sync(data.guid, data.info);
      };

      observer.on("changed", listener);
      incrementListeners();
      return {
        unregister() {
          observer.off("changed", listener);
          decrementListeners();
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },

    onMoved({ fire }) {
      let listener = (event, data) => {
        fire.sync(data.guid, data.info);
      };

      observer.on("moved", listener);
      incrementListeners();
      return {
        unregister() {
          observer.off("moved", listener);
          decrementListeners();
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
  };

  getAPI(context) {
    return {
      bookmarks: {
        async get(idOrIdList) {
          let list = Array.isArray(idOrIdList) ? idOrIdList : [idOrIdList];

          try {
            let bookmarks = [];
            for (let id of list) {
              let bookmark = await PlacesUtils.bookmarks.fetch({ guid: id });
              if (!bookmark) {
                throw new Error("Bookmark not found");
              }
              bookmarks.push(convertBookmarks(bookmark));
            }
            return bookmarks;
          } catch (error) {
            return Promise.reject({ message: error.message });
          }
        },

        getChildren: function (id) {
          // TODO: We should optimize this.
          return getTree(id, true);
        },

        getTree: function () {
          return getTree(PlacesUtils.bookmarks.rootGuid, false);
        },

        getSubTree: function (id) {
          return getTree(id, false);
        },

        search: function (query) {
          return PlacesUtils.bookmarks
            .search(query)
            .then(result => result.map(convertBookmarks));
        },

        getRecent: function (numberOfItems) {
          return PlacesUtils.bookmarks
            .getRecent(numberOfItems)
            .then(result => result.map(convertBookmarks));
        },

        create: function (bookmark) {
          let info = {
            title: bookmark.title || "",
          };

          info.type = API_TYPES_TO_BOOKMARKS_TYPES_MAP.get(bookmark.type);
          if (!info.type) {
            // If url is NULL or missing, it will be a folder.
            if (bookmark.url !== null) {
              info.type = TYPE_BOOKMARK;
            } else {
              info.type = TYPE_FOLDER;
            }
          }

          if (info.type === TYPE_BOOKMARK) {
            info.url = bookmark.url || "";
          }

          if (bookmark.index !== null) {
            info.index = bookmark.index;
          }

          if (bookmark.parentId !== null) {
            throwIfRootId(bookmark.parentId);
            info.parentGuid = bookmark.parentId;
          } else {
            info.parentGuid = PlacesUtils.bookmarks.unfiledGuid;
          }

          try {
            return PlacesUtils.bookmarks
              .insert(info)
              .then(convertBookmarks)
              .catch(error => Promise.reject({ message: error.message }));
          } catch (e) {
            return Promise.reject({
              message: `Invalid bookmark: ${JSON.stringify(info)}`,
            });
          }
        },

        move: function (id, destination) {
          throwIfRootId(id);
          let info = {
            guid: id,
          };

          if (destination.parentId !== null) {
            throwIfRootId(destination.parentId);
            info.parentGuid = destination.parentId;
          }
          info.index =
            destination.index === null
              ? PlacesUtils.bookmarks.DEFAULT_INDEX
              : destination.index;

          try {
            return PlacesUtils.bookmarks
              .update(info)
              .then(convertBookmarks)
              .catch(error => Promise.reject({ message: error.message }));
          } catch (e) {
            return Promise.reject({
              message: `Invalid bookmark: ${JSON.stringify(info)}`,
            });
          }
        },

        update: function (id, changes) {
          throwIfRootId(id);
          let info = {
            guid: id,
          };

          if (changes.title !== null) {
            info.title = changes.title;
          }
          if (changes.url !== null) {
            info.url = changes.url;
          }

          try {
            return PlacesUtils.bookmarks
              .update(info)
              .then(convertBookmarks)
              .catch(error => Promise.reject({ message: error.message }));
          } catch (e) {
            return Promise.reject({
              message: `Invalid bookmark: ${JSON.stringify(info)}`,
            });
          }
        },

        remove: function (id) {
          throwIfRootId(id);
          let info = {
            guid: id,
          };

          // The API doesn't give you the old bookmark at the moment
          try {
            return PlacesUtils.bookmarks
              .remove(info, { preventRemovalOfNonEmptyFolders: true })
              .catch(error => Promise.reject({ message: error.message }));
          } catch (e) {
            return Promise.reject({
              message: `Invalid bookmark: ${JSON.stringify(info)}`,
            });
          }
        },

        removeTree: function (id) {
          throwIfRootId(id);
          let info = {
            guid: id,
          };

          try {
            return PlacesUtils.bookmarks
              .remove(info)
              .catch(error => Promise.reject({ message: error.message }));
          } catch (e) {
            return Promise.reject({
              message: `Invalid bookmark: ${JSON.stringify(info)}`,
            });
          }
        },

        onCreated: new EventManager({
          context,
          module: "bookmarks",
          event: "onCreated",
          extensionApi: this,
        }).api(),

        onRemoved: new EventManager({
          context,
          module: "bookmarks",
          event: "onRemoved",
          extensionApi: this,
        }).api(),

        onChanged: new EventManager({
          context,
          module: "bookmarks",
          event: "onChanged",
          extensionApi: this,
        }).api(),

        onMoved: new EventManager({
          context,
          module: "bookmarks",
          event: "onMoved",
          extensionApi: this,
        }).api(),
      },
    };
  }
};

Messung V0.5
C=94 H=97 G=95

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.