merge autoland to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-11-10 16:57:59 +01:00
Родитель 5d1eaca102 05f854f094
Коммит ebe55e2d67
164 изменённых файлов: 3994 добавлений и 11064 удалений

Просмотреть файл

@ -6,7 +6,7 @@ module.exports = {
"mozilla"
],
"rules": {
"mozilla/import-globals": 1,
"mozilla/import-globals": "warn",
},
"env": {
"es6": true

Просмотреть файл

@ -32,6 +32,30 @@ typedef [wire_marshal(mozHRGN)] void* HRGN;
typedef [wire_marshal(mozHMONITOR)] void* HMONITOR;
cpp_quote("#endif // 0")
import "Accessible2.idl";
import "Accessible2_2.idl";
import "Accessible2_3.idl";
import "AccessibleAction.idl";
import "AccessibleApplication.idl";
import "AccessibleComponent.idl";
import "AccessibleDocument.idl";
import "AccessibleEditableText.idl";
import "AccessibleEventId.idl";
import "AccessibleHyperlink.idl";
import "AccessibleHypertext.idl";
import "AccessibleHypertext2.idl";
import "AccessibleImage.idl";
import "AccessibleRelation.idl";
import "AccessibleRole.idl";
import "AccessibleStates.idl";
import "AccessibleTable.idl";
import "AccessibleTable2.idl";
import "AccessibleTableCell.idl";
import "AccessibleText.idl";
import "AccessibleText2.idl";
import "AccessibleValue.idl";
import "IA2CommonTypes.idl";
// We are explicitly using #include instead of import so that the imported
// IDL is treated as part of this IDL file.
#include "ia2_api_all.idl"
#include "IA2TypeLibrary.idl"

Просмотреть файл

@ -51,168 +51,168 @@ module.exports = { // eslint-disable-line no-undef
"findAccessibleChildByID": true
},
"rules": {
"mozilla/no-aArgs": 1,
"mozilla/no-cpows-in-tests": 1,
"mozilla/reject-importGlobalProperties": 1,
"mozilla/var-only-at-top-level": 1,
"mozilla/no-aArgs": "warn",
"mozilla/no-cpows-in-tests": "warn",
"mozilla/reject-importGlobalProperties": "warn",
"mozilla/var-only-at-top-level": "warn",
"block-scoped-var": 2,
"brace-style": [2, "1tbs"],
"camelcase": 2,
"comma-dangle": [2, "never"],
"comma-spacing": 2,
"comma-style": [2, "last"],
"complexity": [2, 35],
"consistent-this": 0,
"curly": [2, "multi-line"],
"default-case": 0,
"dot-location": [2, "property"],
"dot-notation": 2,
"eol-last": 2,
"eqeqeq": 0,
"func-names": 0,
"func-style": 0,
"generator-star": 0,
"global-strict": 0,
"handle-callback-err": [2, "er"],
"indent": [2, 2, {"SwitchCase": 1}],
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"linebreak-style": 0,
"max-depth": 0,
"max-nested-callbacks": [2, 4],
"max-params": 0,
"max-statements": 0,
"new-cap": [2, {"capIsNew": false}],
"new-parens": 2,
"no-array-constructor": 2,
"no-bitwise": 0,
"no-caller": 2,
"no-catch-shadow": 2,
"no-comma-dangle": 0,
"no-cond-assign": 2,
"no-console": 0,
"no-constant-condition": 0,
"no-continue": 0,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-div-regex": 0,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-else-return": 2,
"no-empty": 2,
"no-empty-character-class": 2,
"no-eval": 2,
"no-ex-assign": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-boolean-cast": 2,
"no-extra-parens": 0,
"no-extra-semi": 2,
"no-extra-strict": 0,
"no-fallthrough": 2,
"no-floating-decimal": 0,
"no-inline-comments": 0,
"no-lonely-if": 2,
"no-mixed-requires": 0,
"no-mixed-spaces-and-tabs": 2,
"no-multi-spaces": 2,
"no-multi-str": 2,
"no-multiple-empty-lines": [2, {"max": 1}],
"no-native-reassign": 2,
"no-nested-ternary": 2,
"no-new-require": 0,
"no-octal": 2,
"no-param-reassign": 0,
"no-path-concat": 0,
"no-plusplus": 0,
"no-process-env": 0,
"no-process-exit": 0,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-reserved-keys": 0,
"no-restricted-modules": 0,
"no-return-assign": 1,
"no-script-url": 0,
"no-self-compare": 2,
"no-sequences": 2,
"no-shadow": 1,
"no-shadow-restricted-names": 2,
"no-space-before-semi": 0,
"no-spaced-func": 2,
"no-sparse-arrays": 2,
"no-sync": 0,
"no-ternary": 0,
"no-throw-literal": 2,
"no-trailing-spaces": 2,
"no-undef": 2,
"no-underscore-dangle": 0,
"no-undefined": 0,
"no-unneeded-ternary": 2,
"no-unreachable": 2,
"no-unused-vars": [2, {"vars": "all", "args": "none"}],
"no-use-before-define": 0,
"no-var": 0,
"no-warning-comments": 0,
"no-with": 2,
"object-shorthand": 0,
"one-var": [2, "never"],
"padded-blocks": [2, "never"],
"quote-props": 0,
"radix": 2,
"semi": [2, "always"],
"semi-spacing": [2, {"before": false, "after": true}],
"sort-vars": 0,
"space-after-function-name": 0,
"keyword-spacing": 2,
"space-before-blocks": 2,
"space-before-function-parentheses": 0,
"space-before-function-paren": [2, "never"],
"space-in-brackets": 0,
"space-in-parens": [2, "never"],
"space-infix-ops": [2, {"int32Hint": true}],
"space-unary-ops": [2, { "words": true, "nonwords": false }],
"space-unary-word-ops": 0,
"spaced-comment": [2, "always"],
"strict": [2, "global"],
"use-isnan": 2,
"valid-jsdoc": 0,
"valid-typeof": 2,
"vars-on-top": 0,
"wrap-iife": 0,
"wrap-regex": 0,
"yoda": 2,
"block-scoped-var": "error",
"brace-style": ["error", "1tbs"],
"camelcase": "error",
"comma-dangle": ["error", "never"],
"comma-spacing": "error",
"comma-style": ["error", "last"],
"complexity": ["error", 35],
"consistent-this": "off",
"curly": ["error", "multi-line"],
"default-case": "off",
"dot-location": ["error", "property"],
"dot-notation": "error",
"eol-last": "error",
"eqeqeq": "off",
"func-names": "off",
"func-style": "off",
"generator-star": "off",
"global-strict": "off",
"handle-callback-err": ["error", "er"],
"indent": ["error", 2, {"SwitchCase": 1}],
"key-spacing": ["error", {"beforeColon": false, "afterColon": true}],
"linebreak-style": "off",
"max-depth": "off",
"max-nested-callbacks": ["error", 4],
"max-params": "off",
"max-statements": "off",
"new-cap": ["error", {"capIsNew": false}],
"new-parens": "error",
"no-array-constructor": "error",
"no-bitwise": "off",
"no-caller": "error",
"no-catch-shadow": "error",
"no-comma-dangle": "off",
"no-cond-assign": "error",
"no-console": "off",
"no-constant-condition": "off",
"no-continue": "off",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-div-regex": "off",
"no-dupe-args": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-else-return": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-eval": "error",
"no-ex-assign": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-boolean-cast": "error",
"no-extra-parens": "off",
"no-extra-semi": "error",
"no-extra-strict": "off",
"no-fallthrough": "error",
"no-floating-decimal": "off",
"no-inline-comments": "off",
"no-lonely-if": "error",
"no-mixed-requires": "off",
"no-mixed-spaces-and-tabs": "error",
"no-multi-spaces": "error",
"no-multi-str": "error",
"no-multiple-empty-lines": ["error", {"max": 1}],
"no-native-reassign": "error",
"no-nested-ternary": "error",
"no-new-require": "off",
"no-octal": "error",
"no-param-reassign": "off",
"no-path-concat": "off",
"no-plusplus": "off",
"no-process-env": "off",
"no-process-exit": "off",
"no-proto": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-reserved-keys": "off",
"no-restricted-modules": "off",
"no-return-assign": "warn",
"no-script-url": "off",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "warn",
"no-shadow-restricted-names": "error",
"no-space-before-semi": "off",
"no-spaced-func": "error",
"no-sparse-arrays": "error",
"no-sync": "off",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef": "error",
"no-underscore-dangle": "off",
"no-undefined": "off",
"no-unneeded-ternary": "error",
"no-unreachable": "error",
"no-unused-vars": ["error", {"vars": "all", "args": "none"}],
"no-use-before-define": "off",
"no-var": "off",
"no-warning-comments": "off",
"no-with": "error",
"object-shorthand": "off",
"one-var": ["error", "never"],
"padded-blocks": ["error", "never"],
"quote-props": "off",
"radix": "error",
"semi": ["error", "always"],
"semi-spacing": ["error", {"before": false, "after": true}],
"sort-vars": "off",
"space-after-function-name": "off",
"keyword-spacing": "error",
"space-before-blocks": "error",
"space-before-function-parentheses": "off",
"space-before-function-paren": ["error", "never"],
"space-in-brackets": "off",
"space-in-parens": ["error", "never"],
"space-infix-ops": ["error", {"int32Hint": true}],
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
"space-unary-word-ops": "off",
"spaced-comment": ["error", "always"],
"strict": ["error", "global"],
"use-isnan": "error",
"valid-jsdoc": "off",
"valid-typeof": "error",
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yoda": "error",
"guard-for-in": 0,
"newline-after-var": 0,
"no-alert": 0,
"no-eq-null": 0,
"no-func-assign": 0,
"no-implied-eval": 0,
"no-inner-declarations": 0,
"no-invalid-regexp": 0,
"no-irregular-whitespace": 0,
"no-iterator": 0,
"no-label-var": 0,
"no-labels": 2,
"no-lone-blocks": 0,
"no-loop-func": 0,
"no-negated-in-lhs": 0,
"no-new": 0,
"no-new-func": 0,
"no-new-object": 0,
"no-new-wrappers": 0,
"no-obj-calls": 0,
"no-octal-escape": 0,
"no-undef-init": 2,
"no-unexpected-multiline": 2,
"object-curly-spacing": 0,
"no-unused-expressions": 0,
"no-void": 0,
"no-wrap-func": 0,
"operator-assignment": 0,
"operator-linebreak": [2, "after"]
"guard-for-in": "off",
"newline-after-var": "off",
"no-alert": "off",
"no-eq-null": "off",
"no-func-assign": "off",
"no-implied-eval": "off",
"no-inner-declarations": "off",
"no-invalid-regexp": "off",
"no-irregular-whitespace": "off",
"no-iterator": "off",
"no-label-var": "off",
"no-labels": "error",
"no-lone-blocks": "off",
"no-loop-func": "off",
"no-negated-in-lhs": "off",
"no-new": "off",
"no-new-func": "off",
"no-new-object": "off",
"no-new-wrappers": "off",
"no-obj-calls": "off",
"no-octal-escape": "off",
"no-undef-init": "error",
"no-unexpected-multiline": "error",
"object-curly-spacing": "off",
"no-unused-expressions": "off",
"no-void": "off",
"no-wrap-func": "off",
"operator-assignment": "off",
"operator-linebreak": ["error", "after"]
}
};

Просмотреть файл

@ -6,6 +6,6 @@ module.exports = {
],
"rules": {
"no-undef": 2
"no-undef": "error"
}
};

Просмотреть файл

@ -14,69 +14,69 @@ module.exports = { // eslint-disable-line no-undef
"env": { "browser": true },
"rules": {
"block-scoped-var": 2,
// "brace-style": [1, "1tbs", {"allowSingleLine": true}],
"comma-dangle": 0,
"comma-spacing": [1, {"before": false, "after": true}],
"comma-style": [1, "last"],
// "complexity": 1,
"consistent-return": 2,
//"curly": 2,
"dot-notation": 2,
"eol-last": 2,
"indent": [1, 2, {"SwitchCase": 1}],
// "key-spacing": [1, {"beforeColon": false, "afterColon": true}],
"keyword-spacing": 1,
"max-nested-callbacks": [2, 3],
"new-parens": 2,
"no-array-constructor": 2,
"no-cond-assign": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-else-return": 2,
"no-eval": 2,
"no-extend-native": 2,
// "no-extra-bind": 2,
"no-extra-boolean-cast": 2,
"no-extra-semi": 1,
"block-scoped-var": "error",
// "brace-style": ["warn", "1tbs", {"allowSingleLine": true}],
"comma-dangle": "off",
"comma-spacing": ["warn", {"before": false, "after": true}],
"comma-style": ["warn", "last"],
// "complexity": "warn",
"consistent-return": "error",
//"curly": "error",
"dot-notation": "error",
"eol-last": "error",
"indent": ["warn", 2, {"SwitchCase": 1}],
// "key-spacing": ["warn", {"beforeColon": false, "afterColon": true}],
"keyword-spacing": "warn",
"max-nested-callbacks": ["error", 3],
"new-parens": "error",
"no-array-constructor": "error",
"no-cond-assign": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-args": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-else-return": "error",
"no-eval": "error",
"no-extend-native": "error",
// "no-extra-bind": "error",
"no-extra-boolean-cast": "error",
"no-extra-semi": "warn",
"no-fallthrough": ["error", { "commentPattern": ".*[Ii]ntentional(?:ly)?\\s+fall(?:ing)?[\\s-]*through.*" }],
"no-lonely-if": 2,
"no-mixed-spaces-and-tabs": 2,
"no-multi-spaces": 1,
"no-multi-str": 1,
"no-native-reassign": 2,
"no-nested-ternary": 2,
"no-redeclare": 2,
"no-return-assign": 2,
"no-self-compare": 2,
"no-sequences": 2,
"no-shadow": 1,
"no-shadow-restricted-names": 2,
// "no-spaced-func": 1,
"no-throw-literal": 2,
"no-trailing-spaces": 2,
"no-undef": 2,
"no-unneeded-ternary": 2,
"no-unreachable": 2,
"no-lonely-if": "error",
"no-mixed-spaces-and-tabs": "error",
"no-multi-spaces": "warn",
"no-multi-str": "warn",
"no-native-reassign": "error",
"no-nested-ternary": "error",
"no-redeclare": "error",
"no-return-assign": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "warn",
"no-shadow-restricted-names": "error",
// "no-spaced-func": "warn",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef": "error",
"no-unneeded-ternary": "error",
"no-unreachable": "error",
"no-unused-vars": ["error", { "varsIgnorePattern": "^C[ciur]$" }],
"no-with": 2,
"padded-blocks": [1, "never"],
"no-with": "error",
"padded-blocks": ["warn", "never"],
"quotes": ["error", "double", { "avoidEscape": true, "allowTemplateLiterals": true }],
"semi": [2, "always", {"omitLastInOneLineBlock": true }],
"semi-spacing": [1, {"before": false, "after": true}],
"space-before-blocks": [1, "always"],
// "space-before-function-paren": [1, "never"],
"space-in-parens": [1, "never"],
"space-infix-ops": [1, {"int32Hint": true}],
// "space-unary-ops": [1, { "words": true, "nonwords": false }],
"strict": [2, "global"],
"use-isnan": 2,
"valid-typeof": 2,
"yoda": 2
"semi": ["error", "always", {"omitLastInOneLineBlock": true }],
"semi-spacing": ["warn", {"before": false, "after": true}],
"space-before-blocks": ["warn", "always"],
// "space-before-function-paren": ["warn", "never"],
"space-in-parens": ["warn", "never"],
"space-infix-ops": ["warn", {"int32Hint": true}],
// "space-unary-ops": ["warn", { "words": true, "nonwords": false }],
"strict": ["error", "global"],
"use-isnan": "error",
"valid-typeof": "error",
"yoda": "error"
}
};

Просмотреть файл

@ -4,6 +4,7 @@ const TEST_ENGINE_NAME = "Foo";
const TEST_ENGINE_BASENAME = "testEngine.xml";
const SEARCHBAR_BASE_ID = "searchbar-engine-one-off-item-";
const URLBAR_BASE_ID = "urlbar-engine-one-off-item-";
const ONEOFF_URLBAR_PREF = "browser.urlbar.oneOffSearches";
const searchbar = document.getElementById("searchbar");
const urlbar = document.getElementById("urlbar");
@ -60,6 +61,11 @@ add_task(function* test_searchBarChangeEngine() {
});
add_task(function* test_urlBarChangeEngine() {
Services.prefs.setBoolPref(ONEOFF_URLBAR_PREF, true);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref(ONEOFF_URLBAR_PREF);
});
// Ensure the engine is reset.
resetEngine();

Просмотреть файл

@ -12,12 +12,12 @@ module.exports = { // eslint-disable-line no-undef
"rules": {
// Rules from the mozilla plugin
"mozilla/balanced-listeners": 2,
"mozilla/no-aArgs": 1,
"mozilla/no-cpows-in-tests": 1,
"mozilla/var-only-at-top-level": 1,
"mozilla/balanced-listeners": "error",
"mozilla/no-aArgs": "warn",
"mozilla/no-cpows-in-tests": "warn",
"mozilla/var-only-at-top-level": "warn",
"valid-jsdoc": [2, {
"valid-jsdoc": ["error", {
"prefer": {
"return": "returns",
},
@ -33,442 +33,442 @@ module.exports = { // eslint-disable-line no-undef
}],
// Braces only needed for multi-line arrow function blocks
// "arrow-body-style": [2, "as-needed"],
// "arrow-body-style": ["error", "as-needed"],
// Require spacing around =>
"arrow-spacing": 2,
"arrow-spacing": "error",
// Always require spacing around a single line block
"block-spacing": 1,
"block-spacing": "warn",
// Forbid spaces inside the square brackets of array literals.
"array-bracket-spacing": [2, "never"],
"array-bracket-spacing": ["error", "never"],
// Forbid spaces inside the curly brackets of object literals.
"object-curly-spacing": [2, "never"],
"object-curly-spacing": ["error", "never"],
// No space padding in parentheses
"space-in-parens": [2, "never"],
"space-in-parens": ["error", "never"],
// Enforce one true brace style (opening brace on the same line) and avoid
// start and end braces on the same line.
"brace-style": [2, "1tbs", {"allowSingleLine": true}],
"brace-style": ["error", "1tbs", {"allowSingleLine": true}],
// No space before always a space after a comma
"comma-spacing": [2, {"before": false, "after": true}],
"comma-spacing": ["error", {"before": false, "after": true}],
// Commas at the end of the line not the start
"comma-style": 2,
"comma-style": "error",
// Don't require spaces around computed properties
"computed-property-spacing": [1, "never"],
"computed-property-spacing": ["warn", "never"],
// Functions are not required to consistently return something or nothing
"consistent-return": 0,
"consistent-return": "off",
// Require braces around blocks that start a new line
"curly": [2, "all"],
"curly": ["error", "all"],
// Always require a trailing EOL
"eol-last": 2,
"eol-last": "error",
// Require function* name()
"generator-star-spacing": [2, {"before": false, "after": true}],
"generator-star-spacing": ["error", {"before": false, "after": true}],
// Two space indent
"indent": [2, 2, {"SwitchCase": 1}],
"indent": ["error", 2, {"SwitchCase": 1}],
// Space after colon not before in property declarations
"key-spacing": [2, {"beforeColon": false, "afterColon": true, "mode": "minimum"}],
"key-spacing": ["error", {"beforeColon": false, "afterColon": true, "mode": "minimum"}],
// Require spaces before and after finally, catch, etc.
"keyword-spacing": 2,
"keyword-spacing": "error",
// Unix linebreaks
"linebreak-style": [2, "unix"],
"linebreak-style": ["error", "unix"],
// Always require parenthesis for new calls
"new-parens": 2,
"new-parens": "error",
// Use [] instead of Array()
"no-array-constructor": 2,
"no-array-constructor": "error",
// No duplicate arguments in function declarations
"no-dupe-args": 2,
"no-dupe-args": "error",
// No duplicate keys in object declarations
"no-dupe-keys": 2,
"no-dupe-keys": "error",
// No duplicate cases in switch statements
"no-duplicate-case": 2,
"no-duplicate-case": "error",
// If an if block ends with a return no need for an else block
// "no-else-return": 2,
// "no-else-return": "error",
// Disallow empty statements. This will report an error for:
// try { something(); } catch (e) {}
// but will not report it for:
// try { something(); } catch (e) { /* Silencing the error because ...*/ }
// which is a valid use case.
"no-empty": 2,
"no-empty": "error",
// No empty character classes in regex
"no-empty-character-class": 2,
"no-empty-character-class": "error",
// Disallow empty destructuring
"no-empty-pattern": 2,
"no-empty-pattern": "error",
// No assiging to exception variable
"no-ex-assign": 2,
"no-ex-assign": "error",
// No using !! where casting to boolean is already happening
"no-extra-boolean-cast": 1,
"no-extra-boolean-cast": "warn",
// No double semicolon
"no-extra-semi": 2,
"no-extra-semi": "error",
// No overwriting defined functions
"no-func-assign": 2,
"no-func-assign": "error",
// No invalid regular expresions
"no-invalid-regexp": 2,
"no-invalid-regexp": "error",
// No odd whitespace characters
"no-irregular-whitespace": 2,
"no-irregular-whitespace": "error",
// No single if block inside an else block
"no-lonely-if": 1,
"no-lonely-if": "warn",
// No mixing spaces and tabs in indent
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
// Disallow use of multiple spaces (sometimes used to align const values,
// array or object items, etc.). It's hard to maintain and doesn't add that
// much benefit.
"no-multi-spaces": 1,
"no-multi-spaces": "warn",
// No reassigning native JS objects
"no-native-reassign": 2,
"no-native-reassign": "error",
// No (!foo in bar)
"no-negated-in-lhs": 2,
"no-negated-in-lhs": "error",
// Nested ternary statements are confusing
"no-nested-ternary": 2,
"no-nested-ternary": "error",
// Use {} instead of new Object()
"no-new-object": 2,
"no-new-object": "error",
// No Math() or JSON()
"no-obj-calls": 2,
"no-obj-calls": "error",
// No octal literals
"no-octal": 2,
"no-octal": "error",
// No redeclaring variables
"no-redeclare": 2,
"no-redeclare": "error",
// No unnecessary comparisons
"no-self-compare": 2,
"no-self-compare": "error",
// No spaces between function name and parentheses
"no-spaced-func": 1,
"no-spaced-func": "warn",
// No trailing whitespace
"no-trailing-spaces": 2,
"no-trailing-spaces": "error",
// Error on newline where a semicolon is needed
"no-unexpected-multiline": 2,
"no-unexpected-multiline": "error",
// No unreachable statements
"no-unreachable": 2,
"no-unreachable": "error",
// No expressions where a statement is expected
"no-unused-expressions": 2,
"no-unused-expressions": "error",
// No declaring variables that are never used
"no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$"}],
"no-unused-vars": ["error", {"args": "none", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$"}],
// No using variables before defined
"no-use-before-define": 2,
"no-use-before-define": "error",
// No using with
"no-with": 2,
"no-with": "error",
// Always require semicolon at end of statement
"semi": [2, "always"],
"semi": ["error", "always"],
// Require space before blocks
"space-before-blocks": 2,
"space-before-blocks": "error",
// Never use spaces before function parentheses
"space-before-function-paren": [2, {"anonymous": "never", "named": "never"}],
"space-before-function-paren": ["error", {"anonymous": "never", "named": "never"}],
// Require spaces around operators, except for a|0.
"space-infix-ops": [2, {"int32Hint": true}],
// Require spaces around operators, except for a|"off".
"space-infix-ops": ["error", {"int32Hint": true}],
// ++ and -- should not need spacing
"space-unary-ops": [1, {"nonwords": false}],
"space-unary-ops": ["warn", {"nonwords": false}],
// No comparisons to NaN
"use-isnan": 2,
"use-isnan": "error",
// Only check typeof against valid results
"valid-typeof": 2,
"valid-typeof": "error",
// Disallow using variables outside the blocks they are defined (especially
// since only let and const are used, see "no-var").
"block-scoped-var": 2,
"block-scoped-var": "error",
// Allow trailing commas for easy list extension. Having them does not
// impair readability, but also not required either.
"comma-dangle": [2, "always-multiline"],
"comma-dangle": ["error", "always-multiline"],
// Warn about cyclomatic complexity in functions.
"complexity": 1,
"complexity": "warn",
// Don't warn for inconsistent naming when capturing this (not so important
// with auto-binding fat arrow functions).
// "consistent-this": [2, "self"],
// "consistent-this": ["error", "self"],
// Don't require a default case in switch statements. Avoid being forced to
// add a bogus default when you know all possible cases are handled.
"default-case": 0,
"default-case": "off",
// Enforce dots on the next line with property name.
"dot-location": [2, "property"],
"dot-location": ["error", "property"],
// Encourage the use of dot notation whenever possible.
"dot-notation": 2,
"dot-notation": "error",
// Allow using == instead of ===, in the interest of landing something since
// the devtools codebase is split on convention here.
"eqeqeq": 0,
"eqeqeq": "off",
// Don't require function expressions to have a name.
// This makes the code more verbose and hard to read. Our engine already
// does a fantastic job assigning a name to the function, which includes
// the enclosing function name, and worst case you have a line number that
// you can just look up.
"func-names": 0,
"func-names": "off",
// Allow use of function declarations and expressions.
"func-style": 0,
"func-style": "off",
// Don't enforce the maximum depth that blocks can be nested. The complexity
// rule is a better rule to check this.
"max-depth": 0,
"max-depth": "off",
// Maximum length of a line.
// Disabled because we exceed this in too many places.
"max-len": [0, 80],
"max-len": ["off", 80],
// Maximum depth callbacks can be nested.
"max-nested-callbacks": [2, 4],
"max-nested-callbacks": ["error", 4],
// Don't limit the number of parameters that can be used in a function.
"max-params": 0,
"max-params": "off",
// Don't limit the maximum number of statement allowed in a function. We
// already have the complexity rule that's a better measurement.
"max-statements": 0,
"max-statements": "off",
// Don't require a capital letter for constructors, only check if all new
// operators are followed by a capital letter. Don't warn when capitalized
// functions are used without the new operator.
"new-cap": [0, {"capIsNew": false}],
"new-cap": ["off", {"capIsNew": false}],
// Allow use of bitwise operators.
"no-bitwise": 0,
"no-bitwise": "off",
// Disallow use of arguments.caller or arguments.callee.
"no-caller": 2,
"no-caller": "error",
// Disallow the catch clause parameter name being the same as a variable in
// the outer scope, to avoid confusion.
"no-catch-shadow": 0,
"no-catch-shadow": "off",
// Disallow assignment in conditional expressions.
"no-cond-assign": 2,
"no-cond-assign": "error",
// Disallow using the console API.
"no-console": 2,
"no-console": "error",
// Allow using constant expressions in conditions like while (true)
"no-constant-condition": 0,
"no-constant-condition": "off",
// Allow use of the continue statement.
"no-continue": 0,
"no-continue": "off",
// Disallow control characters in regular expressions.
"no-control-regex": 2,
"no-control-regex": "error",
// Disallow use of debugger.
"no-debugger": 2,
"no-debugger": "error",
// Disallow deletion of variables (deleting properties is fine).
"no-delete-var": 2,
"no-delete-var": "error",
// Allow division operators explicitly at beginning of regular expression.
"no-div-regex": 0,
"no-div-regex": "off",
// Disallow use of eval(). We have other APIs to evaluate code in content.
"no-eval": 2,
"no-eval": "error",
// Disallow adding to native types
"no-extend-native": 2,
"no-extend-native": "error",
// Disallow unnecessary function binding.
"no-extra-bind": 2,
"no-extra-bind": "error",
// Allow unnecessary parentheses, as they may make the code more readable.
"no-extra-parens": 0,
"no-extra-parens": "off",
// Disallow fallthrough of case statements, except if there is a comment.
"no-fallthrough": 2,
"no-fallthrough": "error",
// Allow the use of leading or trailing decimal points in numeric literals.
"no-floating-decimal": 0,
"no-floating-decimal": "off",
// Allow comments inline after code.
"no-inline-comments": 0,
"no-inline-comments": "off",
// Disallow use of labels for anything other then loops and switches.
"no-labels": [2, {"allowLoop": true}],
"no-labels": ["error", {"allowLoop": true}],
// Disallow use of multiline strings (use template strings instead).
"no-multi-str": 1,
"no-multi-str": "warn",
// Disallow multiple empty lines.
"no-multiple-empty-lines": [1, {"max": 2}],
"no-multiple-empty-lines": ["warn", {"max": 2}],
// Allow reassignment of function parameters.
"no-param-reassign": 0,
"no-param-reassign": "off",
// Allow string concatenation with __dirname and __filename (not a node env).
"no-path-concat": 0,
"no-path-concat": "off",
// Allow use of unary operators, ++ and --.
"no-plusplus": 0,
"no-plusplus": "off",
// Allow using process.env (not a node environment).
"no-process-env": 0,
"no-process-env": "off",
// Allow using process.exit (not a node environment).
"no-process-exit": 0,
"no-process-exit": "off",
// Disallow usage of __proto__ property.
"no-proto": 2,
"no-proto": "error",
// Disallow multiple spaces in a regular expression literal.
"no-regex-spaces": 2,
"no-regex-spaces": "error",
// Allow reserved words being used as object literal keys.
"no-reserved-keys": 0,
"no-reserved-keys": "off",
// Don't restrict usage of specified node modules (not a node environment).
"no-restricted-modules": 0,
"no-restricted-modules": "off",
// Disallow use of assignment in return statement. It is preferable for a
// single line of code to have only one easily predictable effect.
"no-return-assign": 2,
"no-return-assign": "error",
// Don't warn about declaration of variables already declared in the outer scope.
"no-shadow": 0,
"no-shadow": "off",
// Disallow shadowing of names such as arguments.
"no-shadow-restricted-names": 2,
"no-shadow-restricted-names": "error",
// Allow use of synchronous methods (not a node environment).
"no-sync": 0,
"no-sync": "off",
// Allow the use of ternary operators.
"no-ternary": 0,
"no-ternary": "off",
// Disallow throwing literals (eg. throw "error" instead of
// throw new Error("error")).
"no-throw-literal": 2,
"no-throw-literal": "error",
// Disallow use of undeclared variables unless mentioned in a /* global */
// block. Note that globals from head.js are automatically imported in tests
// by the import-headjs-globals rule form the mozilla eslint plugin.
"no-undef": 2,
"no-undef": "error",
// Allow dangling underscores in identifiers (for privates).
"no-underscore-dangle": 0,
"no-underscore-dangle": "off",
// Allow use of undefined variable.
"no-undefined": 0,
"no-undefined": "off",
// Disallow the use of Boolean literals in conditional expressions.
"no-unneeded-ternary": 2,
"no-unneeded-ternary": "error",
// We use var-only-at-top-level instead of no-var as we allow top level
// vars.
"no-var": 0,
"no-var": "off",
// Allow using TODO/FIXME comments.
"no-warning-comments": 0,
"no-warning-comments": "off",
// Don't require method and property shorthand syntax for object literals.
// We use this in the code a lot, but not consistently, and this seems more
// like something to check at code review time.
"object-shorthand": 0,
"object-shorthand": "off",
// Allow more than one variable declaration per function.
"one-var": 0,
"one-var": "off",
// Disallow padding within blocks.
"padded-blocks": [1, "never"],
"padded-blocks": ["warn", "never"],
// Don't require quotes around object literal property names.
"quote-props": 0,
"quote-props": "off",
// Double quotes should be used.
"quotes": [1, "double", {"avoidEscape": true, "allowTemplateLiterals": true}],
"quotes": ["warn", "double", {"avoidEscape": true, "allowTemplateLiterals": true}],
// Require use of the second argument for parseInt().
"radix": 2,
"radix": "error",
// Enforce spacing after semicolons.
"semi-spacing": [2, {"before": false, "after": true}],
"semi-spacing": ["error", {"before": false, "after": true}],
// Don't require to sort variables within the same declaration block.
// Anyway, one-var is disabled.
"sort-vars": 0,
"sort-vars": "off",
// Require a space immediately following the // in a line comment.
"spaced-comment": [2, "always"],
"spaced-comment": ["error", "always"],
// Require "use strict" to be defined globally in the script.
"strict": [2, "global"],
"strict": ["error", "global"],
// Allow vars to be declared anywhere in the scope.
"vars-on-top": 0,
"vars-on-top": "off",
// Don't require immediate function invocation to be wrapped in parentheses.
"wrap-iife": 0,
"wrap-iife": "off",
// Don't require regex literals to be wrapped in parentheses (which
// supposedly prevent them from being mistaken for division operators).
"wrap-regex": 0,
"wrap-regex": "off",
// Disallow Yoda conditions (where literal value comes first).
"yoda": 2,
"yoda": "error",
// disallow use of eval()-like methods
"no-implied-eval": 2,
"no-implied-eval": "error",
// Disallow function or variable declarations in nested blocks
"no-inner-declarations": 2,
"no-inner-declarations": "error",
// Disallow usage of __iterator__ property
"no-iterator": 2,
"no-iterator": "error",
// Disallow labels that share a name with a variable
"no-label-var": 2,
"no-label-var": "error",
// Disallow creating new instances of String, Number, and Boolean
"no-new-wrappers": 2,
"no-new-wrappers": "error",
},
};

Просмотреть файл

@ -412,7 +412,7 @@ Section "Uninstall"
Delete /REBOOTOK "$INSTDIR\update-settings.ini"
${EndIf}
; Explictly remove empty webapprt dir in case it exists (bug 757978).
; Explicitly remove empty webapprt dir in case it exists (bug 757978).
RmDir "$INSTDIR\webapprt\components"
RmDir "$INSTDIR\webapprt"

Просмотреть файл

@ -6,6 +6,7 @@ const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
// The name of the search engine used to generate suggestions.
const SUGGESTION_ENGINE_NAME = "browser_UsageTelemetry usageTelemetrySearchSuggestions.xml";
const ONEOFF_URLBAR_PREF = "browser.urlbar.oneOffSearches";
let searchInAwesomebar = Task.async(function* (inputText, win=window) {
yield new Promise(r => waitForFocus(r, win));
@ -55,11 +56,15 @@ add_task(function* setup() {
// Enable search suggestions in the urlbar.
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
// Enable the urlbar one-off buttons.
Services.prefs.setBoolPref(ONEOFF_URLBAR_PREF, true);
// Make sure to restore the engine once we're done.
registerCleanupFunction(function* () {
Services.search.currentEngine = originalEngine;
Services.search.removeEngine(engine);
Services.prefs.clearUserPref(SUGGEST_URLBAR_PREF, true);
Services.prefs.clearUserPref(ONEOFF_URLBAR_PREF);
});
});

Просмотреть файл

@ -37,28 +37,28 @@ module.exports = {
// devtools coding style.
// Rules from the mozilla plugin
"mozilla/no-aArgs": 1,
"mozilla/no-cpows-in-tests": 2,
"mozilla/no-single-arg-cu-import": 2,
"mozilla/no-aArgs": "warn",
"mozilla/no-cpows-in-tests": "error",
"mozilla/no-single-arg-cu-import": "error",
// See bug 1224289.
"mozilla/reject-importGlobalProperties": 2,
"mozilla/reject-importGlobalProperties": "error",
// devtools/shared/platform is special; see the README.md in that
// directory for details. We reject requires using explicit
// subdirectories of this directory.
"mozilla/reject-some-requires": [2, "^devtools/shared/platform/(chome|content)/"],
"mozilla/var-only-at-top-level": 1,
"mozilla/reject-some-requires": ["error", "^devtools/shared/platform/(chome|content)/"],
"mozilla/var-only-at-top-level": "warn",
// Rules from the React plugin
"react/display-name": 2,
"react/no-danger": 2,
"react/no-did-mount-set-state": 2,
"react/no-did-update-set-state": 2,
"react/no-direct-mutation-state": 2,
"react/no-unknown-property": 2,
"react/prefer-es6-class": [1, "never"],
"react/display-name": "error",
"react/no-danger": "error",
"react/no-did-mount-set-state": "error",
"react/no-did-update-set-state": "error",
"react/no-direct-mutation-state": "error",
"react/no-unknown-property": "error",
"react/prefer-es6-class": ["warn", "never"],
// Disabled temporarily until errors are fixed.
"react/prop-types": 0,
"react/sort-comp": [2, {
"react/prop-types": "off",
"react/sort-comp": ["error", {
order: [
"lifecycle",
"everything-else",
@ -91,382 +91,382 @@ module.exports = {
// Disallow using variables outside the blocks they are defined (especially
// since only let and const are used, see "no-var").
"block-scoped-var": 2,
"block-scoped-var": "error",
// Enforce one true brace style (opening brace on the same line) and avoid
// start and end braces on the same line.
"brace-style": [2, "1tbs", {"allowSingleLine": false}],
"brace-style": ["error", "1tbs", {"allowSingleLine": false}],
// Require camel case names
"camelcase": 2,
"camelcase": "error",
// Allow trailing commas for easy list extension. Having them does not
// impair readability, but also not required either.
"comma-dangle": 0,
"comma-dangle": "off",
// Enforce spacing before and after comma
"comma-spacing": [2, {"before": false, "after": true}],
"comma-spacing": ["error", {"before": false, "after": true}],
// Enforce one true comma style.
"comma-style": [2, "last"],
"comma-style": ["error", "last"],
// Warn about cyclomatic complexity in functions.
"complexity": [2, 35],
"complexity": ["error", 35],
// Require return statements to either always or never specify values.
"consistent-return": 2,
"consistent-return": "error",
// Don't warn for inconsistent naming when capturing this (not so important
// with auto-binding fat arrow functions).
"consistent-this": 0,
"consistent-this": "off",
// Enforce curly brace conventions for all control statements.
"curly": 2,
"curly": "error",
// Don't require a default case in switch statements. Avoid being forced to
// add a bogus default when you know all possible cases are handled.
"default-case": 0,
"default-case": "off",
// Enforce dots on the next line with property name.
"dot-location": [2, "property"],
"dot-location": ["error", "property"],
// Encourage the use of dot notation whenever possible.
"dot-notation": 2,
"dot-notation": "error",
// Enforce newline at the end of file, with no multiple empty lines.
"eol-last": 2,
"eol-last": "error",
// Allow using == instead of ===, in the interest of landing something since
// the devtools codebase is split on convention here.
"eqeqeq": 0,
"eqeqeq": "off",
// Don't require function expressions to have a name.
// This makes the code more verbose and hard to read. Our engine already
// does a fantastic job assigning a name to the function, which includes
// the enclosing function name, and worst case you have a line number that
// you can just look up.
"func-names": 0,
"func-names": "off",
// Allow use of function declarations and expressions.
"func-style": 0,
"func-style": "off",
// Deprecated, will be removed in 1.0.
"generator-star": 0,
"generator-star": "off",
// Enforce the spacing around the * in generator functions.
"generator-star-spacing": [2, "after"],
"generator-star-spacing": ["error", "after"],
// Deprecated, will be removed in 1.0.
"global-strict": 0,
"global-strict": "off",
// Only useful in a node environment.
"handle-callback-err": 0,
"handle-callback-err": "off",
// Tab width.
"indent": [2, 2, {"SwitchCase": 1}],
"indent": ["error", 2, {"SwitchCase": 1}],
// Enforces spacing between keys and values in object literal properties.
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"key-spacing": ["error", {"beforeColon": false, "afterColon": true}],
// Enforces unix style line breaks.
"linebreak-style": [2, "unix"],
"linebreak-style": ["error", "unix"],
// Don't enforce the maximum depth that blocks can be nested. The complexity
// rule is a better rule to check this.
"max-depth": 0,
"max-depth": "off",
// Maximum length of a line.
"max-len": [2, 90, 2, {
"max-len": ["error", 90, 2, {
"ignoreUrls": true,
"ignorePattern": "data:image\/|\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-"
}],
// Maximum depth callbacks can be nested.
"max-nested-callbacks": [2, 3],
"max-nested-callbacks": ["error", 3],
// Don't limit the number of parameters that can be used in a function.
"max-params": 0,
"max-params": "off",
// Don't limit the maximum number of statement allowed in a function. We
// already have the complexity rule that's a better measurement.
"max-statements": 0,
"max-statements": "off",
// Require a capital letter for constructors, only check if all new
// operators are followed by a capital letter. Don't warn when capitalized
// functions are used without the new operator.
"new-cap": [2, {"capIsNew": false}],
"new-cap": ["error", {"capIsNew": false}],
// Disallow the omission of parentheses when invoking a constructor with no
// arguments.
"new-parens": 2,
"new-parens": "error",
// Disallow use of the Array constructor.
"no-array-constructor": 2,
"no-array-constructor": "error",
// Allow use of bitwise operators.
"no-bitwise": 0,
"no-bitwise": "off",
// Disallow use of arguments.caller or arguments.callee.
"no-caller": 2,
"no-caller": "error",
// Disallow the catch clause parameter name being the same as a variable in
// the outer scope, to avoid confusion.
"no-catch-shadow": 2,
"no-catch-shadow": "error",
// Deprecated, will be removed in 1.0.
"no-comma-dangle": 0,
"no-comma-dangle": "off",
// Disallow assignment in conditional expressions.
"no-cond-assign": 2,
"no-cond-assign": "error",
// Allow using the console API.
"no-console": 0,
"no-console": "off",
// Allow using constant expressions in conditions like while (true)
"no-constant-condition": 0,
"no-constant-condition": "off",
// Allow use of the continue statement.
"no-continue": 0,
"no-continue": "off",
// Disallow control characters in regular expressions.
"no-control-regex": 2,
"no-control-regex": "error",
// Disallow use of debugger.
"no-debugger": 2,
"no-debugger": "error",
// Disallow deletion of variables (deleting properties is fine).
"no-delete-var": 2,
"no-delete-var": "error",
// Allow division operators explicitly at beginning of regular expression.
"no-div-regex": 0,
"no-div-regex": "off",
// Disallow duplicate arguments in functions.
"no-dupe-args": 2,
"no-dupe-args": "error",
// Disallow duplicate keys when creating object literals.
"no-dupe-keys": 2,
"no-dupe-keys": "error",
// Disallow a duplicate case label.
"no-duplicate-case": 2,
"no-duplicate-case": "error",
// Disallow else after a return in an if. The else around the second return
// here is useless:
// if (something) { return false; } else { return true; }
"no-else-return": 2,
"no-else-return": "error",
// Disallow empty statements. This will report an error for:
// try { something(); } catch (e) {}
// but will not report it for:
// try { something(); } catch (e) { /* Silencing the error because ...*/ }
// which is a valid use case.
"no-empty": 2,
"no-empty": "error",
// Disallow the use of empty character classes in regular expressions.
"no-empty-character-class": 2,
"no-empty-character-class": "error",
// Disallow use of eval(). We have other APIs to evaluate code in content.
"no-eval": 2,
"no-eval": "error",
// Disallow assigning to the exception in a catch block.
"no-ex-assign": 2,
"no-ex-assign": "error",
// Disallow adding to native types
"no-extend-native": 2,
"no-extend-native": "error",
// Disallow unnecessary function binding.
"no-extra-bind": 2,
"no-extra-bind": "error",
// Disallow double-negation boolean casts in a boolean context.
"no-extra-boolean-cast": 2,
"no-extra-boolean-cast": "error",
// Allow unnecessary parentheses, as they may make the code more readable.
"no-extra-parens": 0,
"no-extra-parens": "off",
// Disallow unnecessary semicolons.
"no-extra-semi": 2,
"no-extra-semi": "error",
// Deprecated, will be removed in 1.0.
"no-extra-strict": 0,
"no-extra-strict": "off",
// Disallow fallthrough of case statements, except if there is a comment.
"no-fallthrough": 2,
"no-fallthrough": "error",
// Allow the use of leading or trailing decimal points in numeric literals.
"no-floating-decimal": 0,
"no-floating-decimal": "off",
// Disallow comments inline after code.
"no-inline-comments": 2,
"no-inline-comments": "error",
// Disallow if as the only statement in an else block.
"no-lonely-if": 2,
"no-lonely-if": "error",
// Allow mixing regular variable and require declarations (not a node env).
"no-mixed-requires": 0,
"no-mixed-requires": "off",
// Disallow mixed spaces and tabs for indentation.
"no-mixed-spaces-and-tabs": 2,
"no-mixed-spaces-and-tabs": "error",
// Disallow use of multiple spaces (sometimes used to align const values,
// array or object items, etc.). It's hard to maintain and doesn't add that
// much benefit.
"no-multi-spaces": 2,
"no-multi-spaces": "error",
// Disallow use of multiline strings (use template strings instead).
"no-multi-str": 2,
"no-multi-str": "error",
// Disallow multiple empty lines.
"no-multiple-empty-lines": [2, {"max": 1}],
"no-multiple-empty-lines": ["error", {"max": 1}],
// Disallow reassignments of native objects.
"no-native-reassign": 2,
"no-native-reassign": "error",
// Disallow nested ternary expressions, they make the code hard to read.
"no-nested-ternary": 2,
"no-nested-ternary": "error",
// Allow use of new operator with the require function.
"no-new-require": 0,
"no-new-require": "off",
// Disallow use of octal literals.
"no-octal": 2,
"no-octal": "error",
// Allow reassignment of function parameters.
"no-param-reassign": 0,
"no-param-reassign": "off",
// Allow string concatenation with __dirname and __filename (not a node env).
"no-path-concat": 0,
"no-path-concat": "off",
// Allow use of unary operators, ++ and --.
"no-plusplus": 0,
"no-plusplus": "off",
// Allow using process.env (not a node environment).
"no-process-env": 0,
"no-process-env": "off",
// Allow using process.exit (not a node environment).
"no-process-exit": 0,
"no-process-exit": "off",
// Disallow usage of __proto__ property.
"no-proto": 2,
"no-proto": "error",
// Disallow declaring the same variable more than once (we use let anyway).
"no-redeclare": 2,
"no-redeclare": "error",
// Disallow multiple spaces in a regular expression literal.
"no-regex-spaces": 2,
"no-regex-spaces": "error",
// Allow reserved words being used as object literal keys.
"no-reserved-keys": 0,
"no-reserved-keys": "off",
// Don't restrict usage of specified node modules (not a node environment).
"no-restricted-modules": 0,
"no-restricted-modules": "off",
// Disallow use of assignment in return statement. It is preferable for a
// single line of code to have only one easily predictable effect.
"no-return-assign": 2,
"no-return-assign": "error",
// Allow use of javascript: urls.
"no-script-url": 0,
"no-script-url": "off",
// Disallow comparisons where both sides are exactly the same.
"no-self-compare": 2,
"no-self-compare": "error",
// Disallow use of comma operator.
"no-sequences": 2,
"no-sequences": "error",
// Warn about declaration of variables already declared in the outer scope.
// This isn't an error because it sometimes is useful to use the same name
// in a small helper function rather than having to come up with another
// random name.
// Still, making this a warning can help people avoid being confused.
"no-shadow": 2,
"no-shadow": "error",
// Disallow shadowing of names such as arguments.
"no-shadow-restricted-names": 2,
"no-shadow-restricted-names": "error",
// Deprecated, will be removed in 1.0.
"no-space-before-semi": 0,
"no-space-before-semi": "off",
// Disallow space between function identifier and application.
"no-spaced-func": 2,
"no-spaced-func": "error",
// Disallow sparse arrays, eg. let arr = [,,2].
// Array destructuring is fine though:
// for (let [, breakpointPromise] of aPromises)
"no-sparse-arrays": 2,
"no-sparse-arrays": "error",
// Allow use of synchronous methods (not a node environment).
"no-sync": 0,
"no-sync": "off",
// Allow the use of ternary operators.
"no-ternary": 0,
"no-ternary": "off",
// Disallow throwing literals (eg. throw "error" instead of
// throw new Error("error")).
"no-throw-literal": 2,
"no-throw-literal": "error",
// Disallow trailing whitespace at the end of lines.
"no-trailing-spaces": 2,
"no-trailing-spaces": "error",
// Disallow use of undeclared variables unless mentioned in a /*global */
// block. Note that globals from head.js are automatically imported in tests
// by the import-headjs-globals rule form the mozilla eslint plugin.
"no-undef": 2,
"no-undef": "error",
// Allow dangling underscores in identifiers (for privates).
"no-underscore-dangle": 0,
"no-underscore-dangle": "off",
// Allow use of undefined variable.
"no-undefined": 0,
"no-undefined": "off",
// Disallow the use of Boolean literals in conditional expressions.
"no-unneeded-ternary": 2,
"no-unneeded-ternary": "error",
// Disallow unreachable statements after a return, throw, continue, or break
// statement.
"no-unreachable": 2,
"no-unreachable": "error",
// Disallow global and local variables that aren't used, but allow unused
// function arguments.
"no-unused-vars": [2, {"vars": "all", "args": "none"}],
"no-unused-vars": ["error", {"vars": "all", "args": "none"}],
// Allow using variables before they are defined.
"no-use-before-define": 0,
"no-use-before-define": "off",
// We use var-only-at-top-level instead of no-var as we allow top level
// vars.
"no-var": 0,
"no-var": "off",
// Allow using TODO/FIXME comments.
"no-warning-comments": 0,
"no-warning-comments": "off",
// Disallow use of the with statement.
"no-with": 2,
"no-with": "error",
// Don't require method and property shorthand syntax for object literals.
// We use this in the code a lot, but not consistently, and this seems more
// like something to check at code review time.
"object-shorthand": 0,
"object-shorthand": "off",
// Allow more than one variable declaration per function.
"one-var": 0,
"one-var": "off",
// Disallow padding within blocks.
"padded-blocks": [2, "never"],
"padded-blocks": ["error", "never"],
// Don't require quotes around object literal property names.
"quote-props": 0,
"quote-props": "off",
// Double quotes should be used. Other quote characters can be used around strings
// with embedded double quotes to avoid escaping them. Template literals are allowed
// mainly for building multi-line messages where only some lines use substitution.
"quotes": [2, "double", {"avoidEscape": true, "allowTemplateLiterals": true}],
"quotes": ["error", "double", {"avoidEscape": true, "allowTemplateLiterals": true}],
// Require use of the second argument for parseInt().
"radix": 2,
"radix": "error",
// Always require use of semicolons wherever they are valid.
"semi": [2, "always"],
"semi": ["error", "always"],
// Enforce spacing after semicolons.
"semi-spacing": [2, {"before": false, "after": true}],
"semi-spacing": ["error", {"before": false, "after": true}],
// Don't require to sort variables within the same declaration block.
// Anyway, one-var is disabled.
"sort-vars": 0,
"sort-vars": "off",
// Deprecated, will be removed in 1.0.
"space-after-function-name": 0,
"space-after-function-name": "off",
// Require a space around all keywords.
"keyword-spacing": 2,
"keyword-spacing": "error",
// Require a space before the start brace of a block.
"space-before-blocks": [2, "always"],
"space-before-blocks": ["error", "always"],
// Deprecated, will be removed in 1.0.
"space-before-function-parentheses": 0,
"space-before-function-parentheses": "off",
// Require space after keyword for anonymous functions, but disallow space
// after name of named functions.
"space-before-function-paren": [2, {"anonymous": "always", "named": "never"}],
"space-before-function-paren": ["error", {"anonymous": "always", "named": "never"}],
// Disable the rule that checks if spaces inside {} and [] are there or not.
// Our code is split on conventions, and it'd be nice to have 2 rules
// Our code is split on conventions, and it'd be nice to have "error" rules
// instead, one for [] and one for {}. So, disabling until we write them.
"space-in-brackets": 0,
"space-in-brackets": "off",
// Disallow spaces inside parentheses.
"space-in-parens": [2, "never"],
// Require spaces around operators, except for a|0.
"space-infix-ops": [2, {"int32Hint": true}],
"space-in-parens": ["error", "never"],
// Require spaces around operators, except for a|"off".
"space-infix-ops": ["error", {"int32Hint": true}],
// Require spaces before/after unary operators (words on by default,
// nonwords off by default).
"space-unary-ops": [2, { "words": true, "nonwords": false }],
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
// Deprecated, will be removed in 1.0.
"space-unary-word-ops": 0,
"space-unary-word-ops": "off",
// Require a space immediately following the // in a line comment.
"spaced-comment": [2, "always"],
"spaced-comment": ["error", "always"],
// Require "use strict" to be defined globally in the script.
"strict": [2, "global"],
"strict": ["error", "global"],
// Disallow comparisons with the value NaN.
"use-isnan": 2,
"use-isnan": "error",
// Warn about invalid JSDoc comments.
// Disabled for now because of https://github.com/eslint/eslint/issues/2270
// The rule fails on some jsdoc comments like in:
// devtools/client/webconsole/console-output.js
"valid-jsdoc": 0,
"valid-jsdoc": "off",
// Ensure that the results of typeof are compared against a valid string.
"valid-typeof": 2,
"valid-typeof": "error",
// Allow vars to be declared anywhere in the scope.
"vars-on-top": 0,
"vars-on-top": "off",
// Don't require immediate function invocation to be wrapped in parentheses.
"wrap-iife": 0,
"wrap-iife": "off",
// Don't require regex literals to be wrapped in parentheses (which
// supposedly prevent them from being mistaken for division operators).
"wrap-regex": 0,
"wrap-regex": "off",
// Disallow Yoda conditions (where literal value comes first).
"yoda": 2,
"yoda": "error",
// And these are the rules that haven't been discussed so far, and that are
// disabled for now until we introduce them, one at a time.
// Require for-in loops to have an if statement.
"guard-for-in": 0,
"guard-for-in": "off",
// allow/disallow an empty newline after var statement
"newline-after-var": 0,
"newline-after-var": "off",
// disallow the use of alert, confirm, and prompt
"no-alert": 0,
"no-alert": "off",
// disallow comparisons to null without a type-checking operator
"no-eq-null": 0,
"no-eq-null": "off",
// disallow overwriting functions written as function declarations
"no-func-assign": 0,
"no-func-assign": "off",
// disallow use of eval()-like methods
"no-implied-eval": 0,
"no-implied-eval": "off",
// disallow function or variable declarations in nested blocks
"no-inner-declarations": 0,
"no-inner-declarations": "off",
// disallow invalid regular expression strings in the RegExp constructor
"no-invalid-regexp": 0,
"no-invalid-regexp": "off",
// disallow irregular whitespace outside of strings and comments
"no-irregular-whitespace": 0,
"no-irregular-whitespace": "off",
// disallow usage of __iterator__ property
"no-iterator": 0,
"no-iterator": "off",
// disallow labels that share a name with a variable
"no-label-var": 0,
"no-label-var": "off",
// disallow use of labeled statements
"no-labels": 2,
"no-labels": "error",
// disallow unnecessary nested blocks
"no-lone-blocks": 0,
"no-lone-blocks": "off",
// disallow creation of functions within loops
"no-loop-func": 0,
"no-loop-func": "off",
// disallow negation of the left operand of an in expression
"no-negated-in-lhs": 0,
"no-negated-in-lhs": "off",
// disallow use of new operator when not part of the assignment or
// comparison
"no-new": 0,
"no-new": "off",
// disallow use of new operator for Function object
"no-new-func": 0,
"no-new-func": "off",
// disallow use of the Object constructor
"no-new-object": 0,
"no-new-object": "off",
// disallows creating new instances of String,Number, and Boolean
"no-new-wrappers": 0,
"no-new-wrappers": "off",
// disallow the use of object properties of the global object (Math and
// JSON) as functions
"no-obj-calls": 0,
"no-obj-calls": "off",
// disallow use of octal escape sequences in string literals, such as
// var foo = "Copyright \251";
"no-octal-escape": 0,
"no-octal-escape": "off",
// disallow use of undefined when initializing variables
"no-undef-init": 0,
"no-undef-init": "off",
// disallow usage of expressions in statement position
"no-unused-expressions": 0,
"no-unused-expressions": "off",
// disallow use of void operator
"no-void": 0,
"no-void": "off",
// disallow wrapping of non-IIFE statements in parens
"no-wrap-func": 0,
"no-wrap-func": "off",
// require assignment operator shorthand where possible or prohibit it
// entirely
"operator-assignment": 0,
"operator-assignment": "off",
// enforce operators to be placed before or after line breaks
"operator-linebreak": 0,
"operator-linebreak": "off",
}
};

Просмотреть файл

@ -11,7 +11,7 @@ module.exports = {
"MessageEvent": true
},
"rules": {
"indent": 0,
"padded-blocks": 0,
"indent": "off",
"padded-blocks": "off",
}
};

Просмотреть файл

@ -10,6 +10,6 @@ module.exports = {
// code. Some files in the inspector disable this rule still. The
// goal is to enable the rule globally on all files.
/* eslint-disable max-len */
"mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
"mozilla/reject-some-requires": ["error", "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
},
};

Просмотреть файл

@ -10,6 +10,6 @@ module.exports = {
// code. Some files in the netmonitor disable this rule still. The
// goal is to enable the rule globally on all files.
/* eslint-disable max-len */
"mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
"mozilla/reject-some-requires": ["error", "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
},
};

Просмотреть файл

@ -0,0 +1,71 @@
/* 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";
// Make this available to both AMD and CJS environments
define(function (require, exports, module) {
// Dependencies
const React = require("devtools/client/shared/vendor/react");
const { sanitizeString, isGrip } = require("./rep-utils");
// Shortcuts
const { span } = React.DOM;
/**
* Renders a long string grip.
*/
const LongStringRep = React.createClass({
displayName: "LongStringRep",
propTypes: {
useQuotes: React.PropTypes.bool,
style: React.PropTypes.object,
},
getDefaultProps: function () {
return {
useQuotes: true,
};
},
render: function () {
let {
cropLimit,
member,
object,
style,
useQuotes
} = this.props;
let {fullText, initial, length} = object;
let config = {className: "objectBox objectBox-string"};
if (style) {
config.style = style;
}
let string = member && member.open
? fullText || initial
: initial.substring(0, cropLimit);
if (string.length < length) {
string += "\u2026";
}
let formattedString = useQuotes ? `"${string}"` : string;
return span(config, sanitizeString(formattedString));
},
});
function supportsObject(object, type) {
if (!isGrip(object)) {
return false;
}
return object.type === "longString";
}
// Exports from this module
exports.LongStringRep = {
rep: LongStringRep,
supportsObject: supportsObject,
};
});

Просмотреть файл

@ -18,6 +18,7 @@ DevToolsModules(
'grip-map.js',
'grip.js',
'infinity.js',
'long-string.js',
'nan.js',
'null.js',
'number.js',

Просмотреть файл

@ -45,15 +45,8 @@ define(function (require, exports, module) {
alternativeText = "\u2026";
}
// Make sure it's a string.
text = text + "";
// Replace all non-printable characters, except of
// (horizontal) tab (HT: \x09) and newline (LF: \x0A, CR: \x0D),
// with unicode replacement character (u+fffd).
// eslint-disable-next-line no-control-regex
let re = new RegExp("[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\x9F]", "g");
text = text.replace(re, "\ufffd");
// Make sure it's a string and sanitize it.
text = sanitizeString(text + "");
// Crop the string only if a limit is actually specified.
if (!limit || limit <= 0) {
@ -76,6 +69,15 @@ define(function (require, exports, module) {
return text;
}
function sanitizeString(text) {
// Replace all non-printable characters, except of
// (horizontal) tab (HT: \x09) and newline (LF: \x0A, CR: \x0D),
// with unicode replacement character (u+fffd).
// eslint-disable-next-line no-control-regex
let re = new RegExp("[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\x9F]", "g");
return text.replace(re, "\ufffd");
}
function parseURLParams(url) {
url = new URL(url);
return parseURLEncodedText(url.searchParams);
@ -154,4 +156,5 @@ define(function (require, exports, module) {
exports.parseURLEncodedText = parseURLEncodedText;
exports.getFileName = getFileName;
exports.getURLDisplayString = getURLDisplayString;
exports.sanitizeString = sanitizeString;
});

Просмотреть файл

@ -17,6 +17,7 @@ define(function (require, exports, module) {
const { Undefined } = require("./undefined");
const { Null } = require("./null");
const { StringRep } = require("./string");
const { LongStringRep } = require("./long-string");
const { Number } = require("./number");
const { ArrayRep } = require("./array");
const { Obj } = require("./object");
@ -55,6 +56,7 @@ define(function (require, exports, module) {
ElementNode,
TextNode,
Attribute,
LongStringRep,
Func,
PromiseRep,
ArrayRep,

Просмотреть файл

@ -19,6 +19,7 @@ support-files =
[test_reps_grip-array.html]
[test_reps_grip-map.html]
[test_reps_infinity.html]
[test_reps_long-string.html]
[test_reps_nan.html]
[test_reps_null.html]
[test_reps_number.html]

Просмотреть файл

@ -0,0 +1,125 @@
<!-- 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/. -->
<!DOCTYPE HTML>
<html>
<!--
Test LongString rep
-->
<head>
<meta charset="utf-8">
<title>Rep test - LongString</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
let { LongStringRep } = browserRequire("devtools/client/shared/components/reps/long-string");
try {
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testMultiline") });
is(renderedRep.type, LongStringRep.rep,
`Rep correctly selects ${LongStringRep.rep.displayName}`);
// Test rendering
yield testMultiline();
yield testMultilineOpen();
yield testFullText();
yield testMultilineLimit();
yield testUseQuotes();
} catch (e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
function testMultiline() {
const stub = getGripStub("testMultiline");
const renderedComponent = renderComponent(
LongStringRep.rep, { object: stub });
is(renderedComponent.textContent, `"${stub.initial}…"`,
"LongString rep has expected text content for multiline string");
}
function testMultilineLimit() {
const renderedComponent = renderComponent(
LongStringRep.rep, { object: getGripStub("testMultiline"), cropLimit: 20 });
is(
renderedComponent.textContent,
`"a\naaaaaaaaaaaaaaaaaa…"`,
"LongString rep has expected text content for multiline string " +
"with specified number of characters");
}
function testMultilineOpen() {
const stub = getGripStub("testMultiline");
const renderedComponent = renderComponent(
LongStringRep.rep, { object: stub, member: {open: true}, cropLimit: 20 });
is(renderedComponent.textContent, `"${stub.initial}…"`,
"LongString rep has expected text content for multiline string when open");
}
function testFullText() {
const stub = getGripStub("testFullText");
const renderedComponentOpen = renderComponent(
LongStringRep.rep, { object: stub, member: {open: true}, cropLimit: 20 });
is(renderedComponentOpen.textContent, `"${stub.fullText}"`,
"LongString rep has expected text content when grip has a fullText " +
"property and is open");
const renderedComponentNotOpen = renderComponent(
LongStringRep.rep, { object: stub, cropLimit: 20 });
is(renderedComponentNotOpen.textContent,
`"a\naaaaaaaaaaaaaaaaaa…"`,
"LongString rep has expected text content when grip has a fullText " +
"property and is not open");
}
function testUseQuotes() {
const renderedComponent = renderComponent(LongStringRep.rep,
{ object: getGripStub("testMultiline"), cropLimit: 20, useQuotes: false });
is(renderedComponent.textContent,
"a\naaaaaaaaaaaaaaaaaa…",
"LongString rep was expected to omit quotes");
}
function getGripStub(name) {
const multilineFullText = "a\n" + Array(20000).fill("a").join("");
const fullTextLength = multilineFullText.length;
const initialText = multilineFullText.substring(0, 10000);
switch (name) {
case "testMultiline":
return {
"type": "longString",
"initial": initialText,
"length": fullTextLength,
"actor": "server1.conn1.child1/longString58"
};
case "testFullText":
return {
"type": "longString",
"fullText": multilineFullText,
"initial": initialText,
"length": fullTextLength,
"actor": "server1.conn1.child1/longString58"
};
}
return null;
}
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -10,6 +10,6 @@ module.exports = {
// code. Some files here disable this rule still. The
// goal is to enable the rule globally on all files.
/* eslint-disable max-len */
"mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm)$"],
"mozilla/reject-some-requires": ["error", "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm)$"],
},
};

Просмотреть файл

@ -15,6 +15,6 @@ module.exports = {
"setTimeout": true
},
"rules": {
"no-unused-vars": [2, {"args": "none"}],
"no-unused-vars": ["error", {"args": "none"}],
}
};

Просмотреть файл

@ -7,6 +7,6 @@ module.exports = {
"rules": {
/* eslint-disable max-len */
// All code in this directory must be content-clean.
"mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
"mozilla/reject-some-requires": ["error", "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
},
};

Просмотреть файл

@ -14247,6 +14247,20 @@ nsDocShell::GetIsInMozBrowserOrApp(bool* aIsInMozBrowserOrApp)
return NS_OK;
}
/* [infallible] */ NS_IMETHODIMP
nsDocShell::GetIsTopLevelContentDocShell(bool* aIsTopLevelContentDocShell)
{
*aIsTopLevelContentDocShell = false;
if (mItemType == typeContent) {
nsCOMPtr<nsIDocShellTreeItem> root;
GetSameTypeRootTreeItem(getter_AddRefs(root));
*aIsTopLevelContentDocShell = root.get() == static_cast<nsIDocShellTreeItem*>(this);
}
return NS_OK;
}
/* [infallible] */ NS_IMETHODIMP
nsDocShell::GetAppId(uint32_t* aAppId)
{

Просмотреть файл

@ -851,6 +851,11 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[infallible] readonly attribute boolean isInMozBrowserOrApp;
/**
* Returns true if this docshell is the top level content docshell.
*/
[infallible] readonly attribute boolean isTopLevelContentDocShell;
/**
* Returns the id of the app associated with this docshell. If this docshell
* is an <iframe mozbrowser> inside an <iframe mozapp>, we return the app's

Просмотреть файл

@ -257,6 +257,20 @@ var tests = [
is(xhr.responseText, "a3", "We got the expected file body");
},
},
// Load one last time to reset the state variable in the .sjs file
{
init: function (xhr) {
xhr.open("GET", path + "bug475156.sjs");
xhr.setRequestHeader("If-Match", "a1");
},
loading: function (xhr) {
},
done: function (xhr) {
},
},
]
@ -280,7 +294,6 @@ function drive(test)
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -13,7 +13,6 @@
#include "mozilla/Telemetry.h"
#include "OggDecoder.h"
#include "OggReader.h"
#include "OggDemuxer.h"
#include "WebMDecoder.h"
@ -39,7 +38,6 @@
#include "WaveDecoder.h"
#include "WaveDemuxer.h"
#include "WaveReader.h"
#include "ADTSDecoder.h"
#include "ADTSDemuxer.h"
@ -66,7 +64,7 @@ CodecListContains(char const *const * aCodecs, const String& aCodec)
static bool
IsOggSupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
const nsAString& aCodecs = EmptyString())
{
return OggDecoder::CanHandleMediaType(aType, aCodecs);
}
@ -77,34 +75,6 @@ IsOggTypeAndEnabled(const nsACString& aType)
return IsOggSupportedType(aType);
}
// See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions
// of WAVE media types and codec types. However, the audio/vnd.wave
// MIME type described there is not used.
static const char* const gWaveTypes[5] = {
"audio/x-wav",
"audio/wav",
"audio/wave",
"audio/x-pn-wav",
nullptr
};
static char const *const gWaveCodecs[4] = {
"1", // Microsoft PCM Format
"6", // aLaw Encoding
"7", // uLaw Encoding
nullptr
};
static bool
IsWaveType(const nsACString& aType)
{
if (!MediaDecoder::IsWaveEnabled()) {
return false;
}
return CodecListContains(gWaveTypes, aType);
}
static bool
IsWebMSupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
@ -205,8 +175,8 @@ IsAACSupportedType(const nsACString& aType,
}
static bool
IsWAVSupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
IsWaveSupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
{
return WaveDecoder::CanHandleMediaType(aType, aCodecs);
}
@ -237,8 +207,14 @@ CanHandleCodecsType(const MediaContentType& aType,
return CANPLAY_NO;
}
}
if (IsWaveType(aType.GetMIMEType())) {
codecList = gWaveCodecs;
if (IsWaveSupportedType(aType.GetMIMEType())) {
if (IsWaveSupportedType(aType.GetMIMEType(), aType.GetCodecs())) {
return CANPLAY_YES;
} else {
// We can only reach this position if a particular codec was requested,
// ogg is supported and working: the codec must be invalid.
return CANPLAY_NO;
}
}
#if !defined(MOZ_OMX_WEBM_DECODER)
if (DecoderTraits::IsWebMTypeAndEnabled(aType.GetMIMEType())) {
@ -324,7 +300,7 @@ CanHandleMediaType(const MediaContentType& aType,
if (IsOggTypeAndEnabled(aType.GetMIMEType())) {
return CANPLAY_MAYBE;
}
if (IsWaveType(aType.GetMIMEType())) {
if (IsWaveSupportedType(aType.GetMIMEType())) {
return CANPLAY_MAYBE;
}
if (DecoderTraits::IsMP4TypeAndEnabled(aType.GetMIMEType(), aDiagnostics)) {
@ -374,7 +350,7 @@ DecoderTraits::CanHandleContentType(const MediaContentType& aContentType,
bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType,
DecoderDoctorDiagnostics* aDiagnostics)
{
if (IsWaveType(nsDependentCString(aMIMEType))) {
if (IsWaveSupportedType(nsDependentCString(aMIMEType))) {
// We should not return true for Wave types, since there are some
// Wave codecs actually in use in the wild that we don't support, and
// we should allow those to be handled by plugins or helper apps.
@ -427,7 +403,7 @@ InstantiateDecoder(const nsACString& aType,
decoder = new OggDecoder(aOwner);
return decoder.forget();
}
if (IsWaveType(aType)) {
if (IsWaveSupportedType(aType)) {
decoder = new WaveDecoder(aOwner);
return decoder.forget();
}
@ -495,19 +471,14 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
if (IsAACSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new ADTSDemuxer(aDecoder->GetResource()));
} else
if (IsWAVSupportedType(aType)) {
if (IsWaveSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new WAVDemuxer(aDecoder->GetResource()));
} else
if (IsFlacSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new FlacDemuxer(aDecoder->GetResource()));
} else
if (IsOggSupportedType(aType)) {
decoderReader = MediaPrefs::OggFormatReader() ?
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new OggDemuxer(aDecoder->GetResource()))) :
new OggReader(aDecoder);
} else
if (IsWaveType(aType)) {
decoderReader = new WaveReader(aDecoder);
decoderReader = new MediaFormatReader(aDecoder, new OggDemuxer(aDecoder->GetResource()));
} else
#ifdef MOZ_ANDROID_OMX
if (MediaDecoder::IsAndroidMediaPluginEnabled() &&

Просмотреть файл

@ -357,6 +357,7 @@ public:
void Enter()
{
MOZ_ASSERT(!mMaster->mVideoDecodeSuspended);
mMaster->UpdateNextFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE);
}
void Exit() override
@ -568,6 +569,10 @@ public:
mMaster->UpdatePlaybackPositionPeriodically();
// Ensure currentTime is up to date prior updating mNextFrameStatus so that
// the MediaDecoderOwner fire events at correct currentTime.
mMaster->UpdateNextFrameStatus();
MOZ_ASSERT(!mMaster->IsPlaying() ||
mMaster->IsStateMachineScheduled(),
"Must have timer scheduled");
@ -758,6 +763,7 @@ public:
EventVisibility aVisibility)
{
mSeekJob = Move(aSeekJob);
mVisibility = aVisibility;
// Always switch off the blank decoder otherwise we might become visible
// in the middle of seeking and won't have a valid video frame to show
@ -798,8 +804,11 @@ public:
mMaster->UpdatePlaybackPositionInternal(
mSeekTask->GetSeekTarget().GetTime().ToMicroseconds());
if (aVisibility == EventVisibility::Observable) {
if (mVisibility == EventVisibility::Observable) {
mMaster->mOnPlaybackEvent.Notify(MediaEventType::SeekStarted);
// We want dormant actions to be transparent to the user.
// So we only notify the change when the seek request is from the user.
mMaster->UpdateNextFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING);
}
// Reset our state machine and decoding pipeline before seeking.
@ -906,6 +915,7 @@ private:
void SeekCompleted();
SeekJob mSeekJob;
EventVisibility mVisibility = EventVisibility::Observable;
MozPromiseRequestHolder<SeekTask::SeekTaskPromise> mSeekTaskRequest;
RefPtr<SeekTask> mSeekTask;
};
@ -939,6 +949,8 @@ public:
stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)");
mMaster->ScheduleStateMachineIn(USECS_PER_S);
mMaster->UpdateNextFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING);
}
void Step() override;
@ -1323,6 +1335,8 @@ DecodingFirstFrameState::Enter(SeekJob aPendingSeek)
// Dispatch tasks to decode first frames.
mMaster->DispatchDecodeTasksIfNeeded();
mMaster->UpdateNextFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE);
}
RefPtr<MediaDecoder::SeekPromise>
@ -1519,6 +1533,10 @@ SeekingState::SeekCompleted()
mMaster->mOnPlaybackEvent.Notify(MediaEventType::Invalidate);
}
if (mVisibility == EventVisibility::Observable) {
mMaster->UpdateNextFrameStatus();
}
if (nextState == DECODER_STATE_COMPLETED) {
SetState<CompletedState>();
} else {
@ -1666,7 +1684,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mWatchManager(this, mTaskQueue),
mDispatchedStateMachine(false),
mDelayedScheduler(mTaskQueue),
INIT_WATCHABLE(mState, DECODER_STATE_DECODING_METADATA),
mCurrentFrameID(0),
INIT_WATCHABLE(mObservedDuration, TimeUnit()),
mFragmentEndTime(-1),
@ -1677,8 +1694,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
mAudioCaptured(false),
INIT_WATCHABLE(mAudioCompleted, false),
INIT_WATCHABLE(mVideoCompleted, false),
mNotifyMetadataBeforeFirstFrame(false),
mMinimizePreroll(false),
mSentLoadedMetadataEvent(false),
@ -1758,9 +1773,6 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
// Initialize watchers.
mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated);
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVideoCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
mWatchManager.Watch(mEstimatedDuration, &MediaDecoderStateMachine::RecomputeDuration);
@ -1997,7 +2009,6 @@ MediaDecoderStateMachine::Push(MediaData* aSample, MediaData::Type aSampleType)
} else {
// TODO: Handle MediaRawData, determine which queue should be pushed.
}
UpdateNextFrameStatus();
DispatchDecodeTasksIfNeeded();
}
@ -2007,7 +2018,6 @@ MediaDecoderStateMachine::OnAudioPopped(const RefPtr<MediaData>& aSample)
MOZ_ASSERT(OnTaskQueue());
mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
UpdateNextFrameStatus();
DispatchAudioDecodeTaskIfNeeded();
}
@ -2016,7 +2026,6 @@ MediaDecoderStateMachine::OnVideoPopped(const RefPtr<MediaData>& aSample)
{
MOZ_ASSERT(OnTaskQueue());
mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
UpdateNextFrameStatus();
DispatchVideoDecodeTaskIfNeeded();
}
@ -2928,41 +2937,36 @@ MediaDecoderStateMachine::UpdatePlaybackPositionPeriodically()
ScheduleStateMachineIn(delay);
}
void MediaDecoderStateMachine::UpdateNextFrameStatus()
/* static */ const char*
MediaDecoderStateMachine::ToStr(NextFrameStatus aStatus)
{
switch (aStatus) {
case MediaDecoderOwner::NEXT_FRAME_AVAILABLE: return "NEXT_FRAME_AVAILABLE";
case MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE: return "NEXT_FRAME_UNAVAILABLE";
case MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING: return "NEXT_FRAME_UNAVAILABLE_BUFFERING";
case MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING: return "NEXT_FRAME_UNAVAILABLE_SEEKING";
case MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED: return "NEXT_FRAME_UNINITIALIZED";
}
return "UNKNOWN";
}
void
MediaDecoderStateMachine::UpdateNextFrameStatus(NextFrameStatus aStatus)
{
MOZ_ASSERT(OnTaskQueue());
MediaDecoderOwner::NextFrameStatus status;
const char* statusString;
switch (mState.Ref()) {
case DECODER_STATE_BUFFERING:
status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING;
statusString = "NEXT_FRAME_UNAVAILABLE_BUFFERING";
break;
case DECODER_STATE_SEEKING:
status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING;
statusString = "NEXT_FRAME_UNAVAILABLE_SEEKING";
break;
default:
bool b = HaveNextFrameData();
status = b ? MediaDecoderOwner::NEXT_FRAME_AVAILABLE :
MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
statusString = b ? "NEXT_FRAME_AVAILABLE" : "NEXT_FRAME_UNAVAILABLE";
break;
if (aStatus != mNextFrameStatus) {
DECODER_LOG("Changed mNextFrameStatus to %s", ToStr(aStatus));
mNextFrameStatus = aStatus;
}
}
if (status != mNextFrameStatus) {
DECODER_LOG("Changed mNextFrameStatus to %s", statusString);
if(status == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING ||
status == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE) {
// Ensure currentTime is up to date prior updating mNextFrameStatus so that
// the MediaDecoderOwner fire events at correct currentTime.
UpdatePlaybackPositionPeriodically();
}
}
mNextFrameStatus = status;
void
MediaDecoderStateMachine::UpdateNextFrameStatus()
{
MOZ_ASSERT(OnTaskQueue());
UpdateNextFrameStatus(HaveNextFrameData()
? MediaDecoderOwner::NEXT_FRAME_AVAILABLE
: MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE);
}
bool
@ -3230,7 +3234,7 @@ MediaDecoderStateMachine::DumpDebugInfo()
GetMediaTime(), mMediaSink->IsStarted() ? GetClock() : -1, mMediaSink.get(),
ToStateStr(), mPlayState.Ref(), mSentFirstFrameLoadedEvent, IsPlaying(),
AudioRequestStatus(), VideoRequestStatus(), mDecodedAudioEndTime, mDecodedVideoEndTime,
mAudioCompleted.Ref(), mVideoCompleted.Ref());
mAudioCompleted, mVideoCompleted);
});
// Since the task is run asynchronously, it is possible other tasks get first

Просмотреть файл

@ -270,6 +270,7 @@ private:
class ShutdownState;
static const char* ToStateStr(State aState);
static const char* ToStr(NextFrameStatus aStatus);
const char* ToStateStr();
// Functions used by assertions to ensure we're calling things
@ -401,6 +402,7 @@ protected:
// Recomputes mNextFrameStatus, possibly dispatching notifications to interested
// parties.
void UpdateNextFrameStatus();
void UpdateNextFrameStatus(NextFrameStatus aStatus);
// Return the current time, either the audio clock if available (if the media
// has audio, and the playback is possible), or a clock for the video.
@ -560,9 +562,7 @@ private:
// the decoder, state machine, and main threads.
MediaQueue<MediaData> mVideoQueue;
// The decoder monitor must be obtained before modifying this state.
// Accessed on state machine, audio, main, and AV thread.
Watchable<State> mState;
State mState = DECODER_STATE_DECODING_METADATA;
UniquePtr<StateObject> mStateObj;
@ -679,17 +679,11 @@ private:
// it has stopped.
bool mAudioCaptured;
// True if the audio playback thread has finished. It is finished
// when either all the audio frames have completed playing, or we've moved
// into shutdown state, and the threads are to be
// destroyed. Written by the audio playback thread and read and written by
// the state machine thread. Synchronised via decoder monitor.
// When data is being sent to a MediaStream, this is true when all data has
// been written to the MediaStream.
Watchable<bool> mAudioCompleted;
// True if all audio frames are already rendered.
bool mAudioCompleted = false;
// True if all video frames are already rendered.
Watchable<bool> mVideoCompleted;
bool mVideoCompleted = false;
// Flag whether we notify metadata before decoding the first frame or after.
//

Просмотреть файл

@ -2300,7 +2300,8 @@ if (privileged) {
bool fake = c.mFake.WasPassed()? c.mFake.Value() :
Preferences::GetBool("media.navigator.streams.fake");
bool askPermission = !privileged &&
bool askPermission =
(!privileged || Preferences::GetBool("media.navigator.permission.force")) &&
(!fake || Preferences::GetBool("media.navigator.permission.fake"));
RefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowID, videoType,

Просмотреть файл

@ -152,7 +152,6 @@ private:
// Ogg
DECL_MEDIA_PREF("media.ogg.enabled", OggEnabled, bool, true);
DECL_MEDIA_PREF("media.format-reader.ogg", OggFormatReader, bool, true);
// Flac
DECL_MEDIA_PREF("media.ogg.flac.enabled", FlacInOgg, bool, false);
DECL_MEDIA_PREF("media.flac.enabled", FlacEnabled, bool, true);

Просмотреть файл

@ -8,6 +8,7 @@
#include "mp4_demuxer/ByteReader.h"
#include "nsTArray.h"
#include "OggCodecState.h"
#include "OpusParser.h"
#include "VideoUtils.h"
using mp4_demuxer::ByteReader;
@ -43,6 +44,10 @@ FlacFrameParser::FlacFrameParser()
{
}
FlacFrameParser::~FlacFrameParser()
{
}
uint32_t
FlacFrameParser::HeaderBlockLength(const uint8_t* aPacket) const
{

Просмотреть файл

@ -26,6 +26,7 @@ class FlacFrameParser
{
public:
FlacFrameParser();
~FlacFrameParser();
bool IsHeaderBlock(const uint8_t* aPacket, size_t aLength) const;
// Return the length of the block header (METADATA_BLOCK_HEADER+
@ -56,7 +57,6 @@ private:
// Used to decode the vorbis comment metadata.
nsAutoPtr<OpusParser> mParser;
};
}

Просмотреть файл

@ -6,18 +6,18 @@
#include <string.h>
#include "mozilla/DebugOnly.h"
#include "mozilla/EndianUtils.h"
#include <stdint.h>
#include "nsDebug.h"
#include "MediaDecoderReader.h"
#include "OggCodecState.h"
#include "OggDecoder.h"
#include "nsISupportsImpl.h"
#include "OpusParser.h"
#include "VideoUtils.h"
#include <algorithm>
#include <opus/opus.h>
#include "opus/opus_multistream.h"
// On Android JellyBean, the hardware.h header redefines version_major and
// version_minor, which breaks our build. See:
// https://bugzilla.mozilla.org/show_bug.cgi?id=912702#c6

Просмотреть файл

@ -7,18 +7,7 @@
#define OggCodecState_h_
#include <ogg/ogg.h>
#include <theora/theoradec.h>
#ifdef MOZ_TREMOR
#include <tremor/ivorbiscodec.h>
#else
#include <vorbis/codec.h>
#endif
#include <opus/opus.h>
#include "opus/opus_multistream.h"
// For MOZ_SAMPLE_TYPE_*
#include "mozilla/dom/HTMLMediaElement.h"
#include "MediaDecoderStateMachine.h"
#include "MediaDecoderReader.h"
#include <nsAutoPtr.h>
#include <nsAutoRef.h>
#include <nsDeque.h>
@ -27,7 +16,12 @@
#include "VideoUtils.h"
#include "FlacFrameParser.h"
#include <stdint.h>
#include <theora/theoradec.h>
#ifdef MOZ_TREMOR
#include <tremor/ivorbiscodec.h>
#else
#include <vorbis/codec.h>
#endif
// Uncomment the following to validate that we're predicting the number
// of Vorbis samples in each packet correctly.
@ -36,10 +30,12 @@
#include <map>
#endif
#include "OpusParser.h"
struct OpusMSDecoder;
namespace mozilla {
class OpusParser;
// Deallocates a packet, used in OggPacketQueue below.
class OggPacketDeallocator : public nsDequeFunctor
{
@ -94,11 +90,11 @@ public:
};
virtual ~OggCodecState();
// Factory for creating nsCodecStates. Use instead of constructor.
// aPage should be a beginning-of-stream page.
static OggCodecState* Create(ogg_page* aPage);
virtual CodecType GetType() { return TYPE_UNKNOWN; }
// Reads a header packet. Returns false if an error was encountered
@ -209,7 +205,7 @@ public:
// captured.
virtual nsresult PageIn(ogg_page* aPage);
// Number of packets read.
// Number of packets read.
uint64_t mPacketCount;
// Serial number of the bitstream.
@ -224,7 +220,7 @@ public:
// Is the bitstream active; whether we're decoding and playing this bitstream.
bool mActive;
// True when all headers packets have been read.
bool mDoneReadingHeaders;
@ -360,7 +356,7 @@ public:
int64_t MaxKeyframeOffset();
// Returns the end time that a granulepos represents.
static int64_t Time(th_info* aInfo, int64_t aGranulePos);
static int64_t Time(th_info* aInfo, int64_t aGranulePos);
th_info mInfo;
th_comment mComment;
@ -566,7 +562,7 @@ private:
{
public:
nsKeyFrameIndex(int64_t aStartTime, int64_t aEndTime)
nsKeyFrameIndex(int64_t aStartTime, int64_t aEndTime)
: mStartTime(aStartTime)
, mEndTime(aEndTime)
{

Просмотреть файл

@ -8,7 +8,6 @@
#include "MediaDecoderStateMachine.h"
#include "MediaFormatReader.h"
#include "OggDemuxer.h"
#include "OggReader.h"
#include "OggDecoder.h"
#include "nsContentTypeParser.h"
@ -16,16 +15,11 @@ namespace mozilla {
MediaDecoderStateMachine* OggDecoder::CreateStateMachine()
{
bool useFormatDecoder = MediaPrefs::OggFormatReader();
RefPtr<OggDemuxer> demuxer =
useFormatDecoder ? new OggDemuxer(GetResource()) : nullptr;
RefPtr<MediaDecoderReader> reader = useFormatDecoder
? static_cast<MediaDecoderReader*>(new MediaFormatReader(this, demuxer, GetVideoFrameContainer()))
: new OggReader(this);
if (useFormatDecoder) {
demuxer->SetChainingEvents(&reader->TimedMetadataProducer(),
&reader->MediaNotSeekableProducer());
}
RefPtr<OggDemuxer> demuxer = new OggDemuxer(GetResource());
RefPtr<MediaFormatReader> reader =
new MediaFormatReader(this, demuxer, GetVideoFrameContainer());
demuxer->SetChainingEvents(&reader->TimedMetadataProducer(),
&reader->MediaNotSeekableProducer());
return new MediaDecoderStateMachine(this, reader);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,306 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#if !defined(OggReader_h_)
#define OggReader_h_
#include <ogg/ogg.h>
#include <theora/theoradec.h>
#ifdef MOZ_TREMOR
#include <tremor/ivorbiscodec.h>
#else
#include <vorbis/codec.h>
#endif
#include "MediaDecoderReader.h"
#include "MediaResource.h"
#include "OggCodecState.h"
#include "VideoUtils.h"
#include "mozilla/Monitor.h"
#include "OggDecoder.h"
#include "OggCodecStore.h"
namespace mozilla {
class OggReader final : public MediaDecoderReader
{
public:
explicit OggReader(AbstractMediaDecoder* aDecoder);
protected:
~OggReader();
public:
nsresult Init() override;
nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
TrackInfo::kVideoTrack)) override;
bool DecodeAudioData() override;
// If the Theora granulepos has not been captured, it may read several packets
// until one with a granulepos has been captured, to ensure that all packets
// read have valid time info.
bool DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) override;
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
RefPtr<SeekPromise> Seek(SeekTarget aTarget, int64_t aEndTime) override;
media::TimeIntervals GetBuffered() override;
private:
bool HasAudio() {
return (mVorbisState != 0 && mVorbisState->mActive) ||
(mOpusState != 0 && mOpusState->mActive);
}
bool HasVideo() {
return mTheoraState != 0 && mTheoraState->mActive;
}
// TODO: DEPRECATED. This uses synchronous decoding.
// Stores the presentation time of the first frame we'd be able to play if
// we started playback at the current position. Returns the first video
// frame, if we have video.
void FindStartTime(int64_t& aOutStartTime);
RefPtr<AudioData> SyncDecodeToFirstAudioData();
RefPtr<VideoData> SyncDecodeToFirstVideoData();
// This monitor should be taken when reading or writing to mIsChained.
ReentrantMonitor mMonitor;
// Specialized Reset() method to signal if the seek is
// to the start of the stream.
nsresult ResetDecode(bool start,
TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
TrackInfo::kVideoTrack));
nsresult SeekInternal(int64_t aTime, int64_t aEndTime);
bool HasSkeleton() {
return mSkeletonState != 0 && mSkeletonState->mActive;
}
// Seeks to the keyframe preceding the target time using available
// keyframe indexes.
enum IndexedSeekResult {
SEEK_OK, // Success.
SEEK_INDEX_FAIL, // Failure due to no index, or invalid index.
SEEK_FATAL_ERROR // Error returned by a stream operation.
};
IndexedSeekResult SeekToKeyframeUsingIndex(int64_t aTarget);
// Rolls back a seek-using-index attempt, returning a failure error code.
IndexedSeekResult RollbackIndexedSeek(int64_t aOffset);
// Represents a section of contiguous media, with a start and end offset,
// and the timestamps of the start and end of that range, that is cached.
// Used to denote the extremities of a range in which we can seek quickly
// (because it's cached).
class SeekRange {
public:
SeekRange()
: mOffsetStart(0),
mOffsetEnd(0),
mTimeStart(0),
mTimeEnd(0)
{}
SeekRange(int64_t aOffsetStart,
int64_t aOffsetEnd,
int64_t aTimeStart,
int64_t aTimeEnd)
: mOffsetStart(aOffsetStart),
mOffsetEnd(aOffsetEnd),
mTimeStart(aTimeStart),
mTimeEnd(aTimeEnd)
{}
bool IsNull() const {
return mOffsetStart == 0 &&
mOffsetEnd == 0 &&
mTimeStart == 0 &&
mTimeEnd == 0;
}
int64_t mOffsetStart, mOffsetEnd; // in bytes.
int64_t mTimeStart, mTimeEnd; // in usecs.
};
// Seeks to aTarget usecs in the buffered range aRange using bisection search,
// or to the keyframe prior to aTarget if we have video. aAdjustedTarget is
// an adjusted version of the target used to account for Opus pre-roll, if
// necessary. aStartTime must be the presentation time at the start of media,
// and aEndTime the time at end of media. aRanges must be the time/byte ranges
// buffered in the media cache as per GetSeekRanges().
nsresult SeekInBufferedRange(int64_t aTarget,
int64_t aAdjustedTarget,
int64_t aStartTime,
int64_t aEndTime,
const nsTArray<SeekRange>& aRanges,
const SeekRange& aRange);
// Seeks to before aTarget usecs in media using bisection search. If the media
// has video, this will seek to before the keyframe required to render the
// media at aTarget. Will use aRanges in order to narrow the bisection
// search space. aStartTime must be the presentation time at the start of
// media, and aEndTime the time at end of media. aRanges must be the time/byte
// ranges buffered in the media cache as per GetSeekRanges().
nsresult SeekInUnbuffered(int64_t aTarget,
int64_t aStartTime,
int64_t aEndTime,
const nsTArray<SeekRange>& aRanges);
// Get the end time of aEndOffset. This is the playback position we'd reach
// after playback finished at aEndOffset.
int64_t RangeEndTime(int64_t aEndOffset);
// Get the end time of aEndOffset, without reading before aStartOffset.
// This is the playback position we'd reach after playback finished at
// aEndOffset. If bool aCachedDataOnly is true, then we'll only read
// from data which is cached in the media cached, otherwise we'll do
// regular blocking reads from the media stream. If bool aCachedDataOnly
// is true, this can safely be called on the main thread, otherwise it
// must be called on the state machine thread.
int64_t RangeEndTime(int64_t aStartOffset,
int64_t aEndOffset,
bool aCachedDataOnly);
// Get the start time of the range beginning at aOffset. This is the start
// time of the first frame and or audio sample we'd be able to play if we
// started playback at aOffset.
int64_t RangeStartTime(int64_t aOffset);
// Performs a seek bisection to move the media stream's read cursor to the
// last ogg page boundary which has end time before aTarget usecs on both the
// Theora and Vorbis bitstreams. Limits its search to data inside aRange;
// i.e. it will only read inside of the aRange's start and end offsets.
// aFuzz is the number of usecs of leniency we'll allow; we'll terminate the
// seek when we land in the range (aTime - aFuzz, aTime) usecs.
nsresult SeekBisection(int64_t aTarget,
const SeekRange& aRange,
uint32_t aFuzz);
// Returns true if the serial number is for a stream we encountered
// while reading metadata. Call on the main thread only.
bool IsKnownStream(uint32_t aSerial);
// Fills aRanges with SeekRanges denoting the sections of the media which
// have been downloaded and are stored in the media cache. The reader
// monitor must must be held with exactly one lock count. The MediaResource
// must be pinned while calling this.
nsresult GetSeekRanges(nsTArray<SeekRange>& aRanges);
// Returns the range in which you should perform a seek bisection if
// you wish to seek to aTarget usecs, given the known (buffered) byte ranges
// in aRanges. If aExact is true, we only return an exact copy of a
// range in which aTarget lies, or a null range if aTarget isn't contained
// in any of the (buffered) ranges. Otherwise, when aExact is false,
// we'll construct the smallest possible range we can, based on the times
// and byte offsets known in aRanges. We can then use this to minimize our
// bisection's search space when the target isn't in a known buffered range.
SeekRange SelectSeekRange(const nsTArray<SeekRange>& aRanges,
int64_t aTarget,
int64_t aStartTime,
int64_t aEndTime,
bool aExact);
private:
// Decodes a packet of Vorbis data, and inserts its samples into the
// audio queue.
nsresult DecodeVorbis(ogg_packet* aPacket);
// Decodes a packet of Opus data, and inserts its samples into the
// audio queue.
nsresult DecodeOpus(ogg_packet* aPacket);
// Decodes a packet of Theora data, and inserts its frame into the
// video queue. May return NS_ERROR_OUT_OF_MEMORY. Caller must have obtained
// the reader's monitor. aTimeThreshold is the current playback position
// in media time in microseconds. Frames with an end time before this will
// not be enqueued.
nsresult DecodeTheora(ogg_packet* aPacket, int64_t aTimeThreshold);
// Read a page of data from the Ogg file. Returns true if a page has been
// read, false if the page read failed or end of file reached.
bool ReadOggPage(ogg_page* aPage);
// Reads and decodes header packets for aState, until either header decode
// fails, or is complete. Initializes the codec state before returning.
// Returns true if reading headers and initializtion of the stream
// succeeds.
bool ReadHeaders(OggCodecState* aState);
// Reads the next link in the chain.
bool ReadOggChain();
// Set this media as being a chain and notifies the state machine that the
// media is no longer seekable.
void SetChained();
// Returns the next Ogg packet for an bitstream/codec state. Returns a
// pointer to an ogg_packet on success, or nullptr if the read failed.
// The caller is responsible for deleting the packet and its |packet| field.
ogg_packet* NextOggPacket(OggCodecState* aCodecState);
// Fills aTracks with the serial numbers of each active stream, for use by
// various SkeletonState functions.
void BuildSerialList(nsTArray<uint32_t>& aTracks);
// Setup target bitstreams for decoding.
void SetupTargetTheora(TheoraState* aTheoraState);
void SetupTargetVorbis(VorbisState* aVorbisState);
void SetupTargetOpus(OpusState* aOpusState);
void SetupTargetSkeleton(SkeletonState* aSkeletonState);
void SetupMediaTracksInfo(const nsTArray<uint32_t>& aSerials);
OggCodecStore mCodecStore;
// Decode state of the Theora bitstream we're decoding, if we have video.
TheoraState* mTheoraState;
// Decode state of the Vorbis bitstream we're decoding, if we have audio.
VorbisState* mVorbisState;
// Decode state of the Opus bitstream we're decoding, if we have one.
OpusState *mOpusState;
// Represents the user pref media.opus.enabled at the time our
// contructor was called. We can't check it dynamically because
// we're not on the main thread;
bool mOpusEnabled;
// Decode state of the Skeleton bitstream.
SkeletonState* mSkeletonState;
// Ogg decoding state.
ogg_sync_state mOggState;
// Vorbis/Opus/Theora data used to compute timestamps. This is written on the
// decoder thread and read on the main thread. All reading on the main
// thread must be done after metadataloaded. We can't use the existing
// data in the codec states due to threading issues. You must check the
// associated mTheoraState or mVorbisState pointer is non-null before
// using this codec data.
uint32_t mVorbisSerial;
uint32_t mOpusSerial;
uint32_t mTheoraSerial;
vorbis_info mVorbisInfo;
int mOpusPreSkip;
th_info mTheoraInfo;
// The picture region inside Theora frame to be displayed, if we have
// a Theora video track.
nsIntRect mPicture;
// True if we are decoding a chained ogg. Reading or writing to this member
// should be done with |mMonitor| acquired.
bool mIsChained;
// Number of audio frames decoded so far.
int64_t mDecodedAudioFrames;
MediaResourceIndex mResource;
};
} // namespace mozilla
#endif

Просмотреть файл

@ -4,18 +4,11 @@
* 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/. */
#include <string.h>
#include "mozilla/DebugOnly.h"
#include <algorithm>
#include "mozilla/EndianUtils.h"
#include <stdint.h>
#include "OpusParser.h"
#include "nsDebug.h"
#include "MediaDecoderReader.h"
#include "VideoUtils.h"
#include <algorithm>
#include "opus/opus.h"
extern "C" {

Просмотреть файл

@ -6,11 +6,6 @@
#if !defined(OpusParser_h_)
#define OpusParser_h_
#include <stdint.h>
#include <opus/opus.h>
#include "opus/opus_multistream.h"
#include "nsTArray.h"
#include "nsString.h"
@ -46,7 +41,6 @@ public:
nsTArray<nsCString> mTags; // Unparsed comment strings from the header.
nsCString mVendorString; // Encoder vendor string from the header.
};
} // namespace mozilla

Просмотреть файл

@ -9,7 +9,6 @@ EXPORTS += [
'OggCodecStore.h',
'OggDecoder.h',
'OggDemuxer.h',
'OggReader.h',
'OggWriter.h',
'OpusParser.h',
]
@ -19,7 +18,6 @@ UNIFIED_SOURCES += [
'OggCodecStore.cpp',
'OggDecoder.cpp',
'OggDemuxer.cpp',
'OggReader.cpp',
'OggWriter.cpp',
'OpusParser.cpp',
]

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OpusDecoder.h"
#include "OpusParser.h"
#include "TimeUnits.h"
#include "VorbisUtils.h"
#include "VorbisDecoder.h" // For VorbisLayout
@ -12,9 +13,13 @@
#include "mozilla/PodOperations.h"
#include "mozilla/SyncRunnable.h"
#include <stdint.h>
#include <inttypes.h> // For PRId64
#include "opus/opus.h"
extern "C" {
#include "opus/opus_multistream.h"
}
#define OPUS_DEBUG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \
("OpusDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))

Просмотреть файл

@ -6,14 +6,17 @@
#if !defined(OpusDecoder_h_)
#define OpusDecoder_h_
#include "OpusParser.h"
#include "PlatformDecoderModule.h"
#include "mozilla/Maybe.h"
#include "nsAutoPtr.h"
struct OpusMSDecoder;
namespace mozilla {
class OpusParser;
class OpusDataDecoder : public MediaDataDecoder
{
public:

Просмотреть файл

@ -73,6 +73,8 @@ skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulato
[test_getUserMedia_playAudioTwice.html]
[test_getUserMedia_playVideoAudioTwice.html]
[test_getUserMedia_playVideoTwice.html]
[test_getUserMedia_scarySources.html]
skip-if = toolkit == 'android' # no screenshare or windowshare on android
[test_getUserMedia_spinEventLoop.html]
[test_getUserMedia_stopAudioStream.html]
[test_getUserMedia_stopAudioStreamWithFollowupAudio.html]

Просмотреть файл

@ -0,0 +1,66 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({title: "Detect screensharing sources that are firefox", bug: "1311048"});
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm');
let observe = topic => new Promise(r => Services.obs.addObserver(function o(...args) {
Services.obs.removeObserver(o, topic);
r(args);
}, topic, false));
let getDevices = async constraints => {
let [{ windowID, innerWindowID, callID }] = await Promise.race([
getUserMedia(constraints),
observe("getUserMedia:request")
]);
let window = Services.wm.getOuterWindowWithId(windowID);
let devices = await new Promise((resolve, reject) =>
window.navigator.mozGetUserMediaDevices({}, resolve, reject,
innerWindowID, callID));
return devices.map(d => d.QueryInterface(Ci.nsIMediaDevice));
};
runTest(async () => {
try {
const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
if (IsMacOSX10_6orOlder() || isWinXP) {
ok(true, "Screensharing disabled for OSX10.6 and WinXP");
return;
}
await pushPrefs(["media.navigator.permission.disabled", true],
["media.navigator.permission.fake", true],
["media.navigator.permission.force", true]);
let devices = await getDevices({video: { mediaSource: "window" }});
ok(devices.length, "Found one or more windows.");
devices = devices.filter(d => d.scary);
ok(devices.length, "Found one or more scary windows (our own counts).");
devices.filter(d => d.name.includes("MochiTest"));
ok(devices.length,
"Our own window is among the scary: " + devices.map(d => `"${d.name}"`));
devices = await getDevices({video: { mediaSource: "screen" }});
let numScreens = devices.length;
ok(numScreens, "Found one or more screens.");
devices = devices.filter(d => d.scary);
is(devices.length, numScreens, "All screens are scary.");
} catch(e) {
ok(false, e);
}
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -5,9 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WaveDemuxer.h"
#include "mozilla/Preferences.h"
#include "MediaDecoderStateMachine.h"
#include "WaveReader.h"
#include "WaveDecoder.h"
#include "MediaFormatReader.h"
#include "PDMFactory.h"
@ -23,39 +21,22 @@ WaveDecoder::Clone(MediaDecoderOwner* aOwner)
MediaDecoderStateMachine*
WaveDecoder::CreateStateMachine()
{
if (Preferences::GetBool("media.wave.decoder.enabled", false)) {
RefPtr<MediaDecoderReader> reader =
new MediaFormatReader(this, new WAVDemuxer(GetResource()));
return new MediaDecoderStateMachine(this, reader);
} else {
return new MediaDecoderStateMachine(this, new WaveReader(this));
}
}
/* static */
bool
WaveDecoder::IsEnabled()
{
MOZ_ASSERT(NS_IsMainThread());
if (!Preferences::GetBool("media.wave.decoder.enabled", false)) {
return false;
}
RefPtr<PDMFactory> platform = new PDMFactory();
return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/x-wav"),
/* DecoderDoctorDiagnostics* */ nullptr);
return new MediaDecoderStateMachine(
this, new MediaFormatReader(this, new WAVDemuxer(GetResource())));
}
/* static */
bool
WaveDecoder::CanHandleMediaType(const nsACString& aType,
const nsAString& aCodecs)
const nsAString& aCodecs)
{
if (!IsWaveEnabled()) {
return false;
}
if (aType.EqualsASCII("audio/wave") || aType.EqualsASCII("audio/x-wav") ||
aType.EqualsASCII("audio/wav") || aType.EqualsASCII("audio/x-pn-wav")) {
return IsEnabled() && (aCodecs.IsEmpty() ||
aCodecs.EqualsASCII("1") ||
aCodecs.EqualsASCII("6") ||
aCodecs.EqualsASCII("7"));
return (aCodecs.IsEmpty() || aCodecs.EqualsASCII("1") ||
aCodecs.EqualsASCII("6") || aCodecs.EqualsASCII("7"));
}
return false;

Просмотреть файл

@ -17,9 +17,6 @@ public:
MediaDecoder* Clone(MediaDecoderOwner* aOwner) override;
MediaDecoderStateMachine* CreateStateMachine() override;
// Returns true if the WAV backend is pref'ed on, and we're running on a
// platform that is likely to have decoders for the format.
static bool IsEnabled();
static bool CanHandleMediaType(const nsACString& aType,
const nsAString& aCodecs);
};

Просмотреть файл

@ -1,689 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "nsError.h"
#include "AbstractMediaDecoder.h"
#include "WaveReader.h"
#include "MediaDecoderStateMachine.h"
#include "VideoUtils.h"
#include "nsISeekableStream.h"
#include <stdint.h>
#include "mozilla/ArrayUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/EndianUtils.h"
#include "mozilla/UniquePtr.h"
#include <algorithm>
using namespace mozilla::media;
namespace mozilla {
// Un-comment to enable logging of seek bisections.
//#define SEEK_LOGGING
extern LazyLogModule gMediaDecoderLog;
#define LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
#ifdef SEEK_LOGGING
#define SEEK_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
#else
#define SEEK_LOG(type, msg)
#endif
struct waveIdToName {
uint32_t id;
nsCString name;
};
// Magic values that identify RIFF chunks we're interested in.
static const uint32_t RIFF_CHUNK_MAGIC = 0x52494646;
static const uint32_t WAVE_CHUNK_MAGIC = 0x57415645;
static const uint32_t FRMT_CHUNK_MAGIC = 0x666d7420;
static const uint32_t DATA_CHUNK_MAGIC = 0x64617461;
static const uint32_t LIST_CHUNK_MAGIC = 0x4c495354;
// Size of chunk header. 4 byte chunk header type and 4 byte size field.
static const uint16_t CHUNK_HEADER_SIZE = 8;
// Size of RIFF header. RIFF chunk and 4 byte RIFF type.
static const uint16_t RIFF_INITIAL_SIZE = CHUNK_HEADER_SIZE + 4;
// Size of required part of format chunk. Actual format chunks may be
// extended (for non-PCM encodings), but we skip any extended data.
static const uint16_t WAVE_FORMAT_CHUNK_SIZE = 16;
// PCM encoding type from format chunk. Linear PCM is the only encoding
// supported by AudioStream.
static const uint16_t WAVE_FORMAT_ENCODING_PCM = 1;
// We reject files with more than this number of channels if we're decoding for
// playback.
static const uint8_t MAX_CHANNELS = 2;
namespace {
uint32_t
ReadUint32BE(const char** aBuffer)
{
uint32_t result = BigEndian::readUint32(*aBuffer);
*aBuffer += sizeof(uint32_t);
return result;
}
uint32_t
ReadUint32LE(const char** aBuffer)
{
uint32_t result = LittleEndian::readUint32(*aBuffer);
*aBuffer += sizeof(uint32_t);
return result;
}
int32_t
ReadInt24LE(const char** aBuffer)
{
int32_t result = int32_t((uint8_t((*aBuffer)[2]) << 16) |
(uint8_t((*aBuffer)[1]) << 8 ) |
(uint8_t((*aBuffer)[0])));
if (((*aBuffer)[2] & 0x80) == 0x80) {
result = (result | 0xff000000);
}
*aBuffer += 3 * sizeof(char);
return result;
}
uint16_t
ReadUint16LE(const char** aBuffer)
{
uint16_t result = LittleEndian::readUint16(*aBuffer);
*aBuffer += sizeof(uint16_t);
return result;
}
int16_t
ReadInt16LE(const char** aBuffer)
{
uint16_t result = LittleEndian::readInt16(*aBuffer);
*aBuffer += sizeof(int16_t);
return result;
}
uint8_t
ReadUint8(const char** aBuffer)
{
uint8_t result = uint8_t((*aBuffer)[0]);
*aBuffer += sizeof(uint8_t);
return result;
}
} // namespace
WaveReader::WaveReader(AbstractMediaDecoder* aDecoder)
: MediaDecoderReader(aDecoder)
, mResource(aDecoder->GetResource())
{
MOZ_COUNT_CTOR(WaveReader);
}
WaveReader::~WaveReader()
{
MOZ_COUNT_DTOR(WaveReader);
}
nsresult WaveReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());
bool loaded = LoadRIFFChunk();
if (!loaded) {
return NS_ERROR_FAILURE;
}
nsAutoPtr<dom::HTMLMediaElement::MetadataTags> tags;
bool loadAllChunks = LoadAllChunks(tags);
if (!loadAllChunks) {
return NS_ERROR_FAILURE;
}
mInfo.mAudio.mRate = mSampleRate;
mInfo.mAudio.mChannels = mChannels;
mInfo.mMetadataDuration.emplace(TimeUnit::FromSeconds(BytesToTime(GetDataLength())));
*aInfo = mInfo;
*aTags = tags.forget();
return NS_OK;
}
template <typename T> T UnsignedByteToAudioSample(uint8_t aValue);
template <typename T> T SignedShortToAudioSample(int16_t aValue);
template <typename T> T Signed24bIntToAudioSample(int32_t aValue);
template <> inline float
UnsignedByteToAudioSample<float>(uint8_t aValue)
{
return aValue * (2.0f / UINT8_MAX) - 1.0f;
}
template <> inline int16_t
UnsignedByteToAudioSample<int16_t>(uint8_t aValue)
{
return int16_t(aValue * UINT16_MAX / UINT8_MAX + INT16_MIN);
}
template <> inline float
SignedShortToAudioSample<float>(int16_t aValue)
{
return AudioSampleToFloat(aValue);
}
template <> inline int16_t
SignedShortToAudioSample<int16_t>(int16_t aValue)
{
return aValue;
}
template <> inline float
Signed24bIntToAudioSample<float>(int32_t aValue)
{
return aValue / 8388608.0f;
}
template <> inline int16_t
Signed24bIntToAudioSample<int16_t>(int32_t aValue)
{
return aValue / 256;
}
bool WaveReader::DecodeAudioData()
{
MOZ_ASSERT(OnTaskQueue());
int64_t pos = GetPosition() - mWavePCMOffset;
int64_t len = GetDataLength();
int64_t remaining = len - pos;
NS_ASSERTION(remaining >= 0, "Current wave position is greater than wave file length");
static const int64_t BLOCK_SIZE = 6144;
int64_t readSize = std::min(BLOCK_SIZE, remaining);
int64_t frames = readSize / mFrameSize;
MOZ_ASSERT(BLOCK_SIZE % 3 == 0);
MOZ_ASSERT(BLOCK_SIZE % 2 == 0);
static_assert(uint64_t(BLOCK_SIZE) < UINT_MAX /
sizeof(AudioDataValue) / MAX_CHANNELS,
"bufferSize calculation could overflow.");
const size_t bufferSize = static_cast<size_t>(frames * mChannels);
AlignedAudioBuffer sampleBuffer(bufferSize);
if (!sampleBuffer) {
return false;
}
static_assert(uint64_t(BLOCK_SIZE) < UINT_MAX / sizeof(char),
"BLOCK_SIZE too large for enumerator.");
auto dataBuffer = MakeUnique<char[]>(static_cast<size_t>(readSize));
if (!ReadAll(dataBuffer.get(), readSize)) {
return false;
}
// convert data to samples
const char* d = dataBuffer.get();
AudioDataValue* s = sampleBuffer.get();
for (int i = 0; i < frames; ++i) {
for (unsigned int j = 0; j < mChannels; ++j) {
if (mSampleFormat == FORMAT_U8) {
uint8_t v = ReadUint8(&d);
*s++ = UnsignedByteToAudioSample<AudioDataValue>(v);
} else if (mSampleFormat == FORMAT_S16) {
int16_t v = ReadInt16LE(&d);
*s++ = SignedShortToAudioSample<AudioDataValue>(v);
} else if (mSampleFormat == FORMAT_S24) {
int32_t v = ReadInt24LE(&d);
*s++ = Signed24bIntToAudioSample<AudioDataValue>(v);
}
}
}
double posTime = BytesToTime(pos);
double readSizeTime = BytesToTime(readSize);
NS_ASSERTION(posTime <= INT64_MAX / USECS_PER_S, "posTime overflow");
NS_ASSERTION(readSizeTime <= INT64_MAX / USECS_PER_S, "readSizeTime overflow");
NS_ASSERTION(frames < INT32_MAX, "frames overflow");
mAudioQueue.Push(new AudioData(pos,
static_cast<int64_t>(posTime * USECS_PER_S),
static_cast<int64_t>(readSizeTime * USECS_PER_S),
static_cast<int32_t>(frames),
Move(sampleBuffer),
mChannels,
mSampleRate));
return true;
}
bool WaveReader::DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold)
{
MOZ_ASSERT(OnTaskQueue());
return false;
}
RefPtr<MediaDecoderReader::SeekPromise>
WaveReader::Seek(SeekTarget aTarget, int64_t aEndTime)
{
MOZ_ASSERT(OnTaskQueue());
LOG(LogLevel::Debug, ("%p About to seek to %lld", mDecoder, aTarget.GetTime().ToMicroseconds()));
if (NS_FAILED(ResetDecode())) {
return SeekPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
double d = BytesToTime(GetDataLength());
NS_ASSERTION(d < INT64_MAX / USECS_PER_S, "Duration overflow");
media::TimeUnit duration = media::TimeUnit::FromSeconds(d);
double seekTime = std::min(aTarget.GetTime(), duration).ToSeconds();
int64_t position = RoundDownToFrame(static_cast<int64_t>(TimeToBytes(seekTime)));
NS_ASSERTION(INT64_MAX - mWavePCMOffset > position, "Integer overflow during wave seek");
position += mWavePCMOffset;
nsresult res = mResource.Seek(nsISeekableStream::NS_SEEK_SET, position);
if (NS_FAILED(res)) {
return SeekPromise::CreateAndReject(res, __func__);
} else {
return SeekPromise::CreateAndResolve(aTarget.GetTime(), __func__);
}
}
media::TimeIntervals WaveReader::GetBuffered()
{
MOZ_ASSERT(OnTaskQueue());
if (!mInfo.HasAudio()) {
return media::TimeIntervals();
}
media::TimeIntervals buffered;
AutoPinned<MediaResource> resource(mDecoder->GetResource());
int64_t startOffset = resource->GetNextCachedData(mWavePCMOffset);
while (startOffset >= 0) {
int64_t endOffset = resource->GetCachedDataEnd(startOffset);
// Bytes [startOffset..endOffset] are cached.
NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
// We need to round the buffered ranges' times to microseconds so that they
// have the same precision as the currentTime and duration attribute on
// the media element.
buffered += media::TimeInterval(
media::TimeUnit::FromSeconds(BytesToTime(startOffset - mWavePCMOffset)),
media::TimeUnit::FromSeconds(BytesToTime(endOffset - mWavePCMOffset)));
startOffset = resource->GetNextCachedData(endOffset);
}
return buffered;
}
bool
WaveReader::ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead)
{
MOZ_ASSERT(OnTaskQueue());
if (aBytesRead) {
*aBytesRead = 0;
}
uint32_t read = 0;
if (NS_FAILED(mResource.Read(aBuf, uint32_t(aSize), &read))) {
NS_WARNING("Resource read failed");
return false;
}
if (!read) {
return false;
}
if (aBytesRead) {
*aBytesRead = read;
}
return true;
}
bool
WaveReader::LoadRIFFChunk()
{
MOZ_ASSERT(OnTaskQueue());
char riffHeader[RIFF_INITIAL_SIZE];
const char* p = riffHeader;
MOZ_ASSERT(mResource.Tell() == 0,
"LoadRIFFChunk called when resource in invalid state");
if (!ReadAll(riffHeader, sizeof(riffHeader))) {
return false;
}
static_assert(sizeof(uint32_t) * 3 <= RIFF_INITIAL_SIZE,
"Reads would overflow riffHeader buffer.");
if (ReadUint32BE(&p) != RIFF_CHUNK_MAGIC) {
NS_WARNING("resource data not in RIFF format");
return false;
}
// Skip over RIFF size field.
p += sizeof(uint32_t);
if (ReadUint32BE(&p) != WAVE_CHUNK_MAGIC) {
NS_WARNING("Expected WAVE chunk");
return false;
}
return true;
}
bool
WaveReader::LoadFormatChunk(uint32_t aChunkSize)
{
MOZ_ASSERT(OnTaskQueue());
uint32_t rate, channels, frameSize, sampleFormat;
char waveFormat[WAVE_FORMAT_CHUNK_SIZE];
const char* p = waveFormat;
// RIFF chunks are always word (two byte) aligned.
MOZ_ASSERT(mResource.Tell() % 2 == 0,
"LoadFormatChunk called with unaligned resource");
if (!ReadAll(waveFormat, sizeof(waveFormat))) {
return false;
}
static_assert(sizeof(uint16_t) +
sizeof(uint16_t) +
sizeof(uint32_t) +
4 +
sizeof(uint16_t) +
sizeof(uint16_t) <= sizeof(waveFormat),
"Reads would overflow waveFormat buffer.");
if (ReadUint16LE(&p) != WAVE_FORMAT_ENCODING_PCM) {
NS_WARNING("WAVE is not uncompressed PCM, compressed encodings are not supported");
return false;
}
channels = ReadUint16LE(&p);
rate = ReadUint32LE(&p);
// Skip over average bytes per second field.
p += 4;
frameSize = ReadUint16LE(&p);
sampleFormat = ReadUint16LE(&p);
// PCM encoded WAVEs are not expected to have an extended "format" chunk,
// but I have found WAVEs that have a extended "format" chunk with an
// extension size of 0 bytes. Be polite and handle this rather than
// considering the file invalid. This code skips any extension of the
// "format" chunk.
if (aChunkSize > WAVE_FORMAT_CHUNK_SIZE) {
uint16_t extra = aChunkSize - WAVE_FORMAT_CHUNK_SIZE;
extra += extra % 2;
if (NS_FAILED(mResource.Seek(nsISeekableStream::NS_SEEK_CUR, extra))) {
return false;
}
}
// RIFF chunks are always word (two byte) aligned.
MOZ_ASSERT(mResource.Tell() % 2 == 0,
"LoadFormatChunk left resource unaligned");
// Make sure metadata is fairly sane. The rate check is fairly arbitrary,
// but the channels check is intentionally limited to mono or stereo
// when the media is intended for direct playback because that's what the
// audio backend currently supports.
unsigned int actualFrameSize = sampleFormat * channels / 8;
if (rate < 100 || rate > 96000 ||
(((channels < 1 || channels > MAX_CHANNELS) ||
(frameSize != 1 && frameSize != 2 && frameSize != 3 &&
frameSize != 4 && frameSize != 6)) &&
!mIgnoreAudioOutputFormat) ||
(sampleFormat != 8 && sampleFormat != 16 && sampleFormat != 24) ||
frameSize != actualFrameSize) {
NS_WARNING("Invalid WAVE metadata");
return false;
}
mSampleRate = rate;
mChannels = channels;
mFrameSize = frameSize;
if (sampleFormat == 8) {
mSampleFormat = FORMAT_U8;
} else if (sampleFormat == 24) {
mSampleFormat = FORMAT_S24;
} else {
mSampleFormat = FORMAT_S16;
}
return true;
}
bool
WaveReader::FindDataOffset(uint32_t aChunkSize)
{
MOZ_ASSERT(OnTaskQueue());
// RIFF chunks are always word (two byte) aligned.
MOZ_ASSERT(mResource.Tell() % 2 == 0,
"FindDataOffset called with unaligned resource");
int64_t offset = mResource.Tell();
if (offset <= 0 || offset > UINT32_MAX) {
NS_WARNING("PCM data offset out of range");
return false;
}
mWaveLength = aChunkSize;
mWavePCMOffset = uint32_t(offset);
return true;
}
double
WaveReader::BytesToTime(int64_t aBytes) const
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aBytes >= 0, "Must be >= 0");
return float(aBytes) / mSampleRate / mFrameSize;
}
int64_t
WaveReader::TimeToBytes(double aTime) const
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aTime >= 0.0f, "Must be >= 0");
return RoundDownToFrame(int64_t(aTime * mSampleRate * mFrameSize));
}
int64_t
WaveReader::RoundDownToFrame(int64_t aBytes) const
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aBytes >= 0, "Must be >= 0");
return aBytes - (aBytes % mFrameSize);
}
int64_t
WaveReader::GetDataLength()
{
MOZ_ASSERT(OnTaskQueue());
int64_t length = mWaveLength;
// If the decoder has a valid content length, and it's shorter than the
// expected length of the PCM data, calculate the playback duration from
// the content length rather than the expected PCM data length.
int64_t streamLength = mDecoder->GetResource()->GetLength();
if (streamLength >= 0) {
int64_t dataLength = std::max<int64_t>(0, streamLength - mWavePCMOffset);
length = std::min(dataLength, length);
}
return length;
}
int64_t
WaveReader::GetPosition()
{
return mResource.Tell();
}
bool
WaveReader::LoadListChunk(uint32_t aChunkSize,
nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags)
{
MOZ_ASSERT(OnTaskQueue());
// List chunks are always word (two byte) aligned.
MOZ_ASSERT(mResource.Tell() % 2 == 0,
"LoadListChunk called with unaligned resource");
static const unsigned int MAX_CHUNK_SIZE = 1 << 16;
static_assert(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char),
"MAX_CHUNK_SIZE too large for enumerator.");
if (aChunkSize > MAX_CHUNK_SIZE || aChunkSize < 4) {
return false;
}
auto chunk = MakeUnique<char[]>(aChunkSize);
if (!ReadAll(chunk.get(), aChunkSize)) {
return false;
}
static const uint32_t INFO_LIST_MAGIC = 0x494e464f;
const char* p = chunk.get();
if (ReadUint32BE(&p) != INFO_LIST_MAGIC) {
return false;
}
const waveIdToName ID_TO_NAME[] = {
{ 0x49415254, NS_LITERAL_CSTRING("artist") }, // IART
{ 0x49434d54, NS_LITERAL_CSTRING("comments") }, // ICMT
{ 0x49474e52, NS_LITERAL_CSTRING("genre") }, // IGNR
{ 0x494e414d, NS_LITERAL_CSTRING("name") }, // INAM
};
const char* const end = chunk.get() + aChunkSize;
aTags = new dom::HTMLMediaElement::MetadataTags;
while (p + 8 < end) {
uint32_t id = ReadUint32BE(&p);
// Uppercase tag id, inspired by GStreamer's Wave parser.
id &= 0xDFDFDFDF;
uint32_t length = ReadUint32LE(&p);
// Subchunk shall not exceed parent chunk.
if (uint32_t(end - p) < length) {
break;
}
// Wrap the string, adjusting length to account for optional
// null termination in the chunk.
nsCString val(p, length);
if (length > 0 && val[length - 1] == '\0') {
val.SetLength(length - 1);
}
// Chunks in List::INFO are always word (two byte) aligned. So round up if
// necessary.
length += length % 2;
p += length;
if (!IsUTF8(val)) {
continue;
}
for (size_t i = 0; i < mozilla::ArrayLength(ID_TO_NAME); ++i) {
if (id == ID_TO_NAME[i].id) {
aTags->Put(ID_TO_NAME[i].name, val);
break;
}
}
}
return true;
}
bool
WaveReader::LoadAllChunks(nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags)
{
MOZ_ASSERT(OnTaskQueue());
// Chunks are always word (two byte) aligned.
MOZ_ASSERT(mResource.Tell() % 2 == 0,
"LoadAllChunks called with unaligned resource");
bool loadFormatChunk = false;
bool findDataOffset = false;
for (;;) {
static const unsigned int CHUNK_HEADER_SIZE = 8;
char chunkHeader[CHUNK_HEADER_SIZE];
const char* p = chunkHeader;
if (!ReadAll(chunkHeader, sizeof(chunkHeader))) {
return false;
}
static_assert(sizeof(uint32_t) * 2 <= CHUNK_HEADER_SIZE,
"Reads would overflow chunkHeader buffer.");
uint32_t magic = ReadUint32BE(&p);
uint32_t chunkSize = ReadUint32LE(&p);
int64_t chunkStart = GetPosition();
switch (magic) {
case FRMT_CHUNK_MAGIC:
loadFormatChunk = LoadFormatChunk(chunkSize);
if (!loadFormatChunk) {
return false;
}
break;
case LIST_CHUNK_MAGIC:
if (!aTags) {
LoadListChunk(chunkSize, aTags);
}
break;
case DATA_CHUNK_MAGIC:
findDataOffset = FindDataOffset(chunkSize);
return loadFormatChunk && findDataOffset;
default:
break;
}
// RIFF chunks are two-byte aligned, so round up if necessary.
chunkSize += chunkSize % 2;
// Move forward to next chunk
CheckedInt64 forward = CheckedInt64(chunkStart) + chunkSize - GetPosition();
if (!forward.isValid() || forward.value() < 0) {
return false;
}
static const int64_t MAX_CHUNK_SIZE = 1 << 16;
static_assert(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char),
"MAX_CHUNK_SIZE too large for enumerator.");
auto chunk = MakeUnique<char[]>(MAX_CHUNK_SIZE);
while (forward.value() > 0) {
int64_t size = std::min(forward.value(), MAX_CHUNK_SIZE);
if (!ReadAll(chunk.get(), size)) {
return false;
}
forward -= size;
}
}
return false;
}
} // namespace mozilla

Просмотреть файл

@ -1,95 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#if !defined(WaveReader_h_)
#define WaveReader_h_
#include "MediaDecoderReader.h"
#include "MediaResource.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "nsAutoPtr.h"
namespace mozilla {
class WaveReader : public MediaDecoderReader
{
public:
explicit WaveReader(AbstractMediaDecoder* aDecoder);
protected:
~WaveReader();
public:
bool DecodeAudioData() override;
bool DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold) override;
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
RefPtr<SeekPromise> Seek(SeekTarget aTarget, int64_t aEndTime) override;
media::TimeIntervals GetBuffered() override;
private:
bool ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead = nullptr);
bool LoadRIFFChunk();
bool LoadFormatChunk(uint32_t aChunkSize);
bool FindDataOffset(uint32_t aChunkSize);
bool LoadListChunk(uint32_t aChunkSize, nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags);
bool LoadAllChunks(nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags);
// Returns the number of seconds that aBytes represents based on the
// current audio parameters. e.g. 176400 bytes is 1 second at 16-bit
// stereo 44.1kHz. The time is rounded to the nearest microsecond.
double BytesToTime(int64_t aBytes) const;
// Returns the number of bytes that aTime represents based on the current
// audio parameters. e.g. 1 second is 176400 bytes at 16-bit stereo
// 44.1kHz.
int64_t TimeToBytes(double aTime) const;
// Rounds aBytes down to the nearest complete audio frame. Assumes
// beginning of byte range is already frame aligned by caller.
int64_t RoundDownToFrame(int64_t aBytes) const;
int64_t GetDataLength();
int64_t GetPosition();
/*
Metadata extracted from the WAVE header. Used to initialize the audio
stream, and for byte<->time domain conversions.
*/
// Number of samples per second. Limited to range [100, 96000] in LoadFormatChunk.
uint32_t mSampleRate;
// Number of channels. Limited to range [1, 2] in LoadFormatChunk.
uint32_t mChannels;
// Size of a single audio frame, which includes a sample for each channel
// (interleaved).
uint32_t mFrameSize;
// The sample format of the PCM data. AudioStream::SampleFormat doesn't
// support U8.
enum {
FORMAT_U8,
FORMAT_S16,
FORMAT_S24
} mSampleFormat;
// Size of PCM data stored in the WAVE as reported by the data chunk in
// the media.
int64_t mWaveLength;
// Start offset of the PCM data in the media stream. Extends mWaveLength
// bytes.
int64_t mWavePCMOffset;
MediaResourceIndex mResource;
};
} // namespace mozilla
#endif

Просмотреть файл

@ -7,13 +7,11 @@
EXPORTS += [
'WaveDecoder.h',
'WaveDemuxer.h',
'WaveReader.h',
]
UNIFIED_SOURCES += [
'WaveDecoder.cpp',
'WaveDemuxer.cpp',
'WaveReader.cpp',
]
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -255,8 +255,8 @@ class SpeechEvent : public Runnable
public:
SpeechEvent(SpeechRecognition* aRecognition, SpeechRecognition::EventType aType)
: mAudioSegment(0)
, mRecognitionResultList(0)
, mError(0)
, mRecognitionResultList(nullptr)
, mError(nullptr)
, mRecognition(aRecognition)
, mType(aType)
, mTrackRate(0)

Просмотреть файл

@ -132,7 +132,8 @@ Presentation::HasReceiverSupport() const
}
if (!Preferences::GetBool("dom.presentation.testing.simulate-receiver") &&
!docShell->GetIsInMozBrowserOrApp()) {
!docShell->GetIsInMozBrowserOrApp() &&
!docShell->GetIsTopLevelContentDocShell()) {
return false;
}

Просмотреть файл

@ -1602,8 +1602,9 @@ PresentationPresentingInfo::ResolvedCallback(JSContext* aCx,
}
// Start to listen to document state change event |STATE_TRANSFERRING|.
HTMLIFrameElement* frame = nullptr;
nsresult rv = UNWRAP_OBJECT(HTMLIFrameElement, obj, frame);
// Use Element to support both HTMLIFrameElement and nsXULElement.
Element* frame = nullptr;
nsresult rv = UNWRAP_OBJECT(Element, obj, frame);
if (NS_WARN_IF(!frame)) {
ReplyError(NS_ERROR_DOM_OPERATION_ERR);
return;

Просмотреть файл

@ -0,0 +1,461 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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/. */
/* jshint esnext:true, globalstrict:true, moz:true, undef:true, unused:true */
/* globals Components, dump */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
// globals XPCOMUtils
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// globals Services
Cu.import("resource://gre/modules/Services.jsm");
// globals Messaging
Cu.import("resource://gre/modules/Messaging.jsm");
function log(str) {
// dump("-*- AndroidCastDeviceProvider -*-: " + str + "\n");
}
// Helper function: transfer nsIPresentationChannelDescription to json
function descriptionToString(aDescription) {
let json = {};
json.type = aDescription.type;
switch(aDescription.type) {
case Ci.nsIPresentationChannelDescription.TYPE_TCP:
let addresses = aDescription.tcpAddress.QueryInterface(Ci.nsIArray);
json.tcpAddress = [];
for (let idx = 0; idx < addresses.length; idx++) {
let address = addresses.queryElementAt(idx, Ci.nsISupportsCString);
json.tcpAddress.push(address.data);
}
json.tcpPort = aDescription.tcpPort;
break;
case Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL:
json.dataChannelSDP = aDescription.dataChannelSDP;
break;
}
return JSON.stringify(json);
}
const TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE = "AndroidCastDevice:SyncDevice";
const TOPIC_ANDROID_CAST_DEVICE_ADDED = "AndroidCastDevice:Added";
const TOPIC_ANDROID_CAST_DEVICE_REMOVED = "AndroidCastDevice:Removed";
const TOPIC_ANDROID_CAST_DEVICE_START = "AndroidCastDevice:Start";
const TOPIC_ANDROID_CAST_DEVICE_STOP = "AndroidCastDevice:Stop";
const TOPIC_PRESENTATION_VIEW_READY = "presentation-view-ready";
function LocalControlChannel(aProvider, aDeviceId, aRole) {
log("LocalControlChannel - create new LocalControlChannel for : "
+ aRole);
this._provider = aProvider;
this._deviceId = aDeviceId;
this._role = aRole;
}
LocalControlChannel.prototype = {
_listener: null,
_provider: null,
_deviceId: null,
_role: null,
_isOnTerminating: false,
_isOnDisconnecting: false,
_pendingConnected: false,
_pendingDisconnect: null,
_pendingOffer: null,
_pendingCandidate: null,
/* For the controller, it would be the control channel of the receiver.
* For the receiver, it would be the control channel of the controller. */
_correspondingControlChannel: null,
set correspondingControlChannel(aCorrespondingControlChannel) {
this._correspondingControlChannel = aCorrespondingControlChannel;
},
get correspondingControlChannel() {
return this._correspondingControlChannel;
},
notifyConnected: function LCC_notifyConnected() {
this._pendingDisconnect = null;
if (!this._listener) {
this._pendingConnected = true;
} else {
this._listener.notifyConnected();
}
},
onOffer: function LCC_onOffer(aOffer) {
if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
log("LocalControlChannel - onOffer of controller should not be called.");
return;
}
if (!this._listener) {
this._pendingOffer = aOffer;
} else {
this._listener.onOffer(aOffer);
}
},
onAnswer: function LCC_onAnswer(aAnswer) {
if (this._role == Ci.nsIPresentationService.ROLE_RECEIVER) {
log("LocalControlChannel - onAnswer of receiver should not be called.");
return;
}
this._listener.onAnswer(aAnswer);
},
notifyIceCandidate: function LCC_notifyIceCandidate(aCandidate) {
if (!this._listener) {
this._pendingCandidate = aCandidate;
} else {
this._listener.onIceCandidate(aCandidate);
}
},
// nsIPresentationControlChannel
get listener() {
return this._listener;
},
set listener(aListener) {
this._listener = aListener;
if (!this._listener) {
return;
}
if (this._pendingConnected) {
this.notifyConnected();
this._pendingConnected = false;
}
if (this._pendingOffer) {
this.onOffer(this._pendingOffer);
this._pendingOffer = null;
}
if (this._pendingCandidate) {
this.notifyIceCandidate(this._pendingCandidate);
this._pendingCandidate = null;
}
if (this._pendingDisconnect != null) {
this.disconnect(this._pendingDisconnect);
this._pendingDisconnect = null;
}
},
sendOffer: function LCC_sendOffer(aOffer) {
if (this._role == Ci.nsIPresentationService.ROLE_RECEIVER) {
log("LocalControlChannel - sendOffer of receiver should not be called.");
return;
}
log("LocalControlChannel - sendOffer aOffer=" + descriptionToString(aOffer));
this._correspondingControlChannel.onOffer(aOffer);
},
sendAnswer: function LCC_sendAnswer(aAnswer) {
if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
log("LocalControlChannel - sendAnswer of controller should not be called.");
return;
}
log("LocalControlChannel - sendAnswer aAnswer=" + descriptionToString(aAnswer));
this._correspondingControlChannel.onAnswer(aAnswer);
},
sendIceCandidate: function LCC_sendIceCandidate(aCandidate) {
log("LocalControlChannel - sendAnswer aCandidate=" + aCandidate);
this._correspondingControlChannel.notifyIceCandidate(aCandidate);
},
launch: function LCC_launch(aPresentationId, aUrl) {
log("LocalControlChannel - launch aPresentationId="
+ aPresentationId + " aUrl=" + aUrl);
// Create control channel for receiver directly.
let controlChannel = new LocalControlChannel(this._provider,
this._deviceId,
Ci.nsIPresentationService.ROLE_RECEIVER);
// Set up the corresponding control channels for both controller and receiver.
this._correspondingControlChannel = controlChannel;
controlChannel._correspondingControlChannel = this;
this._provider.onSessionRequest(this._deviceId,
aUrl,
aPresentationId,
controlChannel);
controlChannel.notifyConnected();
},
terminate: function LCC_terminate(aPresentationId) {
log("LocalControlChannel - terminate aPresentationId="
+ aPresentationId);
if (this._isOnTerminating) {
return;
}
// Create control channel for corresponding role directly.
let correspondingRole = this._role == Ci.nsIPresentationService.ROLE_CONTROLLER
? Ci.nsIPresentationService.ROLE_RECEIVER
: Ci.nsIPresentationService.ROLE_CONTROLLER;
let controlChannel = new LocalControlChannel(this._provider,
this._deviceId,
correspondingRole);
// Prevent the termination recursion.
controlChannel._isOnTerminating = true;
// Set up the corresponding control channels for both controller and receiver.
this._correspondingControlChannel = controlChannel;
controlChannel._correspondingControlChannel = this;
this._provider.onTerminateRequest(this._deviceId,
aPresentationId,
controlChannel,
this._role == Ci.nsIPresentationService.ROLE_RECEIVER);
controlChannel.notifyConnected();
},
disconnect: function LCC_disconnect(aReason) {
log("LocalControlChannel - disconnect aReason=" + aReason);
if (this._isOnDisconnecting) {
return;
}
this._pendingOffer = null;
this._pendingCandidate = null;
this._pendingConnected = false;
// this._pendingDisconnect is a nsresult.
// If it is null, it means no pending disconnect.
// If it is NS_OK, it means this control channel is disconnected normally.
// If it is other nsresult value, it means this control channel is
// disconnected abnormally.
// Remote endpoint closes the control channel with abnormal reason.
if (aReason == Cr.NS_OK &&
this._pendingDisconnect != null &&
this._pendingDisconnect != Cr.NS_OK) {
aReason = this._pendingDisconnect;
}
if (!this._listener) {
this._pendingDisconnect = aReason;
return;
}
this._isOnDisconnecting = true;
this._correspondingControlChannel.disconnect(aReason);
this._listener.notifyDisconnected(aReason);
},
reconnect: function LCC_reconnect(aPresentationId, aUrl) {
log("1-UA on Android doesn't support reconnect.");
throw Cr.NS_ERROR_FAILURE;
},
classID: Components.ID("{c9be9450-e5c7-4294-a287-376971b017fd}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
};
function ChromecastRemoteDisplayDevice(aProvider, aId, aName, aRole) {
this._provider = aProvider;
this._id = aId;
this._name = aName;
this._role = aRole;
}
ChromecastRemoteDisplayDevice.prototype = {
_id: null,
_name: null,
_role: null,
_provider: null,
_ctrlChannel: null,
update: function CRDD_update(aName) {
this._name = aName || this._name;
},
// nsIPresentationDevice
get id() { return this._id; },
get name() { return this._name; },
get type() { return "chromecast"; },
establishControlChannel: function CRDD_establishControlChannel() {
this._ctrlChannel = new LocalControlChannel(this._provider,
this._id,
this._role);
if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
// Only connect to Chromecast for controller.
// Monitor the receiver being ready.
Services.obs.addObserver(this, TOPIC_PRESENTATION_VIEW_READY, true);
// Launch Chromecast service in Android.
Messaging.sendRequestForResult({
type: TOPIC_ANDROID_CAST_DEVICE_START,
id: this.id
}).then(result => {
log("Chromecast is connected.");
}).catch(error => {
log("Can not connect to Chromecast.");
// If Chromecast can not be launched, remove the observer.
Services.obs.removeObserver(this, TOPIC_PRESENTATION_VIEW_READY);
this._ctrlChannel.disconnect(Cr.NS_ERROR_FAILURE);
});
} else {
// If establishControlChannel called from the receiver, we don't need to
// wait the 'presentation-view-ready' event.
this._ctrlChannel.notifyConnected();
}
return this._ctrlChannel;
},
disconnect: function CRDD_disconnect() {
// Disconnect from Chromecast.
Messaging.sendRequestForResult({
type: TOPIC_ANDROID_CAST_DEVICE_STOP,
id: this.id
});
},
isRequestedUrlSupported: function CRDD_isRequestedUrlSupported(aUrl) {
let url = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(aUrl, null, null);
return url.scheme == "http" || url.scheme == "https";
},
// nsIPresentationLocalDevice
get windowId() { return this._id; },
// nsIObserver
observe: function CRDD_observe(aSubject, aTopic, aData) {
if (aTopic == TOPIC_PRESENTATION_VIEW_READY) {
log("ChromecastRemoteDisplayDevice - observe: aTopic="
+ aTopic + " data=" + aData);
if (this.windowId === aData) {
Services.obs.removeObserver(this, TOPIC_PRESENTATION_VIEW_READY);
this._ctrlChannel.notifyConnected();
}
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice,
Ci.nsIPresentationLocalDevice,
Ci.nsISupportsWeakReference,
Ci.nsIObserver]),
};
function AndroidCastDeviceProvider() {
}
AndroidCastDeviceProvider.prototype = {
_listener: null,
_deviceList: new Map(),
onSessionRequest: function APDP_onSessionRequest(aDeviceId,
aUrl,
aPresentationId,
aControlChannel) {
log("AndroidCastDeviceProvider - onSessionRequest"
+ " aDeviceId=" + aDeviceId);
let device = this._deviceList.get(aDeviceId);
let receiverDevice = new ChromecastRemoteDisplayDevice(this,
device.id,
device.name,
Ci.nsIPresentationService.ROLE_RECEIVER);
this._listener.onSessionRequest(receiverDevice,
aUrl,
aPresentationId,
aControlChannel);
},
onTerminateRequest: function APDP_onTerminateRequest(aDeviceId,
aPresentationId,
aControlChannel,
aIsFromReceiver) {
log("AndroidCastDeviceProvider - onTerminateRequest"
+ " aDeviceId=" + aDeviceId
+ " aPresentationId=" + aPresentationId
+ " aIsFromReceiver=" + aIsFromReceiver);
let device = this._deviceList.get(aDeviceId);
this._listener.onTerminateRequest(device,
aPresentationId,
aControlChannel,
aIsFromReceiver);
},
// nsIPresentationDeviceProvider
set listener(aListener) {
this._listener = aListener;
// When unload this provider.
if (!this._listener) {
// remove observer
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED);
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED);
return;
}
// Sync all device already found by Android.
Services.obs.notifyObservers(null, TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE, "");
// Observer registration
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED, false);
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED, false);
},
get listener() {
return this._listener;
},
forceDiscovery: function APDP_forceDiscovery() {
// There is no API to do force discovery in Android SDK.
},
// nsIObserver
observe: function APDP_observe(aSubject, aTopic, aData) {
switch (aTopic) {
case TOPIC_ANDROID_CAST_DEVICE_ADDED: {
let deviceInfo = JSON.parse(aData);
let deviceId = deviceInfo.uuid;
if (!this._deviceList.has(deviceId)) {
let device = new ChromecastRemoteDisplayDevice(this,
deviceInfo.uuid,
deviceInfo.friendlyName,
Ci.nsIPresentationService.ROLE_CONTROLLER);
this._deviceList.set(device.id, device);
this._listener.addDevice(device);
} else {
let device = this._deviceList.get(deviceId);
device.update(deviceInfo.friendlyName);
this._listener.updateDevice(device);
}
break;
}
case TOPIC_ANDROID_CAST_DEVICE_REMOVED: {
let deviceId = aData;
let device = this._deviceList.get(deviceId);
this._listener.removeDevice(device);
this._deviceList.delete(deviceId);
break;
}
}
},
classID: Components.ID("{7394f24c-dbc3-48c8-8a47-cd10169b7c6b}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsIPresentationDeviceProvider]),
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AndroidCastDeviceProvider]);

Просмотреть файл

@ -0,0 +1,4 @@
# AndroidCastDeviceProvider.js
component {7394f24c-dbc3-48c8-8a47-cd10169b7c6b} AndroidCastDeviceProvider.js
contract @mozilla.org/presentation-device/android-cast-device-provider;1 {7394f24c-dbc3-48c8-8a47-cd10169b7c6b}
category presentation-device-provider AndroidCastDeviceProvider @mozilla.org/presentation-device/android-cast-device-provider;1

Просмотреть файл

@ -22,9 +22,12 @@ EXTRA_JS_MODULES.presentation += [
'StateMachineHelper.jsm',
]
# for TV 2.5 device backward capability
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
EXTRA_COMPONENTS += [
# For android presentation device
'AndroidCastDeviceProvider.js',
'AndroidCastDeviceProvider.manifest',
# for TV 2.5 device backward capability
'LegacyPresentationControlService.js',
'LegacyProviders.manifest',
]

Просмотреть файл

@ -296,7 +296,7 @@ protected:
char16_t mChar;
WSPoint()
: mTextNode(0)
: mTextNode(nullptr)
, mOffset(0)
, mChar(0)
{}

Просмотреть файл

@ -105,8 +105,8 @@ skip-if(Android) needs-focus == 462758-grabbers-resizers.html 462758-grabbers-re
needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html
fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658
fuzzy-if(skiaContent,1,3400) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-1.html 824080-1-ref.html
needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-2.html 824080-2-ref.html
needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-3.html 824080-3-ref.html
fuzzy-if(OSX,1,1) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-2.html 824080-2-ref.html #Bug 1313253
fuzzy-if(OSX,1,1) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-3.html 824080-3-ref.html #Bug 1312951
needs-focus != 824080-2.html 824080-3.html
fuzzy-if(skiaContent,1,3200) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-4.html 824080-4-ref.html
fuzzy-if(skiaContent,2,1800) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-5.html 824080-5-ref.html

Просмотреть файл

@ -19,7 +19,7 @@ NS_IMPL_ISUPPORTS(nsTransactionList, nsITransactionList)
nsTransactionList::nsTransactionList(nsITransactionManager *aTxnMgr, nsTransactionStack *aTxnStack)
: mTxnStack(aTxnStack)
, mTxnItem(0)
, mTxnItem(nullptr)
{
if (aTxnMgr)
mTxnMgr = do_GetWeakReference(aTxnMgr);
@ -36,7 +36,7 @@ nsTransactionList::nsTransactionList(nsITransactionManager *aTxnMgr, nsTransacti
nsTransactionList::~nsTransactionList()
{
mTxnStack = 0;
mTxnItem = 0;
mTxnItem = nullptr;
}
NS_IMETHODIMP nsTransactionList::GetNumItems(int32_t *aNumItems)

Просмотреть файл

@ -1211,9 +1211,8 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags)
{
// The only reason we allow aAllocator to be null is for gtests
MOZ_ASSERT(!aAllocator || aAllocator->GetLayersIPCActor()->IPCOpen());
if (aAllocator && !aAllocator->GetLayersIPCActor()->IPCOpen()) {
if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
return nullptr;
}
@ -1229,7 +1228,7 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
}
return MakeAndAddRef<TextureClient>(data, aTextureFlags,
aAllocator ? aAllocator->GetTextureForwarder() : nullptr);
aAllocator->GetTextureForwarder());
}
// static
@ -1241,7 +1240,7 @@ TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
{
// also test the validity of aAllocator
MOZ_ASSERT(!aAllocator || aAllocator->GetLayersIPCActor()->IPCOpen());
if (aAllocator && !aAllocator->GetLayersIPCActor()->IPCOpen()) {
if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
return nullptr;
}
@ -1253,7 +1252,7 @@ TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
}
return MakeAndAddRef<TextureClient>(data, aTextureFlags,
aAllocator ? aAllocator->GetTextureForwarder() : 0);
aAllocator->GetTextureForwarder());
}
TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)

Просмотреть файл

@ -8,9 +8,10 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/RefPtr.h"
#include "gfx2DGlue.h"
#include "gfxImageSurface.h"
@ -266,7 +267,16 @@ TEST(Layers, TextureYCbCrSerialization) {
clientData.mPicX = 0;
clientData.mPicX = 0;
RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(nullptr, clientData.mYSize, clientData.mCbCrSize,
ImageBridgeChild::InitSameProcess();
// wait until IPDL connection
#ifdef XP_WIN
Sleep(1);
#else
sleep(1);
#endif
RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mCbCrSize,
StereoMode::MONO, YUVColorSpace::BT601,
TextureFlags::DEALLOCATE_CLIENT);

Просмотреть файл

@ -523,6 +523,7 @@ private:
DECL_GFX_PREF(Live, "layers.transaction.warning-ms", LayerTransactionWarning, uint32_t, 200);
DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false);
DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces", UseImageOffscreenSurfaces, bool, true);
DECL_GFX_PREF(Live, "layers.draw-mask-debug", DrawMaskLayer, bool, false);
DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, true);

Просмотреть файл

@ -38,7 +38,7 @@ public:
//-----------------------------------------------------------------------------
ObjectWatcher::ObjectWatcher() : watch_(NULL) {
ObjectWatcher::ObjectWatcher() : watch_(nullptr) {
}
ObjectWatcher::~ObjectWatcher() {
@ -99,7 +99,7 @@ bool ObjectWatcher::StopWatching() {
// anything once it is run.
watch_->watcher = NULL;
watch_ = NULL;
watch_ = nullptr;
MessageLoop::current()->RemoveDestructionObserver(this);
return true;

Просмотреть файл

@ -12,8 +12,8 @@ namespace base {
void BaseTimer_Helper::OrphanDelayedTask() {
if (delayed_task_) {
delayed_task_->timer_ = NULL;
delayed_task_ = NULL;
delayed_task_->timer_ = nullptr;
delayed_task_ = nullptr;
}
}

Просмотреть файл

@ -176,7 +176,7 @@ class BaseTimer : public BaseTimer_Helper {
// Task is old. So, if the Timer points to a different task, assume
// that the Timer has already taken care of properly setting the task.
if (self->delayed_task_ == this)
self->delayed_task_ = NULL;
self->delayed_task_ = nullptr;
// By now the delayed_task_ in the Timer does not point to us anymore.
// We should reset our own timer_ because the Timer can not do this
// for us in its destructor.

Просмотреть файл

@ -7090,8 +7090,8 @@ bool nsDisplayMask::ShouldPaintOnMaskLayer(LayerManager* aManager)
return false;
}
nsSVGIntegrationUtils::MaskUsage maskUsage;
nsSVGIntegrationUtils::DetermineMaskUsage(mFrame, mHandleOpacity, maskUsage);
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(mFrame, mHandleOpacity, maskUsage);
if (!maskUsage.shouldGenerateMaskLayer ||
maskUsage.opacity != 1.0 || maskUsage.shouldApplyClipPath ||
@ -7118,6 +7118,10 @@ bool nsDisplayMask::ShouldPaintOnMaskLayer(LayerManager* aManager)
}
}
if (gfxPrefs::DrawMaskLayer()) {
return false;
}
return true;
}

Просмотреть файл

@ -168,7 +168,7 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
el = self.marionette.find_element(By.ID, self._input_id)
sel = SelectionManager(el)
content_to_add = '!'
target_content = sel.content + string.ascii_letters + content_to_add
non_target_content = content_to_add + sel.content + string.ascii_letters
el.tap()
sel.move_cursor_to_end()
@ -184,10 +184,10 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
dest_x, dest_y = 0, 0
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
# The content should be inserted at the end of the <input>.
# The content should not be inserted at the front of the <input>.
el.send_keys(content_to_add)
self.assertEqual(target_content, sel.content)
self.assertNotEqual(non_target_content, sel.content)
@parameterized(_input_id, el_id=_input_id)
@parameterized(_input_padding_id, el_id=_input_padding_id)

Просмотреть файл

@ -356,7 +356,7 @@ BlockReflowInput::GetFloatAvailableSpaceWithState(
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
printf("%s: band=%d,%d,%d,%d hasfloats=%d\n", __func__,
result.mRect.IStart(wm), result.mRect.BStart(wm),
result.mRect.ISize(wm), result.mRect.BSize(wm), result.mHasFloats);
}
@ -389,7 +389,7 @@ BlockReflowInput::GetFloatAvailableSpaceForBSize(
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("GetAvailableSpaceForHeight: space=%d,%d,%d,%d hasfloats=%d\n",
printf("%s: space=%d,%d,%d,%d hasfloats=%d\n", __func__,
result.mRect.IStart(wm), result.mRect.BStart(wm),
result.mRect.ISize(wm), result.mRect.BSize(wm), result.mHasFloats);
}
@ -614,7 +614,7 @@ BlockReflowInput::AddFloat(nsLineLayout* aLineLayout,
bool placed;
// Now place the float immediately if possible. Otherwise stash it
// away in mPendingFloats and place it later.
// away in mBelowCurrentLineFloats and place it later.
// If one or more floats has already been pushed to the next line,
// don't let this one go on the current line, since that would violate
// float ordering.
@ -628,7 +628,13 @@ BlockReflowInput::AddFloat(nsLineLayout* aLineLayout,
if (placed) {
// Pass on updated available space to the current inline reflow engine
WritingMode wm = mReflowInput.GetWritingMode();
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mBCoord);
// If we have mLineBSize, we are reflowing the line again due to
// LineReflowStatus::RedoMoreFloats. We should use mLineBSize to query the
// correct available space.
nsFlowAreaRect floatAvailSpace =
mLineBSize.isNothing()
? GetFloatAvailableSpace(mBCoord)
: GetFloatAvailableSpaceForBSize(mBCoord, mLineBSize.value(), nullptr);
LogicalRect availSpace(wm, floatAvailSpace.mRect.IStart(wm), mBCoord,
floatAvailSpace.mRect.ISize(wm),
floatAvailSpace.mRect.BSize(wm));

Просмотреть файл

@ -376,6 +376,12 @@ public:
// The amount of computed block-direction size "consumed" by previous-in-flows.
nscoord mConsumedBSize;
// Cache the current line's BSize if nsBlockFrame::PlaceLine() fails to
// place the line. When redoing the line, it will be used to query the
// accurate float available space in AddFloat() and
// nsBlockFrame::PlaceLine().
mozilla::Maybe<nscoord> mLineBSize;
private:
bool CanPlaceFloat(nscoord aFloatISize,
const nsFlowAreaRect& aFloatAvailableSpace);

Просмотреть файл

@ -3765,7 +3765,8 @@ nsBlockFrame::ReflowInlineFrames(BlockReflowInput& aState,
LineReflowStatus lineReflowStatus;
do {
nscoord availableSpaceHeight = 0;
nscoord availableSpaceBSize = 0;
aState.mLineBSize.reset();
do {
bool allowPullUp = true;
nsIFrame* forceBreakInFrame = nullptr;
@ -3790,7 +3791,7 @@ nsBlockFrame::ReflowInlineFrames(BlockReflowInput& aState,
lineLayout.ForceBreakAtPosition(forceBreakInFrame, forceBreakOffset);
}
DoReflowInlineFrames(aState, lineLayout, aLine,
floatAvailableSpace, availableSpaceHeight,
floatAvailableSpace, availableSpaceBSize,
&floatManagerState, aKeepReflowGoing,
&lineReflowStatus, allowPullUp);
lineLayout.EndLineReflow();
@ -3837,7 +3838,7 @@ nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
nsLineLayout& aLineLayout,
LineIterator aLine,
nsFlowAreaRect& aFloatAvailableSpace,
nscoord& aAvailableSpaceHeight,
nscoord& aAvailableSpaceBSize,
nsFloatManager::SavedState*
aFloatStateBeforeLine,
bool* aKeepReflowGoing,
@ -4044,7 +4045,7 @@ nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
// no point in placing the line.
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
if (!PlaceLine(aState, aLineLayout, aLine, aFloatStateBeforeLine,
aFloatAvailableSpace.mRect, aAvailableSpaceHeight,
aFloatAvailableSpace.mRect, aAvailableSpaceBSize,
aKeepReflowGoing)) {
lineReflowStatus = LineReflowStatus::RedoMoreFloats;
// PlaceLine already called GetAvailableSpaceForBSize for us.
@ -4432,12 +4433,12 @@ nsBlockFrame::IsLastLine(BlockReflowInput& aState,
bool
nsBlockFrame::PlaceLine(BlockReflowInput& aState,
nsLineLayout& aLineLayout,
LineIterator aLine,
nsLineLayout& aLineLayout,
LineIterator aLine,
nsFloatManager::SavedState *aFloatStateBeforeLine,
LogicalRect& aFloatAvailableSpace,
nscoord& aAvailableSpaceHeight,
bool* aKeepReflowGoing)
LogicalRect& aFloatAvailableSpace,
nscoord& aAvailableSpaceBSize,
bool* aKeepReflowGoing)
{
// Trim extra white-space from the line before placing the frames
aLineLayout.TrimTrailingWhiteSpace();
@ -4469,30 +4470,66 @@ nsBlockFrame::PlaceLine(BlockReflowInput& aState,
}
aLineLayout.VerticalAlignLine();
// We want to compare to the available space that we would have had in
// the line's height *before* we placed any floats in the line itself.
// Floats that are in the line are handled during line reflow (and may
// result in floats being pushed to below the line or (I HOPE???) in a
// reflow with a forced break position).
LogicalRect oldFloatAvailableSpace(aFloatAvailableSpace);
// As we redo for floats, we can't reduce the amount of height we're
// We want to consider the floats in the current line when determining
// whether the float available space is shrunk. If mLineBSize doesn't
// exist, we are in the first pass trying to place the line. Calling
// GetFloatAvailableSpace() like we did in BlockReflowInput::AddFloat()
// for UpdateBand().
// floatAvailableSpaceWithOldLineBSize is the float available space with
// the old BSize, but including the floats that were added in this line.
LogicalRect floatAvailableSpaceWithOldLineBSize =
aState.mLineBSize.isNothing()
? aState.GetFloatAvailableSpace(aLine->BStart()).mRect
: aState.GetFloatAvailableSpaceForBSize(aLine->BStart(),
aState.mLineBSize.value(),
nullptr).mRect;
// As we redo for floats, we can't reduce the amount of BSize we're
// checking.
aAvailableSpaceHeight = std::max(aAvailableSpaceHeight, aLine->BSize());
aFloatAvailableSpace =
aAvailableSpaceBSize = std::max(aAvailableSpaceBSize, aLine->BSize());
LogicalRect floatAvailableSpaceWithLineBSize =
aState.GetFloatAvailableSpaceForBSize(aLine->BStart(),
aAvailableSpaceHeight,
aFloatStateBeforeLine).mRect;
NS_ASSERTION(aFloatAvailableSpace.BStart(wm) ==
oldFloatAvailableSpace.BStart(wm), "yikes");
// Restore the height to the position of the next band.
aFloatAvailableSpace.BSize(wm) = oldFloatAvailableSpace.BSize(wm);
aAvailableSpaceBSize,
nullptr).mRect;
// If the available space between the floats is smaller now that we
// know the height, return false (and cause another pass with
// LineReflowStatus::RedoMoreFloats). We ensure aAvailableSpaceHeight
// know the BSize, return false (and cause another pass with
// LineReflowStatus::RedoMoreFloats). We ensure aAvailableSpaceBSize
// never decreases, which means that we can't reduce the set of floats
// we intersect, which means that the available space cannot grow.
if (AvailableSpaceShrunk(wm, oldFloatAvailableSpace, aFloatAvailableSpace,
false)) {
if (AvailableSpaceShrunk(wm, floatAvailableSpaceWithOldLineBSize,
floatAvailableSpaceWithLineBSize, false)) {
// Prepare data for redoing the line.
aState.mLineBSize = Some(aLine->BSize());
// Since we want to redo the line, we update aFloatAvailableSpace by
// using the aFloatStateBeforeLine, which is the float manager's state
// before the line is placed.
LogicalRect oldFloatAvailableSpace(aFloatAvailableSpace);
aFloatAvailableSpace =
aState.GetFloatAvailableSpaceForBSize(aLine->BStart(),
aAvailableSpaceBSize,
aFloatStateBeforeLine).mRect;
NS_ASSERTION(aFloatAvailableSpace.BStart(wm) ==
oldFloatAvailableSpace.BStart(wm), "yikes");
// Restore the BSize to the position of the next band.
aFloatAvailableSpace.BSize(wm) = oldFloatAvailableSpace.BSize(wm);
// Enforce both IStart() and IEnd() never move outwards to prevent
// infinite grow-shrink loops.
const nscoord iStartDiff =
aFloatAvailableSpace.IStart(wm) - oldFloatAvailableSpace.IStart(wm);
const nscoord iEndDiff =
aFloatAvailableSpace.IEnd(wm) - oldFloatAvailableSpace.IEnd(wm);
if (iStartDiff < 0) {
aFloatAvailableSpace.IStart(wm) -= iStartDiff;
aFloatAvailableSpace.ISize(wm) += iStartDiff;
}
if (iEndDiff > 0) {
aFloatAvailableSpace.ISize(wm) -= iEndDiff;
}
return false;
}

Просмотреть файл

@ -659,7 +659,7 @@ protected:
LineIterator aLine,
nsFloatManager::SavedState* aFloatStateBeforeLine,
mozilla::LogicalRect& aFloatAvailableSpace, //in-out
nscoord& aAvailableSpaceHeight, // in-out
nscoord& aAvailableSpaceBSize, // in-out
bool* aKeepReflowGoing);
/**
@ -705,9 +705,8 @@ protected:
nsLineLayout& aLineLayout,
LineIterator aLine,
nsFlowAreaRect& aFloatAvailableSpace,
nscoord& aAvailableSpaceHeight,
nsFloatManager::SavedState*
aFloatStateBeforeLine,
nscoord& aAvailableSpaceBSize,
nsFloatManager::SavedState* aFloatStateBeforeLine,
bool* aKeepReflowGoing,
LineReflowStatus* aLineReflowStatus,
bool aAllowPullUp);

Просмотреть файл

@ -1394,7 +1394,7 @@ fuzzy-if(skiaContent,1,17000) == 498228-1.xul 498228-1-ref.xul
== 501257-1.xhtml 501257-1-ref.xhtml
== 501627-1.html 501627-1-ref.html
== 502288-1.html 502288-1-ref.html
== 502447-1.html 502447-1-ref.html
fuzzy-if(gtkWidget,1,2) == 502447-1.html 502447-1-ref.html #Bug 1315834
== 502795-1.html 502795-1-ref.html
== 502942-1.html 502942-1-ref.html
== 503364-1a.html 503364-1-ref.html

Просмотреть файл

@ -20,6 +20,12 @@
width: 200px;
height: 100px;
}
div.tall {
background-color: blue;
border: 1px dotted purple;
height: 1000px;
width: 50px;
}
</style>
<script>
function runTest() {
@ -31,21 +37,11 @@
<body onload="runTest();">
<details>
<summary id="summary">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
<div class="tall">
</div>
</summary>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.
<div class="tall">
</div>
</details>
</body>
</html>

Просмотреть файл

@ -16,24 +16,21 @@
width: 200px;
height: 100px;
}
div.tall {
background-color: blue;
border: 1px dotted purple;
height: 1000px;
width: 50px;
}
</style>
<body>
<div id="details">
<div id="summary">Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
<div id="summary">
<div class="tall">
</div>
</div>
<div class="tall">
</div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.
</div>
</body>
</html>

Просмотреть файл

@ -20,24 +20,21 @@
width: 200px;
height: 100px;
}
div.tall {
background-color: blue;
border: 1px dotted purple;
height: 1000px;
width: 50px;
}
</style>
<body>
<details open>
<summary>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
<summary>
<div class="tall">
</div>
</summary>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.
<div class="tall">
</div>
</details>
</body>
</html>

Просмотреть файл

@ -95,7 +95,7 @@ fuzzy-if(gtkWidget,1,20) == mouse-click-overflow-auto-details.html overflow-auto
== mouse-click-fixed-summary.html open-fixed-summary.html
== mouse-click-twice-fixed-summary.html fixed-summary.html
== mouse-click-float-details.html open-float-details.html
== mouse-click-twice-float-details.html float-details.html
fuzzy-if(gtkWidget,1,1) == mouse-click-twice-float-details.html float-details.html #Bug 1316430
# Dispatch keyboard event to summary
== key-enter-single-summary.html open-single-summary.html

Просмотреть файл

@ -0,0 +1,39 @@
<!DOCTYPE html>
<style>
.container {
position: relative;
width: 250px;
height: 300px;
border: 1px solid blue;
}
.float1 {
position: absolute;
width: 100px;
height: 50px;
background-color: green;
}
.float2 {
position: absolute;
top: 50px;
width: 180px;
height: 50px;
background-color: lightgreen;
}
.box {
position: absolute;
left: 180px;
width: 30px;
height: 80px;
background-color: blue;
}
</style>
<div class="container">
<div class="float1"></div>
<div class="float2"></div>
<div class="box"></div>
</div>
<p>The test pass if the inline blue box does not overlap any of the green float boxes.</p>

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<style>
.container {
width: 250px;
height: 300px;
border: 1px solid blue;
}
.float1 {
float: left;
width: 100px;
height: 50px;
background-color: green;
}
.float2 {
float: left;
width: 180px;
height: 50px;
background-color: lightgreen;
}
.box {
display: inline-block;
width: 30px;
height: 80px;
background-color: blue;
}
</style>
<div class="container">
<div class="float1"></div>
<div class="float2"></div>
<div class="box"></div>
</div>
<p>The test pass if the inline blue box does not overlap any of the green float boxes.</p>

Просмотреть файл

@ -0,0 +1,40 @@
<!DOCTYPE html>
<style>
.container {
position: relative;
width: 250px;
height: 300px;
border: 1px solid blue;
}
.float1 {
position: absolute;
width: 100px;
height: 50px;
background-color: green;
}
.float2 {
position: absolute;
top: 50px;
left: 70px;
width: 180px;
height: 50px;
background-color: lightgreen;
}
.box {
position: absolute;
top: 50px;
width: 30px;
height: 80px;
background-color: blue;
}
</style>
<div class="container">
<div class="float1"></div>
<div class="float2"></div>
<div class="box"></div>
</div>
<p>The test pass if the inline blue box does not overlap any of the green float boxes.</p>

Просмотреть файл

@ -0,0 +1,36 @@
<!DOCTYPE html>
<style>
.container {
width: 250px;
height: 300px;
border: 1px solid blue;
}
.float1 {
float: left;
width: 100px;
height: 50px;
background-color: green;
}
.float2 {
float: right;
width: 180px;
height: 50px;
background-color: lightgreen;
}
.box {
display: inline-block;
width: 30px;
height: 80px;
background-color: blue;
}
</style>
<div class="container">
<div class="float1"></div>
<div class="float2"></div>
<div class="box"></div>
</div>
<p>The test pass if the inline blue box does not overlap any of the green float boxes.</p>

Просмотреть файл

@ -10,7 +10,7 @@ fuzzy-if(gtkWidget,1,10) == float-outside-block-push.html float-outside-block-pu
== relative-float-2.html relative-float-2-ref.html
== zero-height-float-base.html zero-height-float-ref.html
fails == zero-height-float.html zero-height-float-ref.html # bug 81710
fails == 345369-1.html 345369-1-ref.html
== 345369-1.html 345369-1-ref.html
fails == 345369-2.html 345369-2-ref.html
== 345369-3.html 345369-3-ref.html
== 345369-4.html 345369-4-ref.html
@ -24,6 +24,8 @@ fails == 345369-2.html 345369-2-ref.html
== 1260031-1.html?display:table 1260031-1-ref.html
== 1260031-1.html?display:table-cell 1260031-1-ref.html
== 1260031-1.html?overflow:hidden 1260031-1-ref.html
== 1291110-1.html 1291110-1-ref.html
== 1291110-2.html 1291110-2-ref.html
== float-in-rtl-1a.html float-in-rtl-1-ref.html
fuzzy-if(skiaContent,1,27000) == float-in-rtl-1b.html float-in-rtl-1-ref.html
fuzzy-if(skiaContent,1,27000) == float-in-rtl-1c.html float-in-rtl-1-ref.html

Просмотреть файл

@ -1,5 +1,16 @@
<!DOCTYPE HTML>
<html>
<html class="reftest-wait">
<script>
/* this test shouldn't need reftest-wait, but if the reftest snapshot is triggered before we've painted,
* then we might not get a chance to invalidate the -moz-element div in time
* See Bug 1283302
*/
window.addEventListener("MozReftestInvalidate", endTest);
function endTest() {
document.documentElement.removeAttribute("class");
}
</script>
<body>
<div id="A" style="background:url(repeatable-diagonal-gradient.png?1234); width:100px; height:100px"></div>
<div style="background:-moz-element(#A); width:100px; height:100px;"></div>

Просмотреть файл

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Masking: clip-path in SVG mask</title>
<link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image">
<link rel="match" href="mask-image-3-ref.html">
<meta name="assert" content="Test checks whether clip-path in SVG mask works correctly or not.">
<svg height="0">
<mask id="mask1" x="0" y="0" width="1" height="1" >
<rect x="0" y="0" width="50" height="50" style="stroke:none; fill: #ffffff"/>
</mask>
<mask id="mask2" x="0" y="0" width="1" height="1" >
<rect x="25" y="25" width="50" height="50" style="stroke:none; fill: #ffffff" clip-path="circle(50% at 50% 50%)"/>
</mask>
</svg>
<style type="text/css">
div {
background-color: purple;
mask-image: url(#mask1), url(#mask2);
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

Просмотреть файл

@ -26,6 +26,7 @@ fuzzy-if(skiaContent||winWidget,1,43) == mask-image-3d.html mask-image-3-ref.htm
== mask-image-3e.html mask-image-3-ref.html
fuzzy-if(skiaContent,50,50) == mask-image-3f.html mask-image-3-ref.html
== mask-image-3g.html mask-image-3-ref.html
pref(layout.css.clip-path-shapes.enabled,true) == mask-image-3h.html mask-image-3-ref.html
== mask-image-4a.html blank.html
== mask-image-4b.html blank.html
== mask-image-5.html mask-image-5-ref.html

Просмотреть файл

@ -1,5 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing</title>
<link href="http://fantasai.inkedblade.net/contact" title="Elika J. Etemad" rel="author"></link>
@ -131,6 +131,17 @@
}
</style>
</head>
<script>
/* this test shouldn't need reftest-wait, but if the reftest snapshot is triggered before we've painted,
* for img5 the right 1/3rd of the element simply isn't painted.
* See Bug 1283302
*/
window.addEventListener("MozReftestInvalidate", endTest);
function endTest() {
document.documentElement.removeAttribute("class");
}
</script>
<body>
<div>All rectangles should be the same size.</div>
<p><img id="img0" class="with-padding" src="support/replaced-min-max.png" alt="FAIL" title="Test 0"></img></p>

Просмотреть файл

@ -1815,6 +1815,10 @@ Loader::SheetComplete(SheetLoadData* aLoadData, nsresult aStatus)
{
LOG(("css::Loader::SheetComplete"));
if (aLoadData->mSheet->IsServo() && NS_FAILED(aStatus)) {
aLoadData->mSheet->AsServo()->LoadFailed();
}
// 8 is probably big enough for all our common cases. It's not likely that
// imports will nest more than 8 deep, and multiple sheets with the same URI
// are rare.

Просмотреть файл

@ -22,6 +22,8 @@
SERVO_BINDING_FUNC(Servo_Node_ClearNodeData, void, RawGeckoNodeBorrowed node)
// Styleset and Stylesheet management
SERVO_BINDING_FUNC(Servo_StyleSheet_Empty, RawServoStyleSheetStrong,
mozilla::css::SheetParsingMode parsing_mode)
SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes, RawServoStyleSheetStrong,
const nsACString* data,
mozilla::css::SheetParsingMode parsing_mode,

Просмотреть файл

@ -81,6 +81,12 @@ ServoStyleSheet::ParseSheet(const nsAString& aInput,
return NS_OK;
}
void
ServoStyleSheet::LoadFailed()
{
mSheet = Servo_StyleSheet_Empty(mParsingMode).Consume();
}
void
ServoStyleSheet::DropSheet()
{

Просмотреть файл

@ -40,6 +40,13 @@ public:
nsIPrincipal* aSheetPrincipal,
uint32_t aLineNumber);
/**
* Called instead of ParseSheet to initialize the Servo stylesheet object
* for a failed load. Either ParseSheet or LoadFailed must be called before
* adding a ServoStyleSheet to a ServoStyleSet.
*/
void LoadFailed();
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
#ifdef DEBUG

Просмотреть файл

@ -576,19 +576,6 @@ CreateAndPaintMaskSurface(const PaintFramesParams& aParams,
return DrawResult::SUCCESS;
}
static float
ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity)
{
float opacity = aFrame->StyleEffects()->mOpacity;
if (opacity != 1.0f &&
(nsSVGUtils::CanOptimizeOpacity(aFrame) || !aHandleOpacity)) {
return 1.0f;
}
return opacity;
}
static bool
ValidateSVGFrame(nsIFrame* aFrame)
{
@ -685,72 +672,6 @@ SetupContextMatrix(nsIFrame* aFrame, const PaintFramesParams& aParams,
}
}
void
nsSVGIntegrationUtils::DetermineMaskUsage(nsIFrame* aFrame,
bool aHandleOpacity,
MaskUsage& aUsage)
{
aUsage.opacity = ComputeOpacity(aFrame, aHandleOpacity);
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
// For a HTML doc:
// According to css-masking spec, always create a mask surface when we
// have any item in maskFrame even if all of those items are
// non-resolvable <mask-sources> or <images>, we still need to create a
// transparent black mask layer under this condition.
// For a SVG doc:
// SVG 1.1 say that if we fail to resolve a mask, we should draw the
// object unmasked.
aUsage.shouldGenerateMaskLayer =
(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
? maskFrames.Length() == 1 && maskFrames[0]
: maskFrames.Length() > 0;
#else
// Since we do not support image mask so far, we should treat any
// unresolvable mask as no mask. Otherwise, any object with a valid image
// mask, e.g. url("xxx.png"), will become invisible just because we can not
// handle image mask correctly. (See bug 1294171)
aUsage.shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
#endif
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
MOZ_ASSERT_IF(clipPathFrame,
svgReset->mClipPath.GetType() == StyleShapeSourceType::URL);
switch (svgReset->mClipPath.GetType()) {
case StyleShapeSourceType::URL:
if (clipPathFrame) {
if (clipPathFrame->IsTrivial()) {
aUsage.shouldApplyClipPath = true;
} else {
aUsage.shouldGenerateClipMaskLayer = true;
}
}
break;
case StyleShapeSourceType::Shape:
case StyleShapeSourceType::Box:
aUsage.shouldApplyBasicShape = true;
break;
case StyleShapeSourceType::None:
MOZ_ASSERT(!aUsage.shouldGenerateClipMaskLayer &&
!aUsage.shouldApplyClipPath && !aUsage.shouldApplyBasicShape);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unsupported clip-path type.");
break;
}
}
bool
nsSVGIntegrationUtils::IsMaskResourceReady(nsIFrame* aFrame)
{
@ -780,8 +701,9 @@ nsSVGIntegrationUtils::IsMaskResourceReady(nsIFrame* aFrame)
DrawResult
nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
{
MaskUsage maskUsage;
DetermineMaskUsage(aParams.frame, aParams.handleOpacity, maskUsage);
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
maskUsage);
MOZ_ASSERT(maskUsage.shouldGenerateMaskLayer);
nsIFrame* frame = aParams.frame;
@ -841,8 +763,9 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
return result;
}
MaskUsage maskUsage;
DetermineMaskUsage(aParams.frame, aParams.handleOpacity, maskUsage);
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
maskUsage);
if (maskUsage.opacity == 0.0f) {
return DrawResult::SUCCESS;
@ -971,6 +894,18 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
aParams.builder);
basic->SetTarget(oldCtx);
if (gfxPrefs::DrawMaskLayer()) {
gfxContextAutoSaveRestore saver(&context);
context.NewPath();
gfxRect drawingRect =
nsLayoutUtils::RectToGfxRect(aParams.borderArea,
frame->PresContext()->AppUnitsPerDevPixel());
context.Rectangle(drawingRect, true);
context.SetColor(Color(0.0, 1.0, 0.0, 1.0));
context.Fill();
}
if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
context.PopClip();
}
@ -995,7 +930,7 @@ nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams)
return DrawResult::SUCCESS;
}
float opacity = ComputeOpacity(frame, aParams.handleOpacity);
float opacity = nsSVGUtils::ComputeOpacity(frame, aParams.handleOpacity);
if (opacity == 0.0f) {
return DrawResult::SUCCESS;
}

Просмотреть файл

@ -167,22 +167,6 @@ public:
static DrawResult
PaintMask(const PaintFramesParams& aParams);
struct MaskUsage {
bool shouldGenerateMaskLayer;
bool shouldGenerateClipMaskLayer;
bool shouldApplyClipPath;
bool shouldApplyBasicShape;
float opacity;
MaskUsage()
: shouldGenerateMaskLayer(false), shouldGenerateClipMaskLayer(false),
shouldApplyClipPath(false), shouldApplyBasicShape(false), opacity(0.0)
{ }
};
static void
DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity, MaskUsage& aUsage);
/**
* Return true if all the mask resource of aFrame are ready.
*/

Просмотреть файл

@ -486,6 +486,139 @@ public:
}
};
float
nsSVGUtils::ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity)
{
float opacity = aFrame->StyleEffects()->mOpacity;
if (opacity != 1.0f &&
(nsSVGUtils::CanOptimizeOpacity(aFrame) || !aHandleOpacity)) {
return 1.0f;
}
return opacity;
}
void
nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
MaskUsage& aUsage)
{
aUsage.opacity = ComputeOpacity(aFrame, aHandleOpacity);
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
// For a HTML doc:
// According to css-masking spec, always create a mask surface when we
// have any item in maskFrame even if all of those items are
// non-resolvable <mask-sources> or <images>, we still need to create a
// transparent black mask layer under this condition.
// For a SVG doc:
// SVG 1.1 say that if we fail to resolve a mask, we should draw the
// object unmasked.
aUsage.shouldGenerateMaskLayer =
(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
? maskFrames.Length() == 1 && maskFrames[0]
: maskFrames.Length() > 0;
#else
// Since we do not support image mask so far, we should treat any
// unresolvable mask as no mask. Otherwise, any object with a valid image
// mask, e.g. url("xxx.png"), will become invisible just because we can not
// handle image mask correctly. (See bug 1294171)
aUsage.shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
#endif
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
MOZ_ASSERT_IF(clipPathFrame,
svgReset->mClipPath.GetType() == StyleShapeSourceType::URL);
switch (svgReset->mClipPath.GetType()) {
case StyleShapeSourceType::URL:
if (clipPathFrame) {
if (clipPathFrame->IsTrivial()) {
aUsage.shouldApplyClipPath = true;
} else {
aUsage.shouldGenerateClipMaskLayer = true;
}
}
break;
case StyleShapeSourceType::Shape:
case StyleShapeSourceType::Box:
aUsage.shouldApplyBasicShape = true;
break;
case StyleShapeSourceType::None:
MOZ_ASSERT(!aUsage.shouldGenerateClipMaskLayer &&
!aUsage.shouldApplyClipPath && !aUsage.shouldApplyBasicShape);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unsupported clip-path type.");
break;
}
}
static IntRect
ComputeClipExtsInDeviceSpace(gfxContext& aCtx)
{
gfxContextMatrixAutoSaveRestore matRestore(&aCtx);
// Get the clip extents in device space.
aCtx.SetMatrix(gfxMatrix());
gfxRect clippedFrameSurfaceRect = aCtx.GetClipExtents();
clippedFrameSurfaceRect.RoundOut();
IntRect result;
ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
: IntRect();
}
static already_AddRefed<gfxContext>
CreateBlendTarget(gfxContext* aContext, IntPoint& aTargetOffset)
{
// Create a temporary context to draw to so we can blend it back with
// another operator.
IntRect drawRect = ComputeClipExtsInDeviceSpace(*aContext);
RefPtr<DrawTarget> targetDT =
aContext->GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(),
SurfaceFormat::B8G8R8A8);
if (!targetDT || !targetDT->IsValid()) {
return nullptr;
}
RefPtr<gfxContext> target = gfxContext::CreateOrNull(targetDT);
MOZ_ASSERT(target); // already checked the draw target above
target->SetMatrix(aContext->CurrentMatrix() *
gfxMatrix::Translation(-drawRect.TopLeft()));
aTargetOffset = drawRect.TopLeft();
return target.forget();
}
static void
BlendToTarget(nsIFrame* aFrame, gfxContext* aSource, gfxContext* aTarget,
const IntPoint& aTargetOffset)
{
MOZ_ASSERT(aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL);
RefPtr<DrawTarget> targetDT = aTarget->GetDrawTarget();
RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();
gfxContextAutoSaveRestore save(aSource);
aSource->SetMatrix(gfxMatrix()); // This will be restored right after.
RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(aTargetOffset.x, aTargetOffset.y));
aSource->SetPattern(pattern);
aSource->Paint();
}
DrawResult
nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
gfxContext& aContext,
@ -502,9 +635,11 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
if (!svgChildFrame)
return DrawResult::SUCCESS;
float opacity = aFrame->StyleEffects()->mOpacity;
if (opacity == 0.0f)
MaskUsage maskUsage;
DetermineMaskUsage(aFrame, true, maskUsage);
if (maskUsage.opacity == 0.0f) {
return DrawResult::SUCCESS;
}
const nsIContent* content = aFrame->GetContent();
if (content->IsSVGElement() &&
@ -512,14 +647,6 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
return DrawResult::SUCCESS;
}
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(aFrame);
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
if (aDirtyRect &&
!(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
// Here we convert aFrame's paint bounds to outer-<svg> device space,
@ -566,92 +693,82 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
*
* + Use cairo's clipPath when representable natively (single object
* clip region).
*
*f
* + Merge opacity and masking if both used together.
*/
if (opacity != 1.0f && CanOptimizeOpacity(aFrame))
opacity = 1.0f;
DrawTarget* drawTarget = aContext.GetDrawTarget();
bool complexEffects = false;
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(aFrame);
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
nsSVGMaskFrame *maskFrame = effectProperties.GetFirstMaskFrame(&isOK);
bool isTrivialClip = clipPathFrame ? clipPathFrame->IsTrivial() : true;
if (!isOK) {
// Some resource is invalid. We shouldn't paint anything.
return DrawResult::SUCCESS;
}
// These are used if we require a temporary surface for a custom blend mode.
RefPtr<gfxContext> target = &aContext;
// Clip the source context first, so that we can generate a smaller temporary
// surface. (Since we will clip this context in SetupContextMatrix, a pair
// of save/restore is needed.)
aContext.Save();
if (!(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
// aFrame has a valid visual overflow rect, so clip to it before calling
// PushGroup() to minimize the size of the surfaces we'll composite:
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&aContext);
aContext.Multiply(aTransform);
nsRect overflowRect = aFrame->GetVisualOverflowRectRelativeToSelf();
if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry) ||
aFrame->IsSVGText()) {
// Unlike containers, leaf frames do not include GetPosition() in
// GetCanvasTM().
overflowRect = overflowRect + aFrame->GetPosition();
}
aContext.Clip(NSRectToSnappedRect(overflowRect,
aFrame->PresContext()->AppUnitsPerDevPixel(),
*aContext.GetDrawTarget()));
}
IntPoint targetOffset;
RefPtr<gfxContext> target =
(aFrame->StyleEffects()->mMixBlendMode == NS_STYLE_BLEND_NORMAL)
? RefPtr<gfxContext>(&aContext).forget()
: CreateBlendTarget(&aContext, targetOffset);
aContext.Restore();
if (!target) {
return DrawResult::TEMPORARY_ERROR;
}
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
if (opacity != 1.0f || maskFrame || (clipPathFrame && !isTrivialClip)
|| aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
complexEffects = true;
bool shouldGenerateMask = (maskUsage.opacity != 1.0f ||
maskUsage.shouldGenerateClipMaskLayer ||
maskUsage.shouldGenerateMaskLayer ||
aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL);
if (shouldGenerateMask) {
Matrix maskTransform;
RefPtr<SourceSurface> maskSurface =
maskFrame ? maskFrame->GetMaskForMaskedFrame(&aContext,
aFrame, aTransform, opacity, &maskTransform)
: nullptr;
RefPtr<SourceSurface> maskSurface;
if (maskFrame && !maskSurface) {
// Entire surface is clipped out.
return DrawResult::SUCCESS;
if (maskUsage.shouldGenerateMaskLayer) {
maskSurface =
maskFrame->GetMaskForMaskedFrame(&aContext, aFrame, aTransform,
maskUsage.opacity, &maskTransform);
if (!maskSurface) {
// Entire surface is clipped out.
return DrawResult::SUCCESS;
}
}
aContext.Save();
if (!(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
// aFrame has a valid visual overflow rect, so clip to it before calling
// PushGroup() to minimize the size of the surfaces we'll composite:
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&aContext);
aContext.Multiply(aTransform);
nsRect overflowRect = aFrame->GetVisualOverflowRectRelativeToSelf();
if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry) ||
aFrame->IsSVGText()) {
// Unlike containers, leaf frames do not include GetPosition() in
// GetCanvasTM().
overflowRect = overflowRect + aFrame->GetPosition();
}
aContext.Clip(NSRectToSnappedRect(overflowRect,
aFrame->PresContext()->AppUnitsPerDevPixel(),
*drawTarget));
}
if (aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
// Create a temporary context to draw to so we can blend it back with
// another operator.
gfxRect clipRect;
{
gfxContextMatrixAutoSaveRestore matRestore(&aContext);
aContext.SetMatrix(gfxMatrix());
clipRect = aContext.GetClipExtents();
}
IntRect drawRect = RoundedOut(ToRect(clipRect));
RefPtr<DrawTarget> targetDT = aContext.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
target = gfxContext::CreateOrNull(targetDT);
if (!target) {
gfxDevCrash(LogReason::InvalidContext) << "SVGPaintWithEffects context problem " << gfx::hexa(targetDT);
return DrawResult::TEMPORARY_ERROR;
}
target->SetMatrix(aContext.CurrentMatrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
targetOffset = drawRect.TopLeft();
}
if (clipPathFrame && !isTrivialClip) {
if (maskUsage.shouldGenerateClipMaskLayer) {
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface = clipPathFrame->GetClipMask(aContext, aFrame, aTransform,
&clippedMaskTransform, maskSurface, maskTransform);
RefPtr<SourceSurface> clipMaskSurface =
clipPathFrame->GetClipMask(aContext, aFrame, aTransform,
&clippedMaskTransform, maskSurface,
maskTransform);
if (clipMaskSurface) {
maskSurface = clipMaskSurface;
@ -659,21 +776,22 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
}
}
if (maskFrame) {
target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 1.0,
maskSurface, maskTransform);
} else if (opacity != 1.0f || (clipPathFrame && !isTrivialClip)) {
target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity,
maskSurface, maskTransform);
}
// SVG mask multiply opacity into maskSurface already, so we do not bother
// to apply opacity again.
float opacity = maskFrame ? 1.0 : maskUsage.opacity;
target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity,
maskSurface, maskTransform);
}
/* If this frame has only a trivial clipPath, set up cairo's clipping now so
* we can just do normal painting and get it clipped appropriately.
*/
if (clipPathFrame && isTrivialClip) {
aContext.Save();
clipPathFrame->ApplyClipPath(aContext, aFrame, aTransform);
if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
if (maskUsage.shouldApplyClipPath) {
clipPathFrame->ApplyClipPath(aContext, aFrame, aTransform);
} else {
nsCSSClipPathInstance::ApplyBasicShapeClip(aContext, aFrame);
}
}
DrawResult result = DrawResult::SUCCESS;
@ -708,30 +826,19 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
result = svgChildFrame->PaintSVG(*target, aTransform, aDirtyRect);
}
if (clipPathFrame && isTrivialClip) {
aContext.Restore();
if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
aContext.PopClip();
}
/* No more effects, we're done. */
if (!complexEffects)
return result;
if (opacity != 1.0f || maskFrame || (clipPathFrame && !isTrivialClip)) {
if (shouldGenerateMask) {
target->PopGroupAndBlend();
}
if (aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
target = nullptr;
RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();
aContext.SetMatrix(gfxMatrix()); // This will be restored right after.
RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(targetOffset.x, targetOffset.y));
aContext.SetPattern(pattern);
aContext.Paint();
MOZ_ASSERT(target != &aContext);
BlendToTarget(aFrame, &aContext, target, targetOffset);
}
aContext.Restore();
return result;
}

Просмотреть файл

@ -576,6 +576,25 @@ public:
ToCanvasBounds(const gfxRect &aUserspaceRect,
const gfxMatrix &aToCanvas,
const nsPresContext *presContext);
struct MaskUsage {
bool shouldGenerateMaskLayer;
bool shouldGenerateClipMaskLayer;
bool shouldApplyClipPath;
bool shouldApplyBasicShape;
float opacity;
MaskUsage()
: shouldGenerateMaskLayer(false), shouldGenerateClipMaskLayer(false),
shouldApplyClipPath(false), shouldApplyBasicShape(false), opacity(0.0)
{ }
};
static void
DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity, MaskUsage& aUsage);
static float
ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity);
};
#endif

Просмотреть файл

@ -82,7 +82,7 @@ public:
// Constructors
RefPtr()
: mRawPtr(0)
: mRawPtr(nullptr)
// default constructor
{
}
@ -112,6 +112,11 @@ public:
}
}
MOZ_IMPLICIT RefPtr(decltype(nullptr))
: mRawPtr(nullptr)
{
}
template <typename I>
MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
: mRawPtr(aSmartPtr.take())
@ -155,6 +160,13 @@ public:
// Assignment operators
RefPtr<T>&
operator=(decltype(nullptr))
{
assign_assuming_AddRef(nullptr);
return *this;
}
RefPtr<T>&
operator=(const RefPtr<T>& aRhs)
// copy assignment operator
@ -243,7 +255,7 @@ public:
// return the value of mRawPtr and null out mRawPtr. Useful for
// already_AddRefed return values.
{
T* temp = 0;
T* temp = nullptr;
swap(temp);
return already_AddRefed<T>(temp);
}
@ -258,7 +270,7 @@ public:
{
MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
*aRhs = mRawPtr;
mRawPtr = 0;
mRawPtr = nullptr;
}
T*
@ -303,7 +315,7 @@ public:
T*
operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
{
MOZ_ASSERT(mRawPtr != 0,
MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator->().");
return get();
}
@ -330,7 +342,7 @@ public:
template <typename R, typename... Args>
Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const
{
MOZ_ASSERT(mRawPtr != 0,
MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator->*().");
return Proxy<R, Args...>(get(), aFptr);
}
@ -355,7 +367,7 @@ public:
T&
operator*() const
{
MOZ_ASSERT(mRawPtr != 0,
MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator*().");
return *get();
}
@ -363,7 +375,7 @@ public:
T**
StartAssignment()
{
assign_assuming_AddRef(0);
assign_assuming_AddRef(nullptr);
return reinterpret_cast<T**>(&mRawPtr);
}
private:

Просмотреть файл

@ -24,6 +24,7 @@ import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
@ -88,7 +89,8 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
"MediaPlayer:Mirror",
"MediaPlayer:Message",
"AndroidCastDevice:Start",
"AndroidCastDevice:Stop");
"AndroidCastDevice:Stop",
"AndroidCastDevice:SyncDevice");
}
@Override
@ -105,7 +107,8 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
"MediaPlayer:Mirror",
"MediaPlayer:Message",
"AndroidCastDevice:Start",
"AndroidCastDevice:Stop");
"AndroidCastDevice:Stop",
"AndroidCastDevice:SyncDevice");
}
// GeckoEventListener implementation
@ -145,16 +148,29 @@ public class MediaPlayerManager extends Fragment implements NativeEventListener
}
if (event.startsWith("AndroidCastDevice:")) {
final GeckoPresentationDisplay display = displays.get(message.getString("id"));
if (display == null) {
Log.e(LOGTAG, "Couldn't find a display for this id: " + message.getString("id") + " for message: " + event);
return;
}
if ("AndroidCastDevice:Start".equals(event)) {
final GeckoPresentationDisplay display = displays.get(message.getString("id"));
if (display == null) {
Log.e(LOGTAG, "Couldn't find a display for this id: " + message.getString("id") + " for message: " + event);
return;
}
display.start(callback);
} else if ("AndroidCastDevice:Stop".equals(event)) {
final GeckoPresentationDisplay display = displays.get(message.getString("id"));
if (display == null) {
Log.e(LOGTAG, "Couldn't find a display for this id: " + message.getString("id") + " for message: " + event);
return;
}
display.stop(callback);
} else if ("AndroidCastDevice:SyncDevice".equals(event)) {
for (Map.Entry<String, GeckoPresentationDisplay> entry : displays.entrySet()) {
GeckoPresentationDisplay display = entry.getValue();
JSONObject json = display.toJSON();
if (json == null) {
break;
}
GeckoAppShell.notifyObservers("AndroidCastDevice:Added", json.toString());
}
}
}
}

Просмотреть файл

@ -1,3 +1,5 @@
/* -*- Mode: tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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/. */
@ -5,6 +7,10 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const TOPIC_PRESENTATION_VIEW_READY = "presentation-view-ready";
const TOPIC_PRESENTATION_RECEIVER_LAUNCH = "presentation-receiver:launch";
const TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE = "presentation-receiver:launch:response";
// globals Services
Cu.import("resource://gre/modules/Services.jsm");
@ -18,5 +24,40 @@ let PresentationView = {
startup: function startup() {
// use hash as the ID of this top level window
this._id = window.location.hash.substr(1);
// Listen "presentation-receiver:launch" sent from
// PresentationRequestUIGlue.
Services.obs.addObserver(this,TOPIC_PRESENTATION_RECEIVER_LAUNCH, false);
// Notify PresentationView is ready.
Services.obs.notifyObservers(null, TOPIC_PRESENTATION_VIEW_READY, this._id);
},
stop: function stop() {
Services.obs.removeObserver(this, TOPIC_PRESENTATION_RECEIVER_LAUNCH);
},
observe: function observe(aSubject, aTopic, aData) {
log("Got observe: aTopic=" + aTopic);
let requestData = JSON.parse(aData);
if (this._id != requestData.windowId) {
return;
}
let browser = document.getElementById("content");
browser.setAttribute("mozpresentation", requestData.url);
try {
browser.loadURI(requestData.url);
Services.obs.notifyObservers(browser,
TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE,
JSON.stringify({ result: "success",
requestId: requestData.requestId }));
} catch (e) {
Services.obs.notifyObservers(null,
TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE,
JSON.stringify({ result: "error",
reason: e.message }));
}
}
};

Просмотреть файл

@ -5,6 +5,7 @@
<window id="presentation-window"
onload="PresentationView.startup();"
onunload="PresentationView.stop();"
windowtype="navigator:browser"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

Просмотреть файл

@ -46,6 +46,10 @@ contract @mozilla.org/network/authprompt-adapter-factory;1 {80dae1e9-e0d2-4974-9
component {388bd149-c919-4a43-b646-d7ec57877689} PresentationDevicePrompt.js
contract @mozilla.org/presentation-device/prompt;1 {388bd149-c919-4a43-b646-d7ec57877689}
# PresentationRequestUIGlue.js
component {9c550ef7-3ff6-4bd1-9ad1-5a3735b90d21} PresentationRequestUIGlue.js
contract @mozilla.org/presentation/requestuiglue;1 {9c550ef7-3ff6-4bd1-9ad1-5a3735b90d21}
# ImageBlockingPolicy.js
component {f55f77f9-d33d-4759-82fc-60db3ee0bb91} ImageBlockingPolicy.js
contract @mozilla.org/browser/blockimages-policy;1 {f55f77f9-d33d-4759-82fc-60db3ee0bb91}

Просмотреть файл

@ -0,0 +1,86 @@
/* -*- Mode: tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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"
const { interfaces: Ci, utils: Cu, classes: Cc } = Components;
const TOPIC_PRESENTATION_RECEIVER_LAUNCH = "presentation-receiver:launch";
const TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE = "presentation-receiver:launch:response";
// globals XPCOMUtils
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// globals Services
Cu.import("resource://gre/modules/Services.jsm");
function log(str) {
// dump("-*- PresentationRequestUIGlue.js -*-: " + str + "\n");
}
function PresentationRequestUIGlue() { }
PresentationRequestUIGlue.prototype = {
sendRequest: function sendRequest(aURL, aSessionId, aDevice) {
log("PresentationRequestUIGlue - sendRequest aURL=" + aURL +
" aSessionId=" + aSessionId);
let localDevice;
try {
localDevice = aDevice.QueryInterface(Ci.nsIPresentationLocalDevice);
} catch (e) {
/* XXX: Currently, Fennec only support 1-UA devices. Remove this
* Promise.reject() when it starts to support 2-UA devices.
*/
log("Not an 1-UA device.")
return new Promise.reject();
}
return new Promise((aResolve, aReject) => {
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
let requestId = uuidGenerator.generateUUID().toString();
let handleObserve = (aSubject, aTopic, aData) => {
log("Got observe: aTopic=" + aTopic);
let data = JSON.parse(aData);
if (data.requestId != requestId) {
return;
}
Services.obs.removeObserver(handleObserve,
TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE);
switch(data.result) {
case "success":
aResolve(aSubject);
break;
case "error":
aReject();
break;
};
};
Services.obs.addObserver(handleObserve,
TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE,
false);
let data = {
url: aURL,
windowId: localDevice.windowId,
requestId: requestId
};
Services.obs.notifyObservers(null,
TOPIC_PRESENTATION_RECEIVER_LAUNCH,
JSON.stringify(data));
})
},
classID: Components.ID("9c550ef7-3ff6-4bd1-9ad1-5a3735b90d21"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationRequestUIGlue])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationRequestUIGlue]);

Просмотреть файл

@ -27,6 +27,7 @@ EXTRA_COMPONENTS += [
'NSSDialogService.js',
'PersistentNotificationHandler.js',
'PresentationDevicePrompt.js',
'PresentationRequestUIGlue.js',
'PromptService.js',
'SessionStore.js',
'SiteSpecificUserAgent.js',

Просмотреть файл

@ -1,4 +1,3 @@
; 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/.
@ -405,6 +404,8 @@
@BINPATH@/components/PresentationDataChannelSessionTransport.manifest
@BINPATH@/components/LegacyProviders.manifest
@BINPATH@/components/LegacyPresentationControlService.js
@BINPATH@/components/AndroidCastDeviceProvider.manifest
@BINPATH@/components/AndroidCastDeviceProvider.js
@BINPATH@/components/TVSimulatorService.js
@BINPATH@/components/TVSimulatorService.manifest
@ -531,6 +532,7 @@
@BINPATH@/components/NSSDialogService.js
@BINPATH@/components/PersistentNotificationHandler.js
@BINPATH@/components/PresentationDevicePrompt.js
@BINPATH@/components/PresentationRequestUIGlue.js
@BINPATH@/components/PromptService.js
@BINPATH@/components/SessionStore.js
@BINPATH@/components/SiteSpecificUserAgent.js

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше