Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ext-history.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 { normalizeTime } = ExtensionCommon;

let nsINavHistoryService = Ci.nsINavHistoryService;
const TRANSITION_TO_TRANSITION_TYPES_MAP = new Map([
  ["link", nsINavHistoryService.TRANSITION_LINK],
  ["typed", nsINavHistoryService.TRANSITION_TYPED],
  ["auto_bookmark", nsINavHistoryService.TRANSITION_BOOKMARK],
  ["auto_subframe", nsINavHistoryService.TRANSITION_EMBED],
  ["manual_subframe", nsINavHistoryService.TRANSITION_FRAMED_LINK],
  ["reload", nsINavHistoryService.TRANSITION_RELOAD],
]);

let TRANSITION_TYPE_TO_TRANSITIONS_MAP = new Map();
for (let [transition, transitionType] of TRANSITION_TO_TRANSITION_TYPES_MAP) {
  TRANSITION_TYPE_TO_TRANSITIONS_MAP.set(transitionType, transition);
}

const getTransitionType = transition => {
  // cannot set a default value for the transition argument as the framework sets it to null
  transition = transition || "link";
  let transitionType = TRANSITION_TO_TRANSITION_TYPES_MAP.get(transition);
  if (!transitionType) {
    throw new Error(
      `|${transition}| is not a supported transition for history`
    );
  }
  return transitionType;
};

const getTransition = transitionType => {
  return TRANSITION_TYPE_TO_TRANSITIONS_MAP.get(transitionType) || "link";
};

/*
 * Converts a mozIStorageRow into a HistoryItem
 */

const convertRowToHistoryItem = row => {
  return {
    id: row.getResultByName("guid"),
    url: row.getResultByName("url"),
    title: row.getResultByName("page_title"),
    lastVisitTime: PlacesUtils.toDate(
      row.getResultByName("last_visit_date")
    ).getTime(),
    visitCount: row.getResultByName("visit_count"),
  };
};

/*
 * Converts a mozIStorageRow into a VisitItem
 */

const convertRowToVisitItem = row => {
  return {
    id: row.getResultByName("guid"),
    visitId: String(row.getResultByName("id")),
    visitTime: PlacesUtils.toDate(row.getResultByName("visit_date")).getTime(),
    referringVisitId: String(row.getResultByName("from_visit")),
    transition: getTransition(row.getResultByName("visit_type")),
  };
};

/*
 * Converts a mozIStorageResultSet into an array of objects
 */

const accumulateNavHistoryResults = (resultSet, converter, results) => {
  let row;
  while ((row = resultSet.getNextRow())) {
    results.push(converter(row));
  }
};

function executeAsyncQuery(historyQuery, options, resultConverter) {
  let results = [];
  return new Promise((resolve, reject) => {
    PlacesUtils.history.asyncExecuteLegacyQuery(historyQuery, options, {
      handleResult(resultSet) {
        accumulateNavHistoryResults(resultSet, resultConverter, results);
      },
      handleError(error) {
        reject(
          new Error(
            "Async execution error (" + error.result + "): " + error.message
          )
        );
      },
      handleCompletion() {
        resolve(results);
      },
    });
  });
}

this.history = class extends ExtensionAPIPersistent {
  PERSISTENT_EVENTS = {
    onVisited({ fire }) {
      const listener = events => {
        for (const event of events) {
          const visit = {
            id: event.pageGuid,
            url: event.url,
            title: event.lastKnownTitle || "",
            lastVisitTime: event.visitTime,
            visitCount: event.visitCount,
            typedCount: event.typedCount,
          };
          fire.sync(visit);
        }
      };

      PlacesUtils.observers.addListener(["page-visited"], listener);
      return {
        unregister() {
          PlacesUtils.observers.removeListener(["page-visited"], listener);
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
    onVisitRemoved({ fire }) {
      const listener = events => {
        const removedURLs = [];

        for (const event of events) {
          switch (event.type) {
            case "history-cleared": {
              fire.sync({ allHistory: true, urls: [] });
              break;
            }
            case "page-removed": {
              if (!event.isPartialVisistsRemoval) {
                removedURLs.push(event.url);
              }
              break;
            }
          }
        }

        if (removedURLs.length) {
          fire.sync({ allHistory: false, urls: removedURLs });
        }
      };

      PlacesUtils.observers.addListener(
        ["history-cleared""page-removed"],
        listener
      );
      return {
        unregister() {
          PlacesUtils.observers.removeListener(
            ["history-cleared""page-removed"],
            listener
          );
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
    onTitleChanged({ fire }) {
      const listener = events => {
        for (const event of events) {
          const titleChanged = {
            id: event.pageGuid,
            url: event.url,
            title: event.title,
          };
          fire.sync(titleChanged);
        }
      };

      PlacesUtils.observers.addListener(["page-title-changed"], listener);
      return {
        unregister() {
          PlacesUtils.observers.removeListener(
            ["page-title-changed"],
            listener
          );
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
  };

  getAPI(context) {
    return {
      history: {
        addUrl: function (details) {
          let transition, date;
          try {
            transition = getTransitionType(details.transition);
          } catch (error) {
            return Promise.reject({ message: error.message });
          }
          if (details.visitTime) {
            date = normalizeTime(details.visitTime);
          }
          let pageInfo = {
            title: details.title,
            url: details.url,
            visits: [
              {
                transition,
                date,
              },
            ],
          };
          try {
            return PlacesUtils.history.insert(pageInfo).then(() => undefined);
          } catch (error) {
            return Promise.reject({ message: error.message });
          }
        },

        deleteAll: function () {
          return PlacesUtils.history.clear();
        },

        deleteRange: function (filter) {
          let newFilter = {
            beginDate: normalizeTime(filter.startTime),
            endDate: normalizeTime(filter.endTime),
          };
          // History.removeVisitsByFilter returns a boolean, but our API should return nothing
          return PlacesUtils.history
            .removeVisitsByFilter(newFilter)
            .then(() => undefined);
        },

        deleteUrl: function (details) {
          let url = details.url;
          // History.remove returns a boolean, but our API should return nothing
          return PlacesUtils.history.remove(url).then(() => undefined);
        },

        search: function (query) {
          let beginTime =
            query.startTime == null
              ? PlacesUtils.toPRTime(Date.now() - 24 * 60 * 60 * 1000)
              : PlacesUtils.toPRTime(normalizeTime(query.startTime));
          let endTime =
            query.endTime == null
              ? Number.MAX_VALUE
              : PlacesUtils.toPRTime(normalizeTime(query.endTime));
          if (beginTime > endTime) {
            return Promise.reject({
              message: "The startTime cannot be after the endTime",
            });
          }

          let options = PlacesUtils.history.getNewQueryOptions();
          options.includeHidden = true;
          options.sortingMode = options.SORT_BY_DATE_DESCENDING;
          options.maxResults = query.maxResults || 100;

          let historyQuery = PlacesUtils.history.getNewQuery();
          historyQuery.searchTerms = query.text;
          historyQuery.beginTime = beginTime;
          historyQuery.endTime = endTime;
          return executeAsyncQuery(
            historyQuery,
            options,
            convertRowToHistoryItem
          );
        },

        getVisits: function (details) {
          let url = details.url;
          if (!url) {
            return Promise.reject({
              message: "A URL must be provided for getVisits",
            });
          }

          let options = PlacesUtils.history.getNewQueryOptions();
          options.includeHidden = true;
          options.sortingMode = options.SORT_BY_DATE_DESCENDING;
          options.resultType = options.RESULTS_AS_VISIT;

          let historyQuery = PlacesUtils.history.getNewQuery();
          historyQuery.uri = Services.io.newURI(url);
          return executeAsyncQuery(
            historyQuery,
            options,
            convertRowToVisitItem
          );
        },

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

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

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

Messung V0.5
C=86 H=95 G=90

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge