michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: 'use strict'; michael@0: michael@0: module.metadata = { michael@0: 'stability': 'experimental', michael@0: 'engines': { michael@0: 'Firefox': '*' michael@0: } michael@0: }; michael@0: michael@0: const { Cc, Ci } = require('chrome'); michael@0: const { Unknown } = require('../platform/xpcom'); michael@0: const { Class } = require('../core/heritage'); michael@0: const { merge } = require('../util/object'); michael@0: const bookmarkService = Cc['@mozilla.org/browser/nav-bookmarks-service;1'] michael@0: .getService(Ci.nsINavBookmarksService); michael@0: const historyService = Cc['@mozilla.org/browser/nav-history-service;1'] michael@0: .getService(Ci.nsINavHistoryService); michael@0: const { mapBookmarkItemType } = require('./utils'); michael@0: const { EventTarget } = require('../event/target'); michael@0: const { emit } = require('../event/core'); michael@0: michael@0: const emitter = EventTarget(); michael@0: michael@0: let HISTORY_ARGS = { michael@0: onBeginUpdateBatch: [], michael@0: onEndUpdateBatch: [], michael@0: onClearHistory: [], michael@0: onDeleteURI: ['url'], michael@0: onDeleteVisits: ['url', 'visitTime'], michael@0: onPageChanged: ['url', 'property', 'value'], michael@0: onTitleChanged: ['url', 'title'], michael@0: onVisit: [ michael@0: 'url', 'visitId', 'time', 'sessionId', 'referringId', 'transitionType' michael@0: ] michael@0: }; michael@0: michael@0: let HISTORY_EVENTS = { michael@0: onBeginUpdateBatch: 'history-start-batch', michael@0: onEndUpdateBatch: 'history-end-batch', michael@0: onClearHistory: 'history-start-clear', michael@0: onDeleteURI: 'history-delete-url', michael@0: onDeleteVisits: 'history-delete-visits', michael@0: onPageChanged: 'history-page-changed', michael@0: onTitleChanged: 'history-title-changed', michael@0: onVisit: 'history-visit' michael@0: }; michael@0: michael@0: let BOOKMARK_ARGS = { michael@0: onItemAdded: [ michael@0: 'id', 'parentId', 'index', 'type', 'url', 'title', 'dateAdded' michael@0: ], michael@0: onItemChanged: [ michael@0: 'id', 'property', null, 'value', 'lastModified', 'type', 'parentId' michael@0: ], michael@0: onItemMoved: [ michael@0: 'id', 'previousParentId', 'previousIndex', 'currentParentId', michael@0: 'currentIndex', 'type' michael@0: ], michael@0: onItemRemoved: ['id', 'parentId', 'index', 'type', 'url'], michael@0: onItemVisited: ['id', 'visitId', 'time', 'transitionType', 'url', 'parentId'] michael@0: }; michael@0: michael@0: let BOOKMARK_EVENTS = { michael@0: onItemAdded: 'bookmark-item-added', michael@0: onItemChanged: 'bookmark-item-changed', michael@0: onItemMoved: 'bookmark-item-moved', michael@0: onItemRemoved: 'bookmark-item-removed', michael@0: onItemVisited: 'bookmark-item-visited', michael@0: }; michael@0: michael@0: function createHandler (type, propNames) { michael@0: propNames = propNames || []; michael@0: return function (...args) { michael@0: let data = propNames.reduce((acc, prop, i) => { michael@0: if (prop) michael@0: acc[prop] = formatValue(prop, args[i]); michael@0: return acc; michael@0: }, {}); michael@0: michael@0: emit(emitter, 'data', { michael@0: type: type, michael@0: data: data michael@0: }); michael@0: }; michael@0: } michael@0: michael@0: /* michael@0: * Creates an observer, creating handlers based off of michael@0: * the `events` names, and ordering arguments from `propNames` hash michael@0: */ michael@0: function createObserverInstance (events, propNames) { michael@0: let definition = Object.keys(events).reduce((prototype, eventName) => { michael@0: prototype[eventName] = createHandler(events[eventName], propNames[eventName]); michael@0: return prototype; michael@0: }, {}); michael@0: michael@0: return Class(merge(definition, { extends: Unknown }))(); michael@0: } michael@0: michael@0: /* michael@0: * Formats `data` based off of the value of `type` michael@0: */ michael@0: function formatValue (type, data) { michael@0: if (type === 'type') michael@0: return mapBookmarkItemType(data); michael@0: if (type === 'url' && data) michael@0: return data.spec; michael@0: return data; michael@0: } michael@0: michael@0: let historyObserver = createObserverInstance(HISTORY_EVENTS, HISTORY_ARGS); michael@0: historyService.addObserver(historyObserver, false); michael@0: michael@0: let bookmarkObserver = createObserverInstance(BOOKMARK_EVENTS, BOOKMARK_ARGS); michael@0: bookmarkService.addObserver(bookmarkObserver, false); michael@0: michael@0: exports.events = emitter;