forked from mirrors/gecko-dev
--HG-- rename : addon-sdk/source/test/fixtures/test-page-worker.html => addon-sdk/source/test/addons/e10s-content/data/test-page-worker.html rename : addon-sdk/source/test/fixtures/test-page-worker.js => addon-sdk/source/test/addons/e10s-content/data/test-page-worker.js rename : addon-sdk/source/test/addons/places/favicon-helpers.js => addon-sdk/source/test/addons/places/lib/favicon-helpers.js rename : addon-sdk/source/test/addons/places/httpd.js => addon-sdk/source/test/addons/places/lib/httpd.js rename : addon-sdk/source/test/addons/places/places-helper.js => addon-sdk/source/test/addons/places/lib/places-helper.js rename : addon-sdk/source/test/addons/places/tests/test-places-utils.js => addon-sdk/source/test/addons/places/lib/test-places-utils.js rename : addon-sdk/source/test/fixtures/test-page-worker.html => addon-sdk/source/test/fixtures/addon-sdk/data/test-page-worker.html rename : addon-sdk/source/test/fixtures/test-page-worker.js => addon-sdk/source/test/fixtures/addon-sdk/data/test-page-worker.js
147 lines
4.3 KiB
JavaScript
147 lines
4.3 KiB
JavaScript
/* 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/. */
|
|
|
|
const { Class } = require("../core/heritage");
|
|
const { extend } = require("../util/object");
|
|
const { MatchPattern } = require("../util/match-pattern");
|
|
const readers = require("./readers");
|
|
|
|
// Context class is required to implement a single `isCurrent(target)` method
|
|
// that must return boolean value indicating weather given target matches a
|
|
// context or not. Most context implementations below will have an associated
|
|
// reader that way context implementation can setup a reader to extract necessary
|
|
// information to make decision if target is matching a context.
|
|
const Context = Class({
|
|
isRequired: false,
|
|
isCurrent(target) {
|
|
throw Error("Context class must implement isCurrent(target) method");
|
|
},
|
|
get required() {
|
|
Object.defineProperty(this, "required", {
|
|
value: Object.assign(Object.create(Object.getPrototypeOf(this)),
|
|
this,
|
|
{isRequired: true})
|
|
});
|
|
return this.required;
|
|
}
|
|
});
|
|
Context.required = function(...params) {
|
|
return Object.assign(new this(...params), {isRequired: true});
|
|
};
|
|
exports.Context = Context;
|
|
|
|
|
|
// Next few context implementations use an associated reader to extract info
|
|
// from the context target and story it to a private symbol associtaed with
|
|
// a context implementation. That way name collisions are avoided while required
|
|
// information is still carried along.
|
|
const isPage = Symbol("context/page?")
|
|
const PageContext = Class({
|
|
extends: Context,
|
|
read: {[isPage]: new readers.isPage()},
|
|
isCurrent: target => target[isPage]
|
|
});
|
|
exports.Page = PageContext;
|
|
|
|
const isFrame = Symbol("context/frame?");
|
|
const FrameContext = Class({
|
|
extends: Context,
|
|
read: {[isFrame]: new readers.isFrame()},
|
|
isCurrent: target => target[isFrame]
|
|
});
|
|
exports.Frame = FrameContext;
|
|
|
|
const selection = Symbol("context/selection")
|
|
const SelectionContext = Class({
|
|
read: {[selection]: new readers.Selection()},
|
|
isCurrent: target => !!target[selection]
|
|
});
|
|
exports.Selection = SelectionContext;
|
|
|
|
const link = Symbol("context/link");
|
|
const LinkContext = Class({
|
|
extends: Context,
|
|
read: {[link]: new readers.LinkURL()},
|
|
isCurrent: target => !!target[link]
|
|
});
|
|
exports.Link = LinkContext;
|
|
|
|
const isEditable = Symbol("context/editable?")
|
|
const EditableContext = Class({
|
|
extends: Context,
|
|
read: {[isEditable]: new readers.isEditable()},
|
|
isCurrent: target => target[isEditable]
|
|
});
|
|
exports.Editable = EditableContext;
|
|
|
|
|
|
const mediaType = Symbol("context/mediaType")
|
|
|
|
const ImageContext = Class({
|
|
extends: Context,
|
|
read: {[mediaType]: new readers.MediaType()},
|
|
isCurrent: target => target[mediaType] === "image"
|
|
});
|
|
exports.Image = ImageContext;
|
|
|
|
|
|
const VideoContext = Class({
|
|
extends: Context,
|
|
read: {[mediaType]: new readers.MediaType()},
|
|
isCurrent: target => target[mediaType] === "video"
|
|
});
|
|
exports.Video = VideoContext;
|
|
|
|
|
|
const AudioContext = Class({
|
|
extends: Context,
|
|
read: {[mediaType]: new readers.MediaType()},
|
|
isCurrent: target => target[mediaType] === "audio"
|
|
});
|
|
exports.Audio = AudioContext;
|
|
|
|
const isSelectorMatch = Symbol("context/selector/mathches?")
|
|
const SelectorContext = Class({
|
|
extends: Context,
|
|
initialize(selector) {
|
|
this.selector = selector;
|
|
// Each instance of selector context will need to store read
|
|
// data into different field, so that case with multilpe selector
|
|
// contexts won't cause a conflicts.
|
|
this[isSelectorMatch] = Symbol(selector);
|
|
this.read = {[this[isSelectorMatch]]: new readers.SelectorMatch(selector)};
|
|
},
|
|
isCurrent(target) {
|
|
return target[this[isSelectorMatch]];
|
|
}
|
|
});
|
|
exports.Selector = SelectorContext;
|
|
|
|
const url = Symbol("context/url");
|
|
const URLContext = Class({
|
|
extends: Context,
|
|
initialize(pattern) {
|
|
this.pattern = new MatchPattern(pattern);
|
|
},
|
|
read: {[url]: new readers.PageURL()},
|
|
isCurrent(target) {
|
|
return this.pattern.test(target[url]);
|
|
}
|
|
});
|
|
exports.URL = URLContext;
|
|
|
|
var PredicateContext = Class({
|
|
extends: Context,
|
|
initialize(isMatch) {
|
|
if (typeof(isMatch) !== "function") {
|
|
throw TypeError("Predicate context mus be passed a function");
|
|
}
|
|
|
|
this.isMatch = isMatch
|
|
},
|
|
isCurrent(target) {
|
|
return this.isMatch(target);
|
|
}
|
|
});
|
|
exports.Predicate = PredicateContext;
|