merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-07-08 14:41:21 +02:00
Родитель 199935117b e916eb8d72
Коммит 0def8508d2
250 изменённых файлов: 3402 добавлений и 2493 удалений

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

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
b=1010371; ANGLE update. Files got moved around, needs a clobber to fix.
bug 940506: removing idl files appears to break the build without a clobber

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

@ -250,9 +250,26 @@ MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
export MOZ_SOURCE_STAMP
endif
.PHONY: update-packaging
update-packaging:
$(MAKE) -C tools/update-packaging
.PHONY: pretty-package
pretty-package:
$(MAKE) package MOZ_PKG_PRETTYNAMES=1
.PHONY: pretty-package-tests
pretty-package-tests:
$(MAKE) package-tests MOZ_PKG_PRETTYNAMES=1
.PHONY: pretty-l10n-check
pretty-l10n-check:
$(MAKE) l10n-check MOZ_PKG_PRETTYNAMES=1
.PHONY: pretty-update-packaging
pretty-update-packaging:
$(MAKE) -C tools/update-packaging MOZ_PKG_PRETTYNAMES=1
#XXX: this is a hack, since we don't want to clobber for MSVC
# PGO support, but we can't do this test in client.mk
ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)

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

@ -81,6 +81,14 @@ def print_header_file(fd, conf):
fd.write(" %s\n" % attributeVariableTypeAndName(a))
fd.write("};\n\n")
fd.write("namespace mozilla {\n"
"template<>\n"
"struct HasDangerousPublicDestructor<%s>\n"
"{\n"
" static const bool value = true;\n"
"};\n"
"}\n" % classname)
fd.write("#endif\n")
def interfaceAttributeTypes(idl):

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

@ -991,10 +991,8 @@ pref("touchcaret.enabled", false);
pref("selectioncaret.enabled", false);
// Enable sync and mozId with Firefox Accounts.
#ifdef MOZ_SERVICES_FXACCOUNTS
pref("services.sync.fxaccounts.enabled", true);
pref("identity.fxaccounts.enabled", true);
#endif
// Mobile Identity API.
pref("services.mobileid.server.uri", "https://msisdn-dev.stage.mozaws.net");

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

@ -19,7 +19,7 @@ if not CONFIG['LIBXUL_SDK']:
DEFINES['XPCOM_GLUE'] = True
for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION', 'MOZ_UPDATER', 'MOZ_SERVICES_FXACCOUNTS'):
for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION', 'MOZ_UPDATER'):
DEFINES[var] = CONFIG[var]
GENERATED_INCLUDES += [

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

@ -26,10 +26,7 @@ Cu.import('resource://gre/modules/ResourceStatsService.jsm');
Cu.import('resource://gre/modules/SignInToWebsite.jsm');
SignInToWebsiteController.init();
#ifdef MOZ_SERVICES_FXACCOUNTS
Cu.import('resource://gre/modules/FxAccountsMgmtService.jsm');
#endif
Cu.import('resource://gre/modules/DownloadsAPI.jsm');
Cu.import('resource://gre/modules/MobileIdentityManager.jsm');

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

@ -80,11 +80,9 @@ component {637b0f77-2429-49a0-915f-abf5d0db8b9a} WebappsUpdateTimer.js
contract @mozilla.org/b2g/webapps-update-timer;1 {637b0f77-2429-49a0-915f-abf5d0db8b9a}
category update-timer WebappsUpdateTimer @mozilla.org/b2g/webapps-update-timer;1,getService,background-update-timer,webapps.update.interval,86400
#ifdef MOZ_SERVICES_FXACCOUNTS
# FxAccountsUIGlue.js
component {51875c14-91d7-4b8c-b65d-3549e101228c} FxAccountsUIGlue.js
contract @mozilla.org/fxaccounts/fxaccounts-ui-glue;1 {51875c14-91d7-4b8c-b65d-3549e101228c}
#endif
# HelperAppDialog.js
component {710322af-e6ae-4b0c-b2c9-1474a87b077e} HelperAppDialog.js

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

@ -12,6 +12,7 @@ EXTRA_COMPONENTS += [
'B2GAboutRedirector.js',
'ContentPermissionPrompt.js',
'FilePicker.js',
'FxAccountsUIGlue.js',
'HelperAppDialog.js',
'InterAppCommUIGlue.js',
'MailtoProtocolHandler.js',
@ -48,6 +49,7 @@ EXTRA_JS_MODULES += [
'AppFrames.jsm',
'ContentRequestHelper.jsm',
'ErrorPage.jsm',
'FxAccountsMgmtService.jsm',
'SignInToWebsite.jsm',
'SystemAppProxy.jsm',
'TelURIParser.jsm',
@ -58,11 +60,3 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
EXTRA_JS_MODULES += [
'GlobalSimulatorScreen.jsm'
]
if CONFIG['MOZ_SERVICES_FXACCOUNTS']:
EXTRA_COMPONENTS += [
'FxAccountsUIGlue.js'
]
EXTRA_JS_MODULES += [
'FxAccountsMgmtService.jsm'
]

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

@ -64,8 +64,6 @@ MOZ_FOLD_LIBS=1
MOZ_JSDOWNLOADS=1
MOZ_SERVICES_FXACCOUNTS=1
MOZ_BUNDLED_FONTS=1
# Enable exact rooting on b2g.

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

@ -832,10 +832,8 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/components/SimulatorScreen.js
#endif
#ifdef MOZ_SERVICES_FXACCOUNTS
@BINPATH@/components/FxAccountsUIGlue.js
@BINPATH@/components/services_fxaccounts.xpt
#endif
@BINPATH@/components/DataStore.manifest
@BINPATH@/components/DataStoreImpl.js

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

@ -2313,7 +2313,8 @@ let BrowserOnClick = {
switch (msg.name) {
case "Browser:CertExceptionError":
this.onAboutCertError(msg.target, msg.json.elementId,
msg.json.isTopFrame, msg.json.location);
msg.json.isTopFrame, msg.json.location,
msg.objects.failedChannel);
break;
case "Browser:SiteBlockedError":
this.onAboutBlocked(msg.json.elementId, msg.json.isMalware,
@ -2326,19 +2327,16 @@ let BrowserOnClick = {
}
},
onAboutCertError: function (browser, elementId, isTopFrame, location) {
onAboutCertError: function (browser, elementId, isTopFrame, location, failedChannel) {
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
switch (elementId) {
case "exceptionDialogButton":
let docshell = aOwnerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let securityInfo = docshell.failedChannel.securityInfo;
let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider).SSLStatus;
if (isTopFrame) {
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_CLICK_ADD_EXCEPTION);
}
let sslStatus = failedChannel.securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
.SSLStatus;
let params = { exceptionAdded : false,
sslStatus : sslStatus };

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

@ -307,10 +307,15 @@ let ClickEventHandler = {
},
onAboutCertError: function (targetElement, ownerDoc) {
let docshell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
sendAsyncMessage("Browser:CertExceptionError", {
location: ownerDoc.location.href,
elementId: targetElement.getAttribute("id"),
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView)
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
}, {
failedChannel: docshell.failedChannel
});
},

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

@ -426,3 +426,5 @@ skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHan
skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
[browser_bug1003461-switchtab-override.js]
[browser_bug1025195_switchToTabHavingURI_ignoreFragment.js]
[browser_addCertException.js]
skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById)

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

@ -0,0 +1,104 @@
/* -*- 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/. */
// Test adding a certificate exception by attempting to browse to a site with
// a bad certificate, being redirected to the internal about:certerror page,
// using the button contained therein to load the certificate exception
// dialog, using that to add an exception, and finally successfully visiting
// the site.
function test() {
waitForExplicitFinish();
whenNewTabLoaded(window, loadBadCertPage);
}
// Attempt to load https://expired.example.com (which has an expired cert).
function loadBadCertPage() {
gBrowser.addProgressListener(certErrorProgressListener);
gBrowser.selectedBrowser.loadURI("https://expired.example.com");
}
// The browser should load about:certerror. When This happens, click the
// button to open the certificate exception dialog.
let certErrorProgressListener = {
buttonClicked: false,
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
let self = this;
// Can't directly call button.click() in onStateChange
executeSoon(function() {
let button = content.document.getElementById("exceptionDialogButton");
// If about:certerror hasn't fully loaded, the button won't be present.
// It will eventually be there, however.
if (button && !self.buttonClicked) {
gBrowser.removeProgressListener(self);
Services.obs.addObserver(certExceptionDialogObserver,
"cert-exception-ui-ready", false);
button.click();
}
});
}
}
};
// When the certificate exception dialog has opened, click the button to add
// an exception.
const EXCEPTION_DIALOG_URI = "chrome://pippki/content/exceptionDialog.xul";
let certExceptionDialogObserver = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "cert-exception-ui-ready") {
Services.obs.removeObserver(this, "cert-exception-ui-ready");
let certExceptionDialog = getDialog(EXCEPTION_DIALOG_URI);
ok(certExceptionDialog, "found exception dialog");
executeSoon(function() {
gBrowser.selectedBrowser.addEventListener("load",
successfulLoadListener,
true);
certExceptionDialog.documentElement.getButton("extra1").click();
});
}
}
};
// Finally, we should successfully load https://expired.example.com.
let successfulLoadListener = {
handleEvent: function() {
gBrowser.selectedBrowser.removeEventListener("load", this, true);
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
certOverrideService.clearValidityOverride("expired.example.com", -1);
gBrowser.removeTab(gBrowser.selectedTab);
finish();
}
};
// Utility function to get a handle on the certificate exception dialog.
// Modified from toolkit/components/passwordmgr/test/prompt_common.js
function getDialog(aLocation) {
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
let enumerator = wm.getXULWindowEnumerator(null);
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
let containedDocShells = windowDocShell.getDocShellEnumerator(
Ci.nsIDocShellTreeItem.typeChrome,
Ci.nsIDocShell.ENUMERATE_FORWARDS);
while (containedDocShells.hasMoreElements()) {
// Get the corresponding document for this docshell
let childDocShell = containedDocShells.getNext();
let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
.contentViewer
.DOMDocument;
if (childDoc.location.href == aLocation) {
return childDoc;
}
}
}
}

2
browser/components/loop/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
.module-cache
standalone/content/config.js

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

@ -1,21 +1,32 @@
This is the directory for the Loop desktop implementation and the standalone client.
This is the directory for the Loop desktop implementation and the standalone
client.
The desktop implementation is the UX built into Firefox, activated by the Loop button on the toolbar. The standalone client is the link-clicker UX for any modern browser that supports WebRTC.
The desktop implementation is the UX built into Firefox, activated by the Loop
button on the toolbar. The standalone client is the link-clicker UX for any
modern browser that supports WebRTC.
The standalone client is a set of web pages intended to be hosted on a standalone server referenced by the loop-server.
The standalone client is a set of web pages intended to be hosted on a
standalone server referenced by the loop-server.
The standalone client exists in standalone/ but shares items
(from content/shared/) with the desktop implementation. See the README.md
file in the standalone/ directory for how to run the server locally.
The standalone client exists in standalone/ but shares items (from content/shared/) with the desktop implementation. See the README.md file in the standalone/ directory for how to run the server locally.
Working with JSX
================
You need to install the JSX compiler in order to compile the .jsx files into regular .js ones.
The JSX compiler is installable using npm:
You need to install the JSX compiler using npm in order to compile the .jsx
files into regular .js ones:
npm install -g react-tools
Once installed, run it with the --watch option, eg.:
Once installed, run build-jsx with the --watch option from
browser/components/loop, eg.:
jsx --watch --x jsx browser/components/loop/content/js/src \
browser/components/loop/content/js
cd browser/components/loop
./build-jsx --watch
build-jsx can also be do a one-time compile pass instead of watching if
the --watch argument is omitted. Be sure to commit any transpiled files
at the same time as changes to their sources.

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

@ -0,0 +1,89 @@
#! /usr/bin/env python
import os
from distutils import spawn
import subprocess
from threading import Thread
import argparse
src_files = [] # files to be compiled
# search for react-tools install
jsx_path = spawn.find_executable('jsx')
if jsx_path is None:
print 'You do not have the react-tools installed'
print 'Please do $ npm install -g react-tools'
exit(1)
# parse the CLI arguments
description = 'Loop build tool for JSX files. ' + \
'Will scan entire loop directory and compile them in place. ' + \
'Must be executed from browser/components/loop directory.'
parser = argparse.ArgumentParser(description=description)
parser.add_argument('--watch', '-w', action='store_true', help='continuous' +
'build based on file changes (optional)')
args = parser.parse_args()
# loop through all tuples and get unique dirs only
unique_jsx_dirs = []
# find all .jsx files
for dirname, dirnames, filenames in os.walk('.'):
for filename in filenames:
if '.jsx' == os.path.splitext(filename)[1]: # (root, ext)
src_files.append(filename)
if dirname not in unique_jsx_dirs:
unique_jsx_dirs.append(dirname)
def jsx_run_watcher(path):
subprocess.call(['jsx', '-w', '-x', 'jsx', path, path])
def start_jsx_watcher_threads(dirs):
"""
starts a thread with a jsx watch process
for every dir in the dirs argument
"""
threads = []
for udir in dirs:
t = Thread(target=jsx_run_watcher, args=(udir,))
threads.append(t)
t.start()
for t in threads:
t.join()
def check_file_packaging(srcs):
"""
get all lines from jar.mn file
check against the files we are going to compile.
Note that this only looks at filenames, and will miss
the one of two identically named files.
"""
# get all lines from jar.mn
packaged_files = [line.strip() for line in open('./jar.mn')]
# loop through our compiled files and compare against jar.mn
# XXX fix to use paths so that identically named files don't get overlooked
# and update the docstring for this function
missing_jar_files = [] # initially empty
for src_file in srcs:
transpiled_file = os.path.splitext(src_file)[0] + ".js" # (root, ext)
if not any(transpiled_file in x for x in packaged_files):
missing_jar_files.append(transpiled_file)
# output a message to the user
if len(missing_jar_files):
for f in missing_jar_files:
print f + ' not in jar.mn file'
check_file_packaging(src_files)
if args.watch:
start_jsx_watcher_threads(unique_jsx_dirs)
else:
for d in unique_jsx_dirs:
out = subprocess.call(['jsx', '-x', 'jsx', d, d])

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

@ -1,3 +1,7 @@
MOZ_AUTOMATION_UPLOAD=0
MOZ_AUTOMATION_UNITTEST_SENDCHANGE=0
MOZ_AUTOMATION_CHECK=0
. "$topsrcdir/browser/config/mozconfigs/linux64/debug"
ac_add_options --disable-unified-compilation

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

@ -2,6 +2,7 @@ MOZ_AUTOMATION_UPLOAD=0
MOZ_AUTOMATION_UNITTEST_SENDCHANGE=0
MOZ_AUTOMATION_TALOS_SENDCHANGE=0
MOZ_AUTOMATION_CHECK=0
MOZ_AUTOMATION_PRETTY=1
. "$topsrcdir/browser/config/mozconfigs/linux64/nightly"

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

@ -28,7 +28,6 @@ MOZ_DISABLE_EXPORT_JS=1
MOZ_SAFE_BROWSING=1
MOZ_SERVICES_COMMON=1
MOZ_SERVICES_CRYPTO=1
MOZ_SERVICES_FXACCOUNTS=1
MOZ_SERVICES_HEALTHREPORT=1
MOZ_SERVICES_METRICS=1
MOZ_SERVICES_SYNC=1

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

@ -22,9 +22,13 @@ AUTOMATION_UPLOAD_OUTPUT = $(DIST)/automation-upload.txt
tier_BUILD_SYMBOLS = buildsymbols
tier_CHECK = check
tier_L10N_CHECK = l10n-check
tier_PRETTY_L10N_CHECK = pretty-l10n-check
tier_PACKAGE = package
tier_PRETTY_PACKAGE = pretty-package
tier_PACKAGE_TESTS = package-tests
tier_PRETTY_PACKAGE_TESTS = pretty-package-tests
tier_UPDATE_PACKAGING = update-packaging
tier_PRETTY_UPDATE_PACKAGING = pretty-update-packaging
tier_UPLOAD_SYMBOLS = uploadsymbols
tier_UPLOAD = upload
@ -32,7 +36,20 @@ tier_UPLOAD = upload
# TIERS for mach display. As such, the MOZ_AUTOMATION_TIERS are roughly sorted
# here in the order that they will be executed (since mach doesn't know of the
# dependencies between them).
moz_automation_symbols = PACKAGE_TESTS BUILD_SYMBOLS UPLOAD_SYMBOLS PACKAGE UPDATE_PACKAGING CHECK L10N_CHECK UPLOAD
moz_automation_symbols = \
PACKAGE_TESTS \
PRETTY_PACKAGE_TESTS \
BUILD_SYMBOLS \
UPLOAD_SYMBOLS \
PACKAGE \
PRETTY_PACKAGE \
UPDATE_PACKAGING \
PRETTY_UPDATE_PACKAGING \
CHECK \
L10N_CHECK \
PRETTY_L10N_CHECK \
UPLOAD \
$(NULL)
MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$(MOZ_AUTOMATION_$(sym))),$(tier_$(sym))))
# Dependencies between automation build steps
@ -53,6 +70,13 @@ automation/upload: automation/update-packaging
automation/package: automation/buildsymbols
automation/check: automation/buildsymbols
# The 'pretty' versions of targets run before the regular ones to avoid
# conflicts in writing to the same files.
automation/package: automation/pretty-package
automation/package-tests: automation/pretty-package-tests
automation/l10n-check: automation/pretty-l10n-check
automation/update-packaging: automation/pretty-update-packaging
automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
$(PYTHON) $(topsrcdir)/build/gen_mach_buildprops.py --complete-mar-file $(DIST)/$(COMPLETE_MAR) --upload-output $(AUTOMATION_UPLOAD_OUTPUT)

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

@ -19,3 +19,15 @@ mk_add_options "export MOZ_AUTOMATION_UNITTEST_SENDCHANGE=${MOZ_AUTOMATION_UNITT
mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}"
mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}"
mk_add_options "export MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-0}"
# If we are also building with MOZ_PKG_PRETTYNAMES, set the corresponding
# stages.
if test "$MOZ_AUTOMATION_PRETTY" = "1"; then
mk_add_options "export MOZ_AUTOMATION_PRETTY_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}"
mk_add_options "export MOZ_AUTOMATION_PRETTY_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-1}"
mk_add_options "export MOZ_AUTOMATION_PRETTY_L10N_CHECK=${MOZ_AUTOMATION_L10N_CHECK-1}"
# Note that we always build the update packaging with pretty names even if
# we don't build it without, so this is set to 1.
mk_add_options "export MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING=1"
fi

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

@ -7551,14 +7551,6 @@ if test -n "$MOZ_AUDIO_CHANNEL_MANAGER"; then
fi
AC_SUBST(MOZ_AUDIO_CHANNEL_MANAGER)
dnl ========================================================
dnl = Enable Support for Firefox Accounts (services/fxaccounts)
dnl ========================================================
if test -n "$MOZ_SERVICES_FXACCOUNTS"; then
AC_DEFINE(MOZ_SERVICES_FXACCOUNTS)
fi
AC_SUBST(MOZ_SERVICES_FXACCOUNTS)
dnl ========================================================
dnl = Support for demangling undefined symbols
dnl ========================================================

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

@ -17,7 +17,7 @@ interface nsIPrincipal;
* one of these per document/principal.
*/
[scriptable, uuid(1ae83090-e1e1-4272-b0c4-0fbd751c1e27)]
[scriptable, uuid(15c409c5-ebf8-457c-a8dd-5b169ca0b218)]
interface nsIContentSecurityPolicy : nsISerializable
{
@ -55,13 +55,9 @@ interface nsIContentSecurityPolicy : nsISerializable
* @param reportOnly
* Should this policy affect content, script and style processing or
* just send reports if it is violated?
* @param specCompliant
* Whether or not the policy conforms to the W3C specification.
* If this is false, that indicates this policy is from the older
* implementation with different semantics and directive names.
*/
void appendPolicy(in AString policyString, in nsIURI selfURI,
in boolean reportOnly, in boolean specCompliant);
in boolean reportOnly);
/**
* Whether this policy allows in-page script.

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

@ -192,8 +192,7 @@ CSPPolicyURIListener.prototype = {
if (Components.isSuccessCode(status)) {
// send the policy we received back to the parent document's CSP
// for parsing
this._csp.appendPolicy(this._policy, this._docURI,
this._reportOnly, true);
this._csp.appendPolicy(this._policy, this._docURI, this._reportOnly);
}
else {
// problem fetching policy so fail closed by appending a "block it all"
@ -201,8 +200,7 @@ CSPPolicyURIListener.prototype = {
// this policy is used.
this._csp.log(WARN_FLAG, CSPLocalizer.getFormatStr("errorFetchingPolicy",
[status]));
this._csp.appendPolicy("default-src 'none'", this._docURI,
this._reportOnly, true);
this._csp.appendPolicy("default-src 'none'", this._docURI, this._reportOnly);
}
// resume the parent document request
this._docRequest.resume();
@ -228,7 +226,7 @@ this.CSPRep = function CSPRep() {
this._directives = {};
}
// Source directives for our CSP 1.0 spec compliant implementation.
// Source directives for our CSP 1.0 implementation.
CSPRep.SRC_DIRECTIVES = {
DEFAULT_SRC: "default-src",
SCRIPT_SRC: "script-src",

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

@ -385,7 +385,7 @@ ContentSecurityPolicy.prototype = {
* @returns the count of policies.
*/
appendPolicy:
function csp_appendPolicy(aPolicy, selfURI, aReportOnly, aSpecCompliant) {
function csp_appendPolicy(aPolicy, selfURI, aReportOnly) {
return this._appendPolicyInternal(aPolicy, selfURI, aReportOnly, true);
},

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

@ -286,8 +286,7 @@ nsCSPContext::RemovePolicy(uint32_t aIndex)
NS_IMETHODIMP
nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
nsIURI* aSelfURI,
bool aReportOnly,
bool aSpecCompliant)
bool aReportOnly)
{
CSPCONTEXTLOG(("nsCSPContext::AppendPolicy: %s",
NS_ConvertUTF16toUTF8(aPolicyString).get()));
@ -1215,16 +1214,6 @@ nsCSPContext::Read(nsIObjectInputStream* aStream)
rv = aStream->ReadBoolean(&reportOnly);
NS_ENSURE_SUCCESS(rv, rv);
bool specCompliant = false;
rv = aStream->ReadBoolean(&specCompliant);
NS_ENSURE_SUCCESS(rv, rv);
// Using the new backend, we don't support non-spec-compliant policies, so
// skip any of those, will be fixed in bug 991466
if (!specCompliant) {
continue;
}
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(policyString,
mSelfURI,
reportOnly,
@ -1254,8 +1243,6 @@ nsCSPContext::Write(nsIObjectOutputStream* aStream)
mPolicies[p]->toString(polStr);
aStream->WriteWStringZ(polStr.get());
aStream->WriteBoolean(mPolicies[p]->getReportOnlyFlag());
// Setting specCompliant boolean for backwards compatibility (fix in bug 991466)
aStream->WriteBoolean(true);
}
return NS_OK;
}

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

@ -665,7 +665,8 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
const nsSubstring& aRel, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aMedia)
{
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aRel);
uint32_t linkTypes =
nsStyleLinkElement::ParseLinkTypes(aRel, mDocument->NodePrincipal());
// The link relation may apply to a different resource, specified
// in the anchor parameter. For the link relations supported so far,

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

@ -2640,7 +2640,7 @@ nsDocument::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages)
static nsresult
AppendCSPFromHeader(nsIContentSecurityPolicy* csp, const nsAString& aHeaderValue,
nsIURI* aSelfURI, bool aReportOnly, bool aSpecCompliant)
nsIURI* aSelfURI, bool aReportOnly)
{
// Need to tokenize the header value since multiple headers could be
// concatenated into one comma-separated list of policies.
@ -2649,7 +2649,7 @@ AppendCSPFromHeader(nsIContentSecurityPolicy* csp, const nsAString& aHeaderValue
nsCharSeparatedTokenizer tokenizer(aHeaderValue, ',');
while (tokenizer.hasMoreTokens()) {
const nsSubstring& policy = tokenizer.nextToken();
rv = csp->AppendPolicy(policy, aSelfURI, aReportOnly, aSpecCompliant);
rv = csp->AppendPolicy(policy, aSelfURI, aReportOnly);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef PR_LOGGING
{
@ -2798,24 +2798,24 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
if (appCSP) {
csp->AppendPolicy(appCSP, selfURI, false, true);
csp->AppendPolicy(appCSP, selfURI, false);
}
}
// ----- if the doc is an app and specifies a CSP in its manifest, apply it.
if (applyAppManifestCSP) {
csp->AppendPolicy(appManifestCSP, selfURI, false, true);
csp->AppendPolicy(appManifestCSP, selfURI, false);
}
// ----- if there's a full-strength CSP header, apply it.
if (!cspHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspHeaderValue, selfURI, false, true);
rv = AppendCSPFromHeader(csp, cspHeaderValue, selfURI, false);
NS_ENSURE_SUCCESS(rv, rv);
}
// ----- if there's a report-only CSP header, apply it.
if (!cspROHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspROHeaderValue, selfURI, true, true);
rv = AppendCSPFromHeader(csp, cspROHeaderValue, selfURI, true);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -5445,7 +5445,7 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
}
bool
nsDocument::IsRegisterElementEnabled(JSContext* aCx, JSObject* aObject)
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
JS::Rooted<JSObject*> obj(aCx, aObject);
return Preferences::GetBool("dom.webcomponents.enabled") ||

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

@ -1479,7 +1479,7 @@ public:
uint32_t aNamespaceID,
mozilla::ErrorResult& rv);
static bool IsRegisterElementEnabled(JSContext* aCx, JSObject* aObject);
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
// The "registry" from the web components spec.
nsRefPtr<mozilla::dom::Registry> mRegistry;

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

@ -120,21 +120,30 @@ nsStyleLinkElement::SetLineNumber(uint32_t aLineNumber)
}
/* static */ bool
nsStyleLinkElement::IsImportEnabled()
nsStyleLinkElement::IsImportEnabled(nsIPrincipal* aPrincipal)
{
static bool sAdded = false;
static bool sImportEnabled;
static bool sWebComponentsEnabled;
if (!sAdded) {
// This part runs only once because of the static flag.
Preferences::AddBoolVarCache(&sImportEnabled,
Preferences::AddBoolVarCache(&sWebComponentsEnabled,
"dom.webcomponents.enabled",
false);
sAdded = true;
}
return sImportEnabled;
if (sWebComponentsEnabled) {
return true;
}
// If the web components pref is not enabled, check
// if we are in a certified app because imports is enabled
// for certified apps.
return aPrincipal &&
aPrincipal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED;
}
static uint32_t ToLinkMask(const nsAString& aLink)
static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
{
if (aLink.EqualsLiteral("prefetch"))
return nsStyleLinkElement::ePREFETCH;
@ -146,13 +155,14 @@ static uint32_t ToLinkMask(const nsAString& aLink)
return nsStyleLinkElement::eNEXT;
else if (aLink.EqualsLiteral("alternate"))
return nsStyleLinkElement::eALTERNATE;
else if (aLink.EqualsLiteral("import") && nsStyleLinkElement::IsImportEnabled())
else if (aLink.EqualsLiteral("import") && aPrincipal &&
nsStyleLinkElement::IsImportEnabled(aPrincipal))
return nsStyleLinkElement::eHTMLIMPORT;
else
return 0;
}
uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes, nsIPrincipal* aPrincipal)
{
uint32_t linkMask = 0;
nsAString::const_iterator start, done;
@ -169,7 +179,7 @@ uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
if (nsContentUtils::IsHTMLWhitespace(*current)) {
if (inString) {
nsContentUtils::ASCIIToLower(Substring(start, current), subString);
linkMask |= ToLinkMask(subString);
linkMask |= ToLinkMask(subString, aPrincipal);
inString = false;
}
}
@ -183,7 +193,7 @@ uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
}
if (inString) {
nsContentUtils::ASCIIToLower(Substring(start, current), subString);
linkMask |= ToLinkMask(subString);
linkMask |= ToLinkMask(subString, aPrincipal);
}
return linkMask;
}

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

@ -61,10 +61,13 @@ public:
eHTMLIMPORT = 0x00000020
};
// The return value is a bitwise or of 0 or more RelValues
static uint32_t ParseLinkTypes(const nsAString& aTypes);
// The return value is a bitwise or of 0 or more RelValues.
// aPrincipal is used to check if HTML imports is enabled for the
// provided principal.
static uint32_t ParseLinkTypes(const nsAString& aTypes,
nsIPrincipal* aPrincipal);
static bool IsImportEnabled();
static bool IsImportEnabled(nsIPrincipal* aPrincipal);
void UpdateStyleSheetInternal()
{

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

@ -117,7 +117,7 @@ nsresult runTest(uint32_t aExpectedPolicyCount, // this should be 0 for policies
policyStr.AssignASCII(aPolicy);
// Second argument in AppendPolicy needs to be a nullptr,
// because we are using the selfURI set in SetRequestingContext
rv = csp->AppendPolicy(policyStr, nullptr, false, true);
rv = csp->AppendPolicy(policyStr, nullptr, false);
NS_ENSURE_SUCCESS(rv, rv);
// when executing fuzzy tests we do not care about the actual output

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

@ -66,13 +66,8 @@ window.done = function(result) {
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?301';
});
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?301';
</script>
</pre>
</body>

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

@ -66,13 +66,8 @@ window.done = function(result) {
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?302';
});
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?302';
</script>
</pre>
</body>

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

@ -66,13 +66,8 @@ window.done = function(result) {
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?303';
});
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?303';
</script>
</pre>
</body>

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

@ -66,13 +66,9 @@ window.done = function(result) {
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?307';
});
// ... this loads the testbed of good and bad requests.
document.getElementById('content_iframe').src = 'file_redirect_content.sjs?307';
</script>
</pre>
</body>

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

@ -101,8 +101,7 @@ window.testResult = function(testname, result, msg) {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true],
// This defaults to 0 ("preload none") on mobile (B2G/Android), which
{'set':[// This defaults to 0 ("preload none") on mobile (B2G/Android), which
// blocks loading the resource until the user interacts with a
// corresponding widget, which breaks the media_* tests. We set it
// back to the default used by desktop Firefox to get consistent

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

@ -65,16 +65,11 @@ function checkBlocked () {
checkExplicitFinish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
document.getElementById('xsltframe').addEventListener('load', checkAllowed, false);
document.getElementById('xsltframe').src = 'file_CSP_bug663567_allows.xml';
document.getElementById('xsltframe').addEventListener('load', checkAllowed, false);
document.getElementById('xsltframe').src = 'file_CSP_bug663567_allows.xml';
document.getElementById('xsltframe2').addEventListener('load', checkBlocked, false);
document.getElementById('xsltframe2').src = 'file_CSP_bug663567_blocks.xml';
}
);
document.getElementById('xsltframe2').addEventListener('load', checkBlocked, false);
document.getElementById('xsltframe2').src = 'file_CSP_bug663567_blocks.xml';
</script>
</body>

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

@ -25,33 +25,28 @@ var checkExplicitFinish = function () {
}
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
// add event listeners for CSP-permitted EventSrc callbacks
addEventListener('allowedEventSrcCallbackOK', function (e) {
ok(true, "OK: CSP allows EventSource for whitelisted domain!");
checkExplicitFinish();
}, false);
addEventListener('allowedEventSrcCallbackFailed', function (e) {
ok(false, "Error: CSP blocks EventSource for whitelisted domain!");
checkExplicitFinish();
}, false);
// add event listeners for CSP-permitted EventSrc callbacks
addEventListener('allowedEventSrcCallbackOK', function (e) {
ok(true, "OK: CSP allows EventSource for whitelisted domain!");
checkExplicitFinish();
}, false);
addEventListener('allowedEventSrcCallbackFailed', function (e) {
ok(false, "Error: CSP blocks EventSource for whitelisted domain!");
checkExplicitFinish();
}, false);
// add event listeners for CSP-blocked EventSrc callbacks
addEventListener('blockedEventSrcCallbackOK', function (e) {
ok(false, "Error: CSP allows EventSource to not whitelisted domain!");
checkExplicitFinish();
}, false);
addEventListener('blockedEventSrcCallbackFailed', function (e) {
ok(true, "OK: CSP blocks EventSource for not whitelisted domain!");
checkExplicitFinish();
}, false);
// add event listeners for CSP-blocked EventSrc callbacks
addEventListener('blockedEventSrcCallbackOK', function (e) {
ok(false, "Error: CSP allows EventSource to not whitelisted domain!");
checkExplicitFinish();
}, false);
addEventListener('blockedEventSrcCallbackFailed', function (e) {
ok(true, "OK: CSP blocks EventSource for not whitelisted domain!");
checkExplicitFinish();
}, false);
// load it
document.getElementById('eventframe').src = 'file_CSP_bug802872.html';
}
);
// load it
document.getElementById('eventframe').src = 'file_CSP_bug802872.html';
</script>
</body>

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

@ -50,15 +50,10 @@ function checkBlocked () {
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
document.getElementById('cspframe').src = 'file_CSP_bug885433_allows.html';
document.getElementById('cspframe').addEventListener('load', checkAllowed, false);
document.getElementById('cspframe2').src = 'file_CSP_bug885433_blocks.html';
document.getElementById('cspframe2').addEventListener('load', checkBlocked, false);
}
);
document.getElementById('cspframe').src = 'file_CSP_bug885433_allows.html';
document.getElementById('cspframe').addEventListener('load', checkAllowed, false);
document.getElementById('cspframe2').src = 'file_CSP_bug885433_blocks.html';
document.getElementById('cspframe2').addEventListener('load', checkBlocked, false);
</script>
</pre>
</body>

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

@ -56,22 +56,17 @@ function checkDefaultSrcWithStyleSrc() {
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
document.getElementById('testframe1').src = 'file_CSP_bug888172.sjs?csp=' +
escape("default-src 'self' 'unsafe-inline' 'unsafe-eval'");
document.getElementById('testframe1').addEventListener('load', checkDefaultSrcOnly, false);
document.getElementById('testframe1').src = 'file_CSP_bug888172.sjs?csp=' +
escape("default-src 'self' 'unsafe-inline' 'unsafe-eval'");
document.getElementById('testframe1').addEventListener('load', checkDefaultSrcOnly, false);
document.getElementById('testframe2').src = 'file_CSP_bug888172.sjs?csp=' +
escape("default-src 'self' 'unsafe-inline' 'unsafe-eval'; script-src 'self'");
document.getElementById('testframe2').addEventListener('load', checkDefaultSrcWithScriptSrc, false);
document.getElementById('testframe2').src = 'file_CSP_bug888172.sjs?csp=' +
escape("default-src 'self' 'unsafe-inline' 'unsafe-eval'; script-src 'self'");
document.getElementById('testframe2').addEventListener('load', checkDefaultSrcWithScriptSrc, false);
document.getElementById('testframe3').src = 'file_CSP_bug888172.sjs?csp=' +
escape("default-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self'");
document.getElementById('testframe3').addEventListener('load', checkDefaultSrcWithStyleSrc, false);
}
);
document.getElementById('testframe3').src = 'file_CSP_bug888172.sjs?csp=' +
escape("default-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self'");
document.getElementById('testframe3').addEventListener('load', checkDefaultSrcWithStyleSrc, false);
</script>
</pre>
</body>

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

@ -120,15 +120,10 @@ function checkInlineWithNone() {
"Inline scripts should be blocked (style-src 'unsafe-inline' with none)");
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
document.getElementById('testframe1').src = 'file_CSP_bug909029_star.html';
document.getElementById('testframe1').addEventListener('load', checkInlineWithStar, false);
document.getElementById('testframe2').src = 'file_CSP_bug909029_none.html';
document.getElementById('testframe2').addEventListener('load', checkInlineWithNone, false);
}
);
document.getElementById('testframe1').src = 'file_CSP_bug909029_star.html';
document.getElementById('testframe1').addEventListener('load', checkInlineWithStar, false);
document.getElementById('testframe2').src = 'file_CSP_bug909029_none.html';
document.getElementById('testframe2').addEventListener('load', checkInlineWithNone, false);
</script>
</body>
</html>

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

@ -58,13 +58,8 @@ function checkBlocked () {
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
document.getElementById('xsltframe').addEventListener('load', checkAllowed, false);
document.getElementById('xsltframe').src = 'file_CSP_bug910139.sjs';
}
);
document.getElementById('xsltframe').addEventListener('load', checkAllowed, false);
document.getElementById('xsltframe').src = 'file_CSP_bug910139.sjs';
</script>
</body>

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

@ -97,13 +97,9 @@ window.testResult = function(testname, result, msg) {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_bug941404.html';
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_bug941404.html';
</script>
</pre>

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

@ -49,14 +49,10 @@ var checkTestResults = function() {
// set up and go
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_evalscript_main.html';
document.getElementById('cspframe2').src = 'file_CSP_evalscript_main_allowed.html';
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_evalscript_main.html';
document.getElementById('cspframe2').src = 'file_CSP_evalscript_main_allowed.html';
</script>
</pre>
</body>

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

@ -48,15 +48,11 @@ var checkTestResults = function() {
// set up and go
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_evalscript_main_getCRMFRequest.html';
document.getElementById('cspframe2').src = 'file_CSP_evalscript_main_allowed_getCRMFRequest.html';
document.getElementById('cspframe3').src = 'file_CSP_evalscript_no_CSP_at_all.html';
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_evalscript_main_getCRMFRequest.html';
document.getElementById('cspframe2').src = 'file_CSP_evalscript_main_allowed_getCRMFRequest.html';
document.getElementById('cspframe3').src = 'file_CSP_evalscript_no_CSP_at_all.html';
</script>
</pre>
</body>

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

@ -147,14 +147,9 @@ function receiveMessage(event) {
window.examiner = new examiner();
SimpleTest.waitForExplicitFinish();
// added this so the tests run even if we don't flip the pref on by default.
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_frameancestors_main.html';
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_frameancestors_main.html';
</script>
</pre>

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

@ -101,16 +101,12 @@ function clickit2() {
sendMouseEvent({type:'click'}, a, cspframe2.contentWindow);
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe1').src = 'file_CSP_inlinescript_main.html';
document.getElementById('cspframe1').addEventListener('load', clickit1, false);
document.getElementById('cspframe2').src = 'file_CSP_inlinescript_main_allowed.html';
document.getElementById('cspframe2').addEventListener('load', clickit2, false);
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe1').src = 'file_CSP_inlinescript_main.html';
document.getElementById('cspframe1').addEventListener('load', clickit1, false);
document.getElementById('cspframe2').src = 'file_CSP_inlinescript_main_allowed.html';
document.getElementById('cspframe2').addEventListener('load', clickit2, false);
</script>
</pre>
</body>

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

@ -94,17 +94,13 @@ function checkIfDone() {
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe1').src = 'file_CSP_inlinestyle_main.html';
document.getElementById('cspframe1').addEventListener('load', checkStyles, false);
document.getElementById('cspframe2').src = 'file_CSP_inlinestyle_main_allowed.html';
document.getElementById('cspframe2').addEventListener('load', checkStylesAllowed, false);
}
);
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe1').src = 'file_CSP_inlinestyle_main.html';
document.getElementById('cspframe1').addEventListener('load', checkStyles, false);
document.getElementById('cspframe2').src = 'file_CSP_inlinestyle_main_allowed.html';
document.getElementById('cspframe2').addEventListener('load', checkStylesAllowed, false);
</script>
</pre>
</body>

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

@ -235,13 +235,9 @@ window.testResult = function(testname, result, msg) {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'http://mochi.test:8888' + path + 'file_bug836922_npolicies.html';
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'http://mochi.test:8888' + path + 'file_bug836922_npolicies.html';
</script>
</pre>

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

@ -157,18 +157,14 @@ window.testResult = function(testname, result, msg) {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_bug886164.html';
document.getElementById('cspframe2').src = 'file_bug886164_2.html';
document.getElementById('cspframe3').src = 'file_bug886164_3.html';
document.getElementById('cspframe4').src = 'file_bug886164_4.html';
document.getElementById('cspframe5').src = 'file_bug886164_5.html';
document.getElementById('cspframe6').src = 'file_bug886164_6.html';
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_bug886164.html';
document.getElementById('cspframe2').src = 'file_bug886164_2.html';
document.getElementById('cspframe3').src = 'file_bug886164_3.html';
document.getElementById('cspframe4').src = 'file_bug886164_4.html';
document.getElementById('cspframe5').src = 'file_bug886164_5.html';
document.getElementById('cspframe6').src = 'file_bug886164_6.html';
</script>
</pre>

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

@ -213,8 +213,7 @@ SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
["security.apps.privileged.CSP.default", DEFAULT_CSP_PRIV],
["security.apps.certified.CSP.default", DEFAULT_CSP_CERT],
["security.mixed_content.block_active_content", false],
["security.mixed_content.block_display_content", false],
["security.csp.speccompliant", true]]},
["security.mixed_content.block_display_content", false]]},
function() { gTestRunner.next(); });

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

@ -218,8 +218,7 @@ SpecialPowers.addPermission("browser", true, "https://example.com");
SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
["security.apps.privileged.CSP.default", DEFAULT_CSP_PRIV],
["security.apps.certified.CSP.default", DEFAULT_CSP_CERT],
["security.csp.speccompliant", true]]},
["security.apps.certified.CSP.default", DEFAULT_CSP_CERT]]},
function() { gTestRunner.next(); });

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

@ -111,8 +111,7 @@ var testResult = function(testName, url, result) {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true],
// This defaults to 0 ("preload none") on mobile (B2G/Android), which
{'set':[// This defaults to 0 ("preload none") on mobile (B2G/Android), which
// blocks loading the resource until the user interacts with a
// corresponding widget, which breaks the media_* tests. We set it
// back to the default used by desktop Firefox to get consistent

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

@ -94,12 +94,7 @@ function test() {
loadNextTest();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
loadNextTest();
}
);
loadNextTest();
</script>
</body>

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

@ -100,13 +100,9 @@ window.examiner = new examiner();
SimpleTest.waitForExplicitFinish();
// load the resource which will generate a CSP violation report
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById("cspframe").src = testFile;
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById("cspframe").src = testFile;
</script>
</pre>
</body>

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

@ -125,14 +125,10 @@ function checkInline () {
// set up and go
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_hash_source.html';
document.getElementById('cspframe').addEventListener('load', checkInline, false);
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_hash_source.html';
document.getElementById('cspframe').addEventListener('load', checkInline, false);
</script>
</pre>
</body>

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

@ -110,13 +110,9 @@ window.testResult = function(testname, result, msg) {
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_multi_policy_injection_bypass.html';
document.getElementById('cspframe2').src = 'file_multi_policy_injection_bypass_2.html';
});
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_multi_policy_injection_bypass.html';
document.getElementById('cspframe2').src = 'file_multi_policy_injection_bypass_2.html';
</script>
</pre>
</body>

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

@ -112,14 +112,10 @@ function checkInlineScriptsAndStyles () {
window.examiner = new examiner();
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_nonce_source.html';
document.getElementById('cspframe').addEventListener('load', checkInlineScriptsAndStyles, false);
});
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_nonce_source.html';
document.getElementById('cspframe').addEventListener('load', checkInlineScriptsAndStyles, false);
</script>
</pre>
</body>

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

@ -14,19 +14,14 @@
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function () {
var testframe = document.getElementById('testframe');
testframe.src = 'file_policyuri_regression_from_multipolicy.html';
testframe.addEventListener('load', function checkInlineScriptExecuted () {
is(this.contentDocument.getElementById('testdiv').innerHTML,
'Inline Script Executed',
'Inline script should execute (it would be blocked by the policy, but the policy is report-only)');
SimpleTest.finish();
});
}
);
var testframe = document.getElementById('testframe');
testframe.src = 'file_policyuri_regression_from_multipolicy.html';
testframe.addEventListener('load', function checkInlineScriptExecuted () {
is(this.contentDocument.getElementById('testdiv').innerHTML,
'Inline Script Executed',
'Inline script should execute (it would be blocked by the policy, but the policy is report-only)');
SimpleTest.finish();
});
</script>
</body>
</html>

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

@ -40,11 +40,7 @@ SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) {
// set up and start testing
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set': [["security.csp.speccompliant", true]]},
function() {
document.getElementById('cspframe').src = 'file_report_uri_missing_in_report_only_header.html';
});
document.getElementById('cspframe').src = 'file_report_uri_missing_in_report_only_header.html';
</script>
</pre>
</body>

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

@ -47,12 +47,8 @@ SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) {
// set up and start testing
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set': [["security.csp.speccompliant", true]]},
function() {
document.getElementById('cspframe').src = 'file_self_none_as_hostname_confusion.html';
startTest = true;
});
document.getElementById('cspframe').src = 'file_self_none_as_hostname_confusion.html';
startTest = true;
</script>
</pre>
</body>

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

@ -27,11 +27,7 @@ function checkResult()
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
document.getElementById('i').src = 'file_subframe_run_js_if_allowed.html';
});
document.getElementById('i').src = 'file_subframe_run_js_if_allowed.html';
</script>
</body>
</html>

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

@ -79,7 +79,7 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
// Load up the policy
// set as report-only if that's the case
csp.appendPolicy(policy, selfuri, useReportOnlyPolicy, true);
csp.appendPolicy(policy, selfuri, useReportOnlyPolicy);
// prime the report server
var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);

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

@ -500,7 +500,7 @@ test(function test_FrameAncestor_ignores_userpass_bug779918() {
function testPermits(aChildUri, aParentUri, aContentType) {
let cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
cspObj.appendPolicy(testPolicy, aChildUri, false, false);
cspObj.appendPolicy(testPolicy, aChildUri, false);
let docshellparent = Cc["@mozilla.org/docshell;1"]
.createInstance(Ci.nsIDocShell);
let docshellchild = Cc["@mozilla.org/docshell;1"]
@ -677,9 +677,9 @@ test(
*
* Document with CSP: https://foobar.com:4443
* Transmitted policy:
* "allow 'self' a.com"
* "default-src 'self' a.com"
* Explicit policy:
* "allow https://foobar.com:4443 https://a.com:443"
* "default-src https://foobar.com:4443 https://a.com:443"
*
* This test examines scheme and nonstandard port inheritance.
*/
@ -716,7 +716,7 @@ test(
test(
function test_bug634773_noneAndStarAreDifferent() {
/**
* Bug 634773 is that allow * and allow 'none' end up "equal" via
* Bug 634773 is that default-src * and default-src 'none' end up "equal" via
* CSPSourceList.prototype.equals(), which is wrong. This tests that
* doesn't happen.
*/
@ -748,7 +748,7 @@ test(
};
const policy = "script-src 'self'";
cspObj.appendPolicy(policy, selfURI, false, true);
cspObj.appendPolicy(policy, selfURI, false);
// Spec-Compliant policy default-src defaults to *.
// This means all images are allowed, and only 'self'
@ -833,13 +833,13 @@ test(function test_csp_permits_case_insensitive() {
test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
var cspr;
var self = "http://localhost:" + POLICY_PORT;
var closed_policy = CSPRep.fromString("allow 'none'");
var closed_policy = CSPRep.fromString("default-src 'none'");
var my_uri_policy = "policy-uri " + POLICY_URI;
//print(" --- Ignore the following two errors if they print ---");
cspr = CSPRep.fromString("allow *; " + my_uri_policy, URI(self));
cspr = CSPRep.fromString("default-src *; " + my_uri_policy, URI(self));
//"Parsing should fail when 'policy-uri' is mixed with allow directive"
//"Parsing should fail when 'policy-uri' is mixed with default-src directive"
do_check_equivalent(cspr, closed_policy);
cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, URI(self));

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

@ -3660,7 +3660,11 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
}
nsRefPtr<gfxContext> thebes;
RefPtr<DrawTarget> drawDT;
if (gfxPlatform::GetPlatform()->SupportsAzureContentForDrawTarget(mTarget)) {
// Rendering directly is faster and can be done if mTarget supports Azure
// and does not need alpha blending.
if (gfxPlatform::GetPlatform()->SupportsAzureContentForDrawTarget(mTarget) &&
GlobalAlpha() == 1.0f)
{
thebes = new gfxContext(mTarget);
thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21,
matrix._22, matrix._31, matrix._32));
@ -3698,7 +3702,7 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
mgfx::Rect sourceRect(0, 0, sw, sh);
mTarget->DrawSurface(source, destRect, sourceRect,
DrawSurfaceOptions(mgfx::Filter::POINT),
DrawOptions(1.0f, CompositionOp::OP_OVER,
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
AntialiasMode::NONE));
mTarget->Flush();
} else {

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

@ -0,0 +1 @@
<template>&#x000d;#

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

@ -55,3 +55,4 @@ load 877910.html
load 903106.html
load 916322-1.html
load 916322-2.html
load 1032654.html

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

@ -276,7 +276,7 @@ HTMLLinkElement::UpdateImport()
// 2. rel type should be import.
nsAutoString rel;
GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel, NodePrincipal());
if (!(linkTypes & eHTMLIMPORT)) {
mImportLoader = nullptr;
return;
@ -288,7 +288,7 @@ HTMLLinkElement::UpdateImport()
return;
}
if (!nsStyleLinkElement::IsImportEnabled()) {
if (!nsStyleLinkElement::IsImportEnabled(NodePrincipal())) {
// For now imports are hidden behind a pref...
return;
}
@ -330,7 +330,8 @@ HTMLLinkElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
aName == nsGkAtoms::type)) {
bool dropSheet = false;
if (aName == nsGkAtoms::rel) {
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue);
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue,
NodePrincipal());
if (GetSheet()) {
dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET);
} else if (linkTypes & eHTMLIMPORT) {
@ -456,7 +457,7 @@ HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
nsAutoString rel;
GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel, NodePrincipal());
// Is it a stylesheet link?
if (!(linkTypes & nsStyleLinkElement::eSTYLESHEET)) {
return;

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

@ -607,7 +607,8 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
nsAutoString relVal;
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
if (!relVal.IsEmpty()) {
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
uint32_t linkTypes =
nsStyleLinkElement::ParseLinkTypes(relVal, aContent->NodePrincipal());
bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
nsAutoString hrefVal;

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

@ -1598,8 +1598,7 @@ ConcatJSString(JSContext* cx, const char* pre, JS::Handle<JSString*> str, const
bool
NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, const char* pre,
const char* post,
JS::Handle<JSObject*> obj,
JS::MutableHandle<JS::Value> v)
{
JS::Rooted<JSPropertyDescriptor> toStringDesc(cx);
@ -1644,7 +1643,6 @@ NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Rooted<JSFunction*> fun(cx, JS_GetObjectFunction(obj));
str = JS_DecompileFunction(cx, fun, 0);
}
str = ConcatJSString(cx, pre, str, post);
}
}

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

@ -2385,14 +2385,11 @@ MustInheritFromNonRefcountedDOMObject(NonRefcountedDOMObject*)
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
* pre is a string that should be prefixed to the value.
* post is a string that should be prefixed to the value.
* v contains the JSString for the value if the function returns true.
*/
bool
NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, const char* pre,
const char* post,
JS::Handle<JSObject*> obj,
JS::MutableHandle<JS::Value> v);
HAS_MEMBER(JSBindingFinalized)

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

@ -150,7 +150,6 @@ public:
MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices);
virtual ~MediaPermissionRequest() {}
// It will be called when prompt dismissed.
virtual bool Recv__delete__(const bool &allow,
@ -159,6 +158,9 @@ public:
already_AddRefed<nsPIDOMWindow> GetOwner();
protected:
virtual ~MediaPermissionRequest() {}
private:
nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice);
@ -378,6 +380,8 @@ public:
MediaDeviceSuccessCallback(nsRefPtr<dom::GetUserMediaRequest> &aRequest)
: mRequest(aRequest) {}
protected:
virtual ~MediaDeviceSuccessCallback() {}
private:
@ -479,6 +483,7 @@ public:
MediaDeviceErrorCallback(const nsAString &aCallID)
: mCallID(aCallID) {}
protected:
virtual ~MediaDeviceErrorCallback() {}
private:

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

@ -23,6 +23,8 @@ public:
NS_DECL_NSIOBSERVER
static MediaPermissionManager* GetInstance();
protected:
virtual ~MediaPermissionManager();
private:

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

@ -431,32 +431,28 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices)
return NS_OK;
}
nsCOMPtr<nsIDOMGeoPosition> lastPosition = gs->GetCachedPosition();
DOMTimeStamp cachedPositionTime;
if (lastPosition) {
lastPosition->GetTimestamp(&cachedPositionTime);
}
// check to see if we can use a cached value
// if the user has specified a maximumAge, return a cached value.
uint32_t maximumAge = 0;
if (mOptions) {
if (mOptions->mMaximumAge > 0) {
maximumAge = mOptions->mMaximumAge;
bool canUseCache = false;
CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition();
if (lastPosition.position) {
DOMTimeStamp cachedPositionTime_ms;
lastPosition.position->GetTimestamp(&cachedPositionTime_ms);
// check to see if we can use a cached value
// if the user has specified a maximumAge, return a cached value.
if (mOptions && mOptions->mMaximumAge > 0) {
uint32_t maximumAge_ms = mOptions->mMaximumAge;
bool isCachedWithinRequestedAccuracy = WantsHighAccuracy() <= lastPosition.isHighAccuracy;
bool isCachedWithinRequestedTime =
DOMTimeStamp(PR_Now() / PR_USEC_PER_MSEC - maximumAge_ms) <= cachedPositionTime_ms;
canUseCache = isCachedWithinRequestedAccuracy && isCachedWithinRequestedTime;
}
}
gs->UpdateAccuracy(WantsHighAccuracy());
bool canUseCache = lastPosition && maximumAge > 0 &&
(PRTime(PR_Now() / PR_USEC_PER_MSEC) - maximumAge <=
PRTime(cachedPositionTime));
if (canUseCache) {
// okay, we can return a cached position
// getCurrentPosition requests serviced by the cache
// will now be owned by the RequestSendLocationEvent
Update(lastPosition);
Update(lastPosition.position);
}
if (mIsWatchPositionRequest || !canUseCache) {
@ -764,7 +760,7 @@ nsGeolocationService::HandleMozsettingValue(const bool aValue)
// turn things off
StopDevice();
Update(nullptr);
mLastPosition = nullptr;
mLastPosition.position = nullptr;
sGeoEnabled = false;
} else {
sGeoEnabled = true;
@ -854,10 +850,11 @@ nsGeolocationService::NotifyError(uint16_t aErrorCode)
void
nsGeolocationService::SetCachedPosition(nsIDOMGeoPosition* aPosition)
{
mLastPosition = aPosition;
mLastPosition.position = aPosition;
mLastPosition.isHighAccuracy = mHigherAccuracy;
}
nsIDOMGeoPosition*
CachedPositionAndAccuracy
nsGeolocationService::GetCachedPosition()
{
return mLastPosition;

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

@ -45,6 +45,11 @@ typedef CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallba
}
}
struct CachedPositionAndAccuracy {
nsCOMPtr<nsIDOMGeoPosition> position;
bool isHighAccuracy;
};
/**
* Singleton that manages the geolocation provider
*/
@ -73,7 +78,7 @@ public:
void RemoveLocator(mozilla::dom::Geolocation* locator);
void SetCachedPosition(nsIDOMGeoPosition* aPosition);
nsIDOMGeoPosition* GetCachedPosition();
CachedPositionAndAccuracy GetCachedPosition();
// Find and startup a geolocation device (gps, nmea, etc.)
nsresult StartDevice(nsIPrincipal* aPrincipal);
@ -106,7 +111,7 @@ private:
nsTArray<mozilla::dom::Geolocation*> mGeolocators;
// This is the last geo position that we have seen.
nsCOMPtr<nsIDOMGeoPosition> mLastPosition;
CachedPositionAndAccuracy mLastPosition;
// Current state of requests for higher accuracy
bool mHigherAccuracy;

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

@ -20,7 +20,7 @@ let gLoggingEnabled = false;
from the Wifi subsystem. If this timer fires, we believe the Wifi scan has
had a problem and we no longer can use Wifi to position the user this time
around (we will continue to be hopeful that Wifi will recover).
This timeout value is also used when Wifi scanning is disabled (see
gWifiScanningEnabled). In this case, we use this timer to collect cell/ip
data and xhr it to the location server.
@ -39,6 +39,172 @@ function LOG(aMsg) {
}
}
function CachedRequest(loc, cellInfo, wifiList) {
this.location = loc;
let wifis = new Set();
if (wifiList) {
for (let i = 0; i < wifiList.length; i++) {
wifis.add(wifiList[i].macAddress);
}
}
// Use only these values for equality
// (the JSON will contain additional values in future)
function makeCellKey(cell) {
return "" + cell.radio + ":" + cell.mobileCountryCode + ":" +
cell.mobileNetworkCode + ":" + cell.locationAreaCode + ":" +
cell.cellId;
}
let cells = new Set();
if (cellInfo) {
for (let i = 0; i < cellInfo.length; i++) {
cells.add(makeCellKey(cellInfo[i]));
}
}
this.hasCells = () => cells.size > 0;
this.hasWifis = () => wifis.size > 0;
// if fields match
this.isCellEqual = function(cellInfo) {
if (!this.hasCells()) {
return false;
}
let len1 = cells.size;
let len2 = cellInfo.length;
if (len1 != len2) {
LOG("cells not equal len");
return false;
}
for (let i = 0; i < len2; i++) {
if (!cells.has(makeCellKey(cellInfo[i]))) {
return false;
}
}
return true;
};
// if 50% of the SSIDS match
this.isWifiApproxEqual = function(wifiList) {
if (!this.hasWifis()) {
return false;
}
// if either list is a 50% subset of the other, they are equal
let common = 0;
for (let i = 0; i < wifiList.length; i++) {
if (wifis.has(wifiList[i].macAddress)) {
common++;
}
}
let kPercentMatch = 0.5;
return common >= (Math.max(wifis.size, wifiList.length) * kPercentMatch);
};
this.isGeoip = function() {
return !this.hasCells() && !this.hasWifis();
};
this.isCellAndWifi = function() {
return this.hasCells() && this.hasWifis();
};
this.isCellOnly = function() {
return this.hasCells() && !this.hasWifis();
};
this.isWifiOnly = function() {
return this.hasWifis() && !this.hasCells();
};
}
let gCachedRequest = null;
let gDebugCacheReasoning = ""; // for logging the caching logic
// This function serves two purposes:
// 1) do we have a cached request
// 2) is the cached request better than what newCell and newWifiList will obtain
// If the cached request exists, and we know it to have greater accuracy
// by the nature of its origin (wifi/cell/geoip), use its cached location.
//
// If there is more source info than the cached request had, return false
// In other cases, MLS is known to produce better/worse accuracy based on the
// inputs, so base the decision on that.
function isCachedRequestMoreAccurateThanServerRequest(newCell, newWifiList)
{
gDebugCacheReasoning = "";
let isNetworkRequestCacheEnabled = true;
try {
// Mochitest needs this pref to simulate request failure
isNetworkRequestCacheEnabled = Services.prefs.getBoolPref("geo.wifi.debug.requestCache.enabled");
if (!isNetworkRequestCacheEnabled) {
gCachedRequest = null;
}
} catch (e) {}
if (!gCachedRequest || !isNetworkRequestCacheEnabled) {
gDebugCacheReasoning = "No cached data";
return false;
}
if (!newCell && !newWifiList) {
gDebugCacheReasoning = "New req. is GeoIP.";
return true;
}
if (newCell && newWifiList && (gCachedRequest.isCellOnly() || gCachedRequest.isWifiOnly())) {
gDebugCacheReasoning = "New req. is cell+wifi, cache only cell or wifi.";
return false;
}
if (newCell && gCachedRequest.isWifiOnly()) {
// In order to know if a cell-only request should trump a wifi-only request
// need to know if wifi is low accuracy. >5km would be VERY low accuracy,
// it is worth trying the cell
var isHighAccuracyWifi = gCachedRequest.location.coords.accuracy < 5000;
gDebugCacheReasoning = "Req. is cell, cache is wifi, isHigh:" + isHighAccuracyWifi;
return isHighAccuracyWifi;
}
let hasEqualCells = false;
if (newCell) {
hasEqualCells = gCachedRequest.isCellEqual(newCell);
}
let hasEqualWifis = false;
if (newWifiList) {
hasEqualWifis = gCachedRequest.isWifiApproxEqual(newWifiList);
}
gDebugCacheReasoning = "EqualCells:" + hasEqualCells + " EqualWifis:" + hasEqualWifis;
if (gCachedRequest.isCellOnly()) {
gDebugCacheReasoning += ", Cell only.";
if (hasEqualCells) {
return true;
}
} else if (gCachedRequest.isWifiOnly() && hasEqualWifis) {
gDebugCacheReasoning +=", Wifi only."
return true;
} else if (gCachedRequest.isCellAndWifi()) {
gDebugCacheReasoning += ", Cache has Cell+Wifi.";
if ((hasEqualCells && hasEqualWifis) ||
(!newWifiList && hasEqualCells) ||
(!newCell && hasEqualWifis))
{
return true;
}
}
return false;
}
function WifiGeoCoordsObject(lat, lon, acc, alt, altacc) {
this.latitude = lat;
this.longitude = lon;
@ -140,7 +306,7 @@ WifiGeoPositionProvider.prototype = {
}
}
},
handleError: function(message) {
gLoggingEnabled = false;
LOG("settings callback threw an exception, dropping");
@ -178,6 +344,10 @@ WifiGeoPositionProvider.prototype = {
return;
}
// Without clearing this, we could end up using the cache almost indefinitely
// TODO: add logic for cache lifespan, for now just be safe and clear it
gCachedRequest = null;
if (this.timer) {
this.timer.cancel();
this.timer = null;
@ -232,7 +402,7 @@ WifiGeoPositionProvider.prototype = {
},
getMobileInfo: function() {
LOG("updateMobileInfo called");
LOG("getMobileInfo called");
try {
let radioService = Cc["@mozilla.org/ril;1"]
.getService(Ci.nsIRadioInterfaceLayer);
@ -269,6 +439,30 @@ WifiGeoPositionProvider.prototype = {
},
sendLocationRequest: function (wifiData) {
let data = {};
if (wifiData) {
data.wifiAccessPoints = wifiData;
}
if (gCellScanningEnabled) {
let cellData = this.getMobileInfo();
if (cellData && cellData.length > 0) {
data.cellTowers = cellData;
}
}
let useCached = isCachedRequestMoreAccurateThanServerRequest(data.cellTowers,
data.wifiAccessPoints);
LOG("Use request cache:" + useCached + " reason:" + gDebugCacheReasoning);
if (useCached) {
gCachedRequest.location.timestamp = Date.now();
this.listener.update(gCachedRequest.location);
return;
}
// From here on, do a network geolocation request //
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
let listener = this.listener;
LOG("Sending request: " + url + "\n");
@ -304,23 +498,12 @@ WifiGeoPositionProvider.prototype = {
xhr.response.accuracy);
listener.update(newLocation);
gCachedRequest = new CachedRequest(newLocation, data.cellTowers, data.wifiAccessPoints);
};
let data = {};
if (wifiData) {
data.wifiAccessPoints = wifiData;
}
if (gCellScanningEnabled) {
let cellData = this.getMobileInfo();
if (cellData) {
data.cellTowers = cellData;
}
}
data = JSON.stringify(data);
LOG("sending " + data);
xhr.send(data);
var requestData = JSON.stringify(data);
LOG("sending " + requestData);
xhr.send(requestData);
},
};

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

@ -34,7 +34,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
try {
var css = Components.utils.evalInSandbox("CSSStyleDeclaration", sandbox);
is(css.prototype, "[object XrayWrapper [object CSSStyleDeclarationPrototype]]", "'CSSStyleDeclaration.prototype' in a sandbox should return the CSSStyleDeclaration interface prototype object");
is(css.prototype, "[object CSSStyleDeclarationPrototype]", "'CSSStyleDeclaration.prototype' in a sandbox should return the CSSStyleDeclaration interface prototype object");
} catch (e) {
ok(false, "'CSSStyleDeclaration' shouldn't throw in a sandbox");
}
@ -94,7 +94,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
}
try {
var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
is(xhr, "[object XrayWrapper " + XMLHttpRequest + "]", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
is(xhr, XMLHttpRequest + "", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper");
isnot(Object.getOwnPropertyDescriptor(xhr, "UNSENT"), undefined,
"We should claim to have an UNSENT constant");
@ -109,13 +109,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
}
try {
var xhr = Components.utils.evalInSandbox("new XMLHttpRequest()", sandbox);
is("" + xhr, "[object XrayWrapper " + new XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
is("" + xhr, new XMLHttpRequest() + "", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
} catch (e) {
ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (1)");
}
try {
var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; new XMLHttpRequest();", sandbox);
is(xhr.toString(), "[object XrayWrapper " + new XMLHttpRequest() + "]", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
is(xhr.toString(), new XMLHttpRequest() + "", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
} catch (e) {
ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (2)");
}
@ -141,7 +141,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
Components.utils.evalInSandbox("document.defaultView.XMLHttpRequest = function() {};", sandbox);
var win = Components.utils.evalInSandbox("document.defaultView", sandbox);
var xhr = new win.XMLHttpRequest();
is("" + xhr, "[object XrayWrapper " + new XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
is("" + xhr, new XMLHttpRequest() + "", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
} catch (e) {
ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
}

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

@ -1,3 +1,4 @@
var BASE_URL = "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs";
function sleep(delay)
{
@ -11,7 +12,7 @@ function force_prompt(allow, callback) {
function start_sending_garbage(callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=respond-garbage"]]}, function() {
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + "?action=respond-garbage"]]}, function() {
// we need to be sure that all location data has been purged/set.
sleep(1000);
callback.call();
@ -20,7 +21,7 @@ function start_sending_garbage(callback)
function stop_sending_garbage(callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs"]]}, function() {
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + ""]]}, function() {
// we need to be sure that all location data has been purged/set.
sleep(1000);
callback.call();
@ -29,31 +30,37 @@ function stop_sending_garbage(callback)
function stop_geolocationProvider(callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=stop-responding"]]}, function() {
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + "?action=stop-responding"]]}, function() {
// we need to be sure that all location data has been purged/set.
sleep(1000);
callback.call();
});
}
function set_network_request_cache_enabled(enabled, callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.debug.requestCache.enabled", enabled]]}, callback);
}
function worse_geolocationProvider(callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=worse-accuracy"]]}, callback);
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + "?action=worse-accuracy"]]}, callback);
}
function resume_geolocationProvider(callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs"]]}, callback);
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + ""]]}, callback);
}
function delay_geolocationProvider(delay, callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?delay=" + delay]]}, callback);
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + "?delay=" + delay]]}, callback);
}
function send404_geolocationProvider(callback)
{
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=send404"]]}, callback);
set_network_request_cache_enabled(false, function() {
SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", BASE_URL + "?action=send404"]]}, callback);});
}
function check_geolocation(location) {
@ -76,8 +83,8 @@ function check_geolocation(location) {
// optional ok("heading" in coords, "Check to see if there is a heading");
// optional ok("speed" in coords, "Check to see if there is a speed");
ok (location.coords.latitude == 37.41857, "lat matches known value");
ok (location.coords.longitude == -122.08769, "lon matches known value");
ok (Math.abs(location.coords.latitude - 37.41857) < 0.001, "lat matches known value");
ok (Math.abs(location.coords.longitude + 122.08769) < 0.001, "lon matches known value");
// optional ok(location.coords.altitude == 42, "alt matches known value");
// optional ok(location.coords.altitudeAccuracy == 42, "alt acc matches known value");
}

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

@ -22,12 +22,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850442
SimpleTest.waitForExplicitFinish();
resume_geolocationProvider(function() {
force_prompt(true, test1);
force_prompt(true, function () {
set_network_request_cache_enabled(false, function() {
test1();
});
});
});
function done() {
resume_geolocationProvider(function() {
SimpleTest.finish();
set_network_request_cache_enabled(true, function() {
resume_geolocationProvider(function() {
SimpleTest.finish();
});
});
}

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

@ -37,15 +37,18 @@ function errorCallback(err) {
if (times >= 3) {
navigator.geolocation.clearWatch(watchID);
resume_geolocationProvider(function() {
SimpleTest.finish();
set_network_request_cache_enabled(true,
function() { SimpleTest.finish(); } );
});
}
}
function successCallback(position) {
ok(1, "on success");
// Now that we got a success callback, lets try to ensure
// that we get a timeout error.
stop_geolocationProvider(function() {});
// The network cache is already off, now stop the sjs from reponding to requests
stop_geolocationProvider(function(){});
}
var options = {
@ -54,7 +57,10 @@ var options = {
};
function test1() {
watchID = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
set_network_request_cache_enabled(false,
function() {
watchID = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
});
}
</script>
</pre>

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

@ -229,7 +229,7 @@ partial interface Document {
//http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register
partial interface Document {
[Throws, Func="nsDocument::IsRegisterElementEnabled"]
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
object registerElement(DOMString name, optional ElementRegistrationOptions options);
};

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

@ -201,11 +201,11 @@ partial interface Element {
// http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-element-interface
partial interface Element {
[Throws,Pref="dom.webcomponents.enabled"]
[Throws,Func="nsDocument::IsWebComponentsEnabled"]
ShadowRoot createShadowRoot();
[Pref="dom.webcomponents.enabled"]
[Func="nsDocument::IsWebComponentsEnabled"]
NodeList getDestinationInsertionPoints();
[Pref="dom.webcomponents.enabled"]
[Func="nsDocument::IsWebComponentsEnabled"]
readonly attribute ShadowRoot? shadowRoot;
};

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

@ -44,7 +44,7 @@ partial interface HTMLLinkElement {
// http://w3c.github.io/webcomponents/spec/imports/#interface-import
partial interface HTMLLinkElement {
[Pref="dom.webcomponents.enabled"]
[Func="nsDocument::IsWebComponentsEnabled"]
readonly attribute Document? import;
};

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

@ -10,7 +10,7 @@
* liability, trademark and document use rules apply.
*/
[Pref="dom.webcomponents.enabled"]
[Func="nsDocument::IsWebComponentsEnabled"]
interface ShadowRoot : DocumentFragment
{
Element? getElementById(DOMString elementId);

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

@ -5227,43 +5227,62 @@ nsEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
// If the event is trusted, the event should always cause input.
NS_ENSURE_TRUE(aEvent, false);
// If this is mouse event but this editor doesn't have focus, we shouldn't
// handle it.
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
if (mouseEvent) {
WidgetEvent* widgetEvent = aEvent->GetInternalNSEvent();
if (NS_WARN_IF(!widgetEvent)) {
return false;
}
// If this is dispatched by using cordinates but this editor doesn't have
// focus, we shouldn't handle it.
if (widgetEvent->IsUsingCoordinates()) {
nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
if (!focusedContent) {
return false;
}
} else {
nsAutoString eventType;
aEvent->GetType(eventType);
// If composition event or text event isn't dispatched via widget,
// we need to ignore them since they cannot be managed by TextComposition.
// E.g., the event was created by chrome JS.
// Note that if we allow to handle such events, editor may be confused by
// strange event order.
if (eventType.EqualsLiteral("text") ||
eventType.EqualsLiteral("compositionstart") ||
eventType.EqualsLiteral("compositionend")) {
WidgetGUIEvent* widgetGUIEvent =
aEvent->GetInternalNSEvent()->AsGUIEvent();
if (!widgetGUIEvent || !widgetGUIEvent->widget) {
return false;
}
}
}
bool isTrusted;
nsresult rv = aEvent->GetIsTrusted(&isTrusted);
NS_ENSURE_SUCCESS(rv, false);
if (isTrusted) {
// If composition event or text event isn't dispatched via widget,
// we need to ignore them since they cannot be managed by TextComposition.
// E.g., the event was created by chrome JS.
// Note that if we allow to handle such events, editor may be confused by
// strange event order.
bool needsWidget = false;
WidgetGUIEvent* widgetGUIEvent = nullptr;
switch (widgetEvent->message) {
case NS_USER_DEFINED_EVENT:
// If events are not created with proper event interface, their message
// are initialized with NS_USER_DEFINED_EVENT. Let's ignore such event.
return false;
case NS_TEXT_TEXT:
// Don't allow text events whose internal event are not
// WidgetTextEvent.
widgetGUIEvent = aEvent->GetInternalNSEvent()->AsTextEvent();
needsWidget = true;
break;
case NS_COMPOSITION_START:
case NS_COMPOSITION_END:
case NS_COMPOSITION_UPDATE:
// Don't allow composition events whose internal event are not
// WidgetCompositionEvent.
widgetGUIEvent = aEvent->GetInternalNSEvent()->AsCompositionEvent();
needsWidget = true;
break;
default:
break;
}
if (needsWidget &&
(!widgetGUIEvent || !widgetGUIEvent->widget)) {
return false;
}
// Accept all trusted events.
if (widgetEvent->mFlags.mIsTrusted) {
return true;
}
// Ignore untrusted mouse event.
// XXX Why are we handling other untrusted input events?
if (mouseEvent) {
if (widgetEvent->AsMouseEventBase()) {
return false;
}

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

@ -3,5 +3,6 @@
[test_bug46555.html]
[test_bug599983.xul]
[test_bug646194.xul]
[test_composition_event_created_in_chrome.html]
[test_dragdrop.html]
[test_selection_move_commands.xul]

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

@ -0,0 +1,81 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<input id="input">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var gInputElement = document.getElementById("input");
function getEditorIMESupport(aInputElement)
{
var editableElement = aInputElement.QueryInterface(Components.interfaces.nsIDOMNSEditableElement);
ok(editableElement, "The input element doesn't have nsIDOMNSEditableElement interface");
ok(editableElement.editor, "There is no editor for the input element");
var editorIMESupport = editableElement.editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
ok(editorIMESupport, "The input element doesn't have nsIEditorIMESupport interface");
return editorIMESupport;
}
var gEditorIMESupport;
function testNotGenerateCompositionByCreatedEvents(aEventInterface)
{
var compositionEvent = document.createEvent(aEventInterface);
if (compositionEvent.initCompositionEvent) {
compositionEvent.initCompositionEvent("compositionstart", true, true, window, "", "");
} else if (compositionEvent.initMouseEvent) {
compositionEvent.initMouseEvent("compositionstart", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
gInputElement.dispatchEvent(compositionEvent);
ok(!gEditorIMESupport.composing, "Composition shouldn't be started with a created compositionstart event (" + aEventInterface + ")");
compositionEvent = document.createEvent(aEventInterface);
if (compositionEvent.initCompositionEvent) {
compositionEvent.initCompositionEvent("compositionupdate", true, false, window, "abc", "");
} else if (compositionEvent.initMouseEvent) {
compositionEvent.initMouseEvent("compositionupdate", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
gInputElement.dispatchEvent(compositionEvent);
ok(!gEditorIMESupport.composing, "Composition shouldn't be started with a created compositionupdate event (" + aEventInterface + ")");
is(gInputElement.value, "", "Input element shouldn't be modified with a created compositionupdate event (" + aEventInterface + ")");
compositionEvent = document.createEvent(aEventInterface);
if (compositionEvent.initCompositionEvent) {
compositionEvent.initCompositionEvent("compositionend", true, false, window, "abc", "");
} else if (compositionEvent.initMouseEvent) {
compositionEvent.initMouseEvent("compositionend", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
gInputElement.dispatchEvent(compositionEvent);
ok(!gEditorIMESupport.composing, "Composition shouldn't be committed with a created compositionend event (" + aEventInterface + ")");
is(gInputElement.value, "", "Input element shouldn't be committed with a created compositionend event (" + aEventInterface + ")");
}
function doTests()
{
gInputElement.focus();
gEditorIMESupport = getEditorIMESupport(gInputElement);
testNotGenerateCompositionByCreatedEvents("CompositionEvent");
testNotGenerateCompositionByCreatedEvents("MouseEvent");
SimpleTest.finish();
}
SimpleTest.waitForFocus(doTests);
</script>
</body>
</html>

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

@ -258,7 +258,7 @@ ffs (int x)
__asm _emit ((__COUNTER__>>8) & 0xff) \
__asm _emit ((__COUNTER__>>16) & 0xff)\
__asm _emit ((__COUNTER__>>24) & 0xff)\
__asm lea eax, file \
__asm lea eax, dword ptr file \
__asm __internal_skip_line_no: \
}; \
} while (0)

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

@ -150,19 +150,37 @@ void GrallocImage::SetData(const GrallocData& aData)
*/
static void
ConvertYVU420SPToRGB565(void *aYData, uint32_t aYStride,
void *aUVData, uint32_t aUVStride,
void *aUData, void *aVData, uint32_t aUVStride,
void *aOut,
uint32_t aWidth, uint32_t aHeight)
{
uint8_t *y = (uint8_t*)aYData;
int8_t *uv = (int8_t*)aUVData;
bool isCbCr;
int8_t *uv;
if (aUData < aVData) {
// The color format is YCbCr
isCbCr = true;
uv = (int8_t*)aUData;
} else {
// The color format is YCrCb
isCbCr = false;
uv = (int8_t*)aVData;
}
uint16_t *rgb = (uint16_t*)aOut;
for (size_t i = 0; i < aHeight; i++) {
for (size_t j = 0; j < aWidth; j++) {
int8_t d = uv[j | 1] - 128;
int8_t e = uv[j & ~1] - 128;
int8_t d, e;
if (isCbCr) {
d = uv[j & ~1] - 128;
e = uv[j | 1] - 128;
} else {
d = uv[j | 1] - 128;
e = uv[j & ~1] - 128;
}
// Constants taken from https://en.wikipedia.org/wiki/YUV
int32_t r = (298 * y[j] + 409 * e + 128) >> 11;
@ -183,113 +201,192 @@ ConvertYVU420SPToRGB565(void *aYData, uint32_t aYStride,
}
}
/**
* Converts the format of vendor-specific YVU420(planar and semi-planar)
* with the help of GraphicBuffer::lockYCbCr. In this way, we can convert
* the YUV color format without awaring actual definition/enumeration
* of vendor formats.
*/
static status_t
ConvertVendorYUVFormatToRGB565(android::sp<GraphicBuffer>& aBuffer,
gfx::DataSourceSurface *aSurface,
gfx::DataSourceSurface::MappedSurface *aMappedSurface)
{
status_t rv = BAD_VALUE;
#if ANDROID_VERSION >= 18
android_ycbcr ycbcr;
// Check if the vendor provides explicit addresses of Y/Cb/Cr buffer from lockYCbCr
rv = aBuffer->lockYCbCr(android::GraphicBuffer::USAGE_SW_READ_OFTEN, &ycbcr);
if (rv != OK) {
NS_WARNING("Couldn't lock graphic buffer using lockYCbCr()");
return rv;
}
GraphicBufferAutoUnlock unlock(aBuffer);
uint32_t width = aSurface->GetSize().width;
uint32_t height = aSurface->GetSize().height;
if (ycbcr.chroma_step == 2) {
// From the system/core/include/system/graphics.h
// @chroma_step is the distance in bytes from one chroma pixel value to
// the next. This is 2 bytes for semiplanar (because chroma values are
// interleaved and each chroma value is one byte) and 1 for planar.
ConvertYVU420SPToRGB565(ycbcr.y, ycbcr.ystride,
ycbcr.cb, ycbcr.cr, ycbcr.cstride,
aMappedSurface->mData,
width, height);
} else {
layers::PlanarYCbCrData ycbcrData;
ycbcrData.mYChannel = static_cast<uint8_t*>(ycbcr.y);
ycbcrData.mYStride = ycbcr.ystride;
ycbcrData.mYSize = aSurface->GetSize();
ycbcrData.mCbChannel = static_cast<uint8_t*>(ycbcr.cb);
ycbcrData.mCrChannel = static_cast<uint8_t*>(ycbcr.cr);
ycbcrData.mCbCrStride = ycbcr.cstride;
ycbcrData.mCbCrSize = aSurface->GetSize() / 2;
ycbcrData.mPicSize = aSurface->GetSize();
gfx::ConvertYCbCrToRGB(ycbcrData,
aSurface->GetFormat(),
aSurface->GetSize(),
aMappedSurface->mData,
aMappedSurface->mStride);
}
#endif
return rv;
}
static status_t
ConvertOmxYUVFormatToRGB565(android::sp<GraphicBuffer>& aBuffer,
gfx::DataSourceSurface *aSurface,
gfx::DataSourceSurface::MappedSurface *aMappedSurface,
const layers::PlanarYCbCrData& aYcbcrData,
int aOmxFormat)
{
if (!aOmxFormat) {
NS_WARNING("Unknown color format");
return BAD_VALUE;
}
status_t rv;
uint8_t *buffer;
rv = aBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void **>(&buffer));
if (rv != OK) {
NS_WARNING("Couldn't lock graphic buffer");
return BAD_VALUE;
}
GraphicBufferAutoUnlock unlock(aBuffer);
uint32_t format = aBuffer->getPixelFormat();
uint32_t width = aSurface->GetSize().width;
uint32_t height = aSurface->GetSize().height;
if (format == GrallocImage::HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO) {
// The Adreno hardware decoder aligns image dimensions to a multiple of 32,
// so we have to account for that here
uint32_t alignedWidth = ALIGN(width, 32);
uint32_t alignedHeight = ALIGN(height, 32);
uint32_t uvOffset = ALIGN(alignedHeight * alignedWidth, 4096);
uint32_t uvStride = 2 * ALIGN(width / 2, 32);
ConvertYVU420SPToRGB565(buffer, alignedWidth,
buffer + uvOffset + 1,
buffer + uvOffset,
uvStride,
aMappedSurface->mData,
width, height);
return OK;
}
if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
uint32_t uvOffset = height * width;
ConvertYVU420SPToRGB565(buffer, width,
buffer + uvOffset + 1,
buffer + uvOffset,
width,
aMappedSurface->mData,
width, height);
return OK;
}
if (format == HAL_PIXEL_FORMAT_YV12) {
gfx::ConvertYCbCrToRGB(aYcbcrData,
aSurface->GetFormat(),
aSurface->GetSize(),
aSurface->GetData(),
aSurface->Stride());
return OK;
}
android::ColorConverter colorConverter((OMX_COLOR_FORMATTYPE)aOmxFormat,
OMX_COLOR_Format16bitRGB565);
if (!colorConverter.isValid()) {
NS_WARNING("Invalid color conversion");
return BAD_VALUE;
}
rv = colorConverter.convert(buffer, width, height,
0, 0, width - 1, height - 1 /* source crop */,
aMappedSurface->mData, width, height,
0, 0, width - 1, height - 1 /* dest crop */);
if (rv) {
NS_WARNING("OMX color conversion failed");
return BAD_VALUE;
}
return OK;
}
TemporaryRef<gfx::SourceSurface>
GrallocImage::GetAsSourceSurface()
{
if (!mTextureClient) {
return nullptr;
}
android::sp<GraphicBuffer> graphicBuffer =
mTextureClient->GetGraphicBuffer();
void *buffer;
int32_t rv =
graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_OFTEN, &buffer);
if (rv) {
NS_WARNING("Couldn't lock graphic buffer");
return nullptr;
}
GraphicBufferAutoUnlock unlock(graphicBuffer);
uint32_t format = graphicBuffer->getPixelFormat();
uint32_t omxFormat = 0;
for (int i = 0; sColorIdMap[i]; i += 2) {
if (sColorIdMap[i] == format) {
omxFormat = sColorIdMap[i + 1];
break;
}
}
if (!omxFormat) {
NS_WARNING("Unknown color format");
return nullptr;
}
RefPtr<gfx::DataSourceSurface> surface
= gfx::Factory::CreateDataSourceSurface(GetSize(), gfx::SurfaceFormat::R5G6B5);
RefPtr<gfx::DataSourceSurface> surface =
gfx::Factory::CreateDataSourceSurface(GetSize(), gfx::SurfaceFormat::R5G6B5);
if (!surface) {
NS_WARNING("Failed to create SourceSurface.");
return nullptr;
}
uint32_t width = GetSize().width;
uint32_t height = GetSize().height;
gfx::DataSourceSurface::MappedSurface mappedSurface;
if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
NS_WARNING("Could not map DataSourceSurface");
return nullptr;
}
if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO) {
// The Adreno hardware decoder aligns image dimensions to a multiple of 32,
// so we have to account for that here
uint32_t alignedWidth = ALIGN(width, 32);
uint32_t alignedHeight = ALIGN(height, 32);
uint32_t uvOffset = ALIGN(alignedHeight * alignedWidth, 4096);
uint32_t uvStride = 2 * ALIGN(width / 2, 32);
uint8_t* buffer_as_bytes = static_cast<uint8_t*>(buffer);
ConvertYVU420SPToRGB565(buffer, alignedWidth,
buffer_as_bytes + uvOffset, uvStride,
mappedSurface.mData,
width, height);
int32_t rv;
uint32_t omxFormat = 0;
omxFormat = GrallocImage::GetOmxFormat(graphicBuffer->getPixelFormat());
if (!omxFormat) {
rv = ConvertVendorYUVFormatToRGB565(graphicBuffer, surface, &mappedSurface);
surface->Unmap();
if (rv != OK) {
NS_WARNING("Unknown color format");
return nullptr;
}
return surface;
}
if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
uint32_t uvOffset = height * width;
ConvertYVU420SPToRGB565(buffer, width,
buffer + uvOffset, width,
mappedSurface.mData,
width, height);
surface->Unmap();
return surface;
}
if (format == HAL_PIXEL_FORMAT_YV12) {
gfx::ConvertYCbCrToRGB(mData,
surface->GetFormat(),
mSize,
surface->GetData(),
surface->Stride());
surface->Unmap();
return surface;
}
android::ColorConverter colorConverter((OMX_COLOR_FORMATTYPE)omxFormat,
OMX_COLOR_Format16bitRGB565);
if (!colorConverter.isValid()) {
NS_WARNING("Invalid color conversion");
surface->Unmap();
return nullptr;
}
rv = colorConverter.convert(buffer, width, height,
0, 0, width - 1, height - 1 /* source crop */,
mappedSurface.mData, width, height,
0, 0, width - 1, height - 1 /* dest crop */);
rv = ConvertOmxYUVFormatToRGB565(graphicBuffer, surface, &mappedSurface, mData, omxFormat);
surface->Unmap();
if (rv) {
NS_WARNING("OMX color conversion failed");
if (rv != OK) {
return nullptr;
}

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

@ -107,6 +107,20 @@ public:
return (static_cast<ANativeWindowBuffer*>(GetNativeBuffer()))->usage;
}
static int GetOmxFormat(int aFormat)
{
uint32_t omxFormat = 0;
for (int i = 0; sColorIdMap[i]; i += 2) {
if (sColorIdMap[i] == aFormat) {
omxFormat = sColorIdMap[i + 1];
break;
}
}
return omxFormat;
}
private:
RefPtr<GrallocTextureClientOGL> mTextureClient;
};

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

@ -116,27 +116,30 @@ AppendToString(std::stringstream& aStream, const nsIntSize& sz,
void
AppendToString(std::stringstream& aStream, const FrameMetrics& m,
const char* pfx, const char* sfx)
const char* pfx, const char* sfx, bool detailed)
{
aStream << pfx;
AppendToString(aStream, m.mViewport, "{ viewport=");
AppendToString(aStream, m.mCompositionBounds, " cb=");
AppendToString(aStream, m.GetScrollOffset(), " viewportScroll=");
AppendToString(aStream, m.mDisplayPort, " displayport=");
AppendToString(aStream, m.mCriticalDisplayPort, " critdp=");
AppendToString(aStream, m.mScrollableRect, " scrollableRect=");
AppendToString(aStream, m.GetScrollId(), " scrollId=", " }");
aStream << sfx;
}
void
AppendToString(std::stringstream& aStream, const IntSize& size,
const char* pfx, const char* sfx)
{
aStream << pfx;
aStream << nsPrintfCString(
"(width=%d, height=%d)",
size.width, size.height).get();
AppendToString(aStream, m.mCompositionBounds, "{ cb=");
AppendToString(aStream, m.mScrollableRect, " sr=");
AppendToString(aStream, m.GetScrollOffset(), " s=");
AppendToString(aStream, m.mDisplayPort, " dp=");
AppendToString(aStream, m.mCriticalDisplayPort, " cdp=");
if (!detailed) {
aStream << nsPrintfCString(" z=%.3f }", m.GetZoom().scale).get();
} else {
AppendToString(aStream, m.GetDisplayPortMargins(), " dpm=");
aStream << nsPrintfCString(" um=%d", m.GetUseDisplayPortMargins()).get();
AppendToString(aStream, m.GetRootCompositionSize(), " rcs=");
AppendToString(aStream, m.mViewport, " v=");
aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)",
m.mDevPixelsPerCSSPixel.scale, m.mResolution.scale,
m.mCumulativeResolution.scale, m.GetZoom().scale,
m.mTransformScale.scale).get();
aStream << nsPrintfCString(" u=(%d %lu)",
m.GetScrollOffsetUpdated(), m.GetScrollGeneration()).get();
aStream << nsPrintfCString(" i=(%ld %lld) }",
m.GetPresShellId(), m.GetScrollId()).get();
}
aStream << sfx;
}

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

@ -97,11 +97,43 @@ AppendToString(std::stringstream& aStream, const nsIntSize& sz,
void
AppendToString(std::stringstream& aStream, const FrameMetrics& m,
const char* pfx="", const char* sfx="");
const char* pfx="", const char* sfx="", bool detailed = false);
template<class T>
void
AppendToString(std::stringstream& aStream, const mozilla::gfx::IntSize& size,
const char* pfx="", const char* sfx="");
AppendToString(std::stringstream& aStream, const mozilla::gfx::MarginTyped<T>& m,
const char* pfx="", const char* sfx="")
{
aStream << pfx;
aStream << nsPrintfCString(
"(l=%f, t=%f, r=%f, b=%f)",
m.left, m.top, m.right, m.bottom).get();
aStream << sfx;
}
template<class T>
void
AppendToString(std::stringstream& aStream, const mozilla::gfx::SizeTyped<T>& sz,
const char* pfx="", const char* sfx="")
{
aStream << pfx;
aStream << nsPrintfCString(
"(w=%f, h=%f)",
sz.width, sz.height).get();
aStream << sfx;
}
template<class T>
void
AppendToString(std::stringstream& aStream, const mozilla::gfx::IntSizeTyped<T>& sz,
const char* pfx="", const char* sfx="")
{
aStream << pfx;
aStream << nsPrintfCString(
"(w=%d, h=%d)",
sz.width, sz.height).get();
aStream << sfx;
}
void
AppendToString(std::stringstream& aStream, const mozilla::gfx::Matrix4x4& m,

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

@ -1084,7 +1084,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
// Hit testing for this layer takes place in our parent layer coordinates,
// since the composition bounds (used to initialize the visible rect against
// which we hit test are in those coordinates).
gfxPoint hitTestPointForThisLayer = ancestorUntransform.ProjectPoint(aHitTestPoint);
gfxPointH3D hitTestPointForThisLayer = ancestorUntransform.ProjectPoint(aHitTestPoint);
APZCTM_LOG("Untransformed %f %f to transient coordinates %f %f for hit-testing APZC %p\n",
aHitTestPoint.x, aHitTestPoint.y,
hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc);
@ -1096,7 +1096,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
gfx3DMatrix childUntransform = ancestorUntransform
* aApzc->GetCSSTransform().Inverse()
* gfx3DMatrix(aApzc->GetCurrentAsyncTransform()).Inverse();
gfxPoint hitTestPointForChildLayers = childUntransform.ProjectPoint(aHitTestPoint);
gfxPointH3D hitTestPointForChildLayers = childUntransform.ProjectPoint(aHitTestPoint);
APZCTM_LOG("Untransformed %f %f to layer coordinates %f %f for APZC %p\n",
aHitTestPoint.x, aHitTestPoint.y,
hitTestPointForChildLayers.x, hitTestPointForChildLayers.y, aApzc);
@ -1104,14 +1104,17 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
AsyncPanZoomController* result = nullptr;
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
AsyncPanZoomController* match = GetAPZCAtPoint(child, hitTestPointForChildLayers, aOutInOverscrolledApzc);
if (match) {
result = match;
break;
if (hitTestPointForChildLayers.HasPositiveWCoord()) {
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
AsyncPanZoomController* match = GetAPZCAtPoint(child, hitTestPointForChildLayers.As2DPoint(), aOutInOverscrolledApzc);
if (match) {
result = match;
break;
}
}
}
if (!result && aApzc->VisibleRegionContains(ViewAs<ParentLayerPixel>(hitTestPointForThisLayer))) {
if (!result && hitTestPointForThisLayer.HasPositiveWCoord() &&
aApzc->VisibleRegionContains(ViewAs<ParentLayerPixel>(hitTestPointForThisLayer.As2DPoint()))) {
APZCTM_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n",
hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc);
result = aApzc;

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

@ -62,24 +62,21 @@
// #define APZC_ENABLE_RENDERTRACE
#define APZC_LOG(...)
// #define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
#define APZC_LOG_FM(fm, prefix, ...) \
APZC_LOG(prefix ":" \
" i=(%ld %lld) cb=(%.3f %.3f %.3f %.3f) rcs=(%.3f %.3f) dp=(%.3f %.3f %.3f %.3f) dpm=(%.3f %.3f %.3f %.3f) um=%d " \
"v=(%.3f %.3f %.3f %.3f) s=(%.3f %.3f) sr=(%.3f %.3f %.3f %.3f) z(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f) u=(%d %lu)\n", \
__VA_ARGS__, \
fm.GetPresShellId(), fm.GetScrollId(), \
fm.mCompositionBounds.x, fm.mCompositionBounds.y, fm.mCompositionBounds.width, fm.mCompositionBounds.height, \
fm.GetRootCompositionSize().width, fm.GetRootCompositionSize().height, \
fm.mDisplayPort.x, fm.mDisplayPort.y, fm.mDisplayPort.width, fm.mDisplayPort.height, \
fm.GetDisplayPortMargins().top, fm.GetDisplayPortMargins().right, fm.GetDisplayPortMargins().bottom, fm.GetDisplayPortMargins().left, \
fm.GetUseDisplayPortMargins() ? 1 : 0, \
fm.mViewport.x, fm.mViewport.y, fm.mViewport.width, fm.mViewport.height, \
fm.GetScrollOffset().x, fm.GetScrollOffset().y, \
fm.mScrollableRect.x, fm.mScrollableRect.y, fm.mScrollableRect.width, fm.mScrollableRect.height, \
fm.mDevPixelsPerCSSPixel.scale, fm.mResolution.scale, fm.mCumulativeResolution.scale, fm.GetZoom().scale, fm.mTransformScale.scale, \
fm.GetScrollOffsetUpdated(), fm.GetScrollGeneration()); \
#define ENABLE_APZC_LOGGING 0
// #define ENABLE_APZC_LOGGING 1
#if ENABLE_APZC_LOGGING
# define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
# define APZC_LOG_FM(fm, prefix, ...) \
{ std::stringstream ss; \
ss << nsPrintfCString(prefix, __VA_ARGS__).get(); \
AppendToString(ss, fm, ":", "", true); \
APZC_LOG("%s", ss.str().c_str()); \
}
#else
# define APZC_LOG(...)
# define APZC_LOG_FM(fm, prefix, ...)
#endif
// Static helper functions
namespace {

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

@ -753,89 +753,88 @@ gfx3DMatrix::ProjectTo2D()
return *this;
}
gfxPoint gfx3DMatrix::ProjectPoint(const gfxPoint& aPoint) const
gfxPointH3D gfx3DMatrix::ProjectPoint(const gfxPoint& aPoint) const
{
// Define a ray of the form P + Ut where t is a real number
// w is assumed to always be 1 when transforming 3d points with our
// 4x4 matrix.
// p is our click point, q is another point on the same ray.
//
// Note: since the transformation is a general projective transformation and is not
// necessarily affine, we can't just take a unit vector u, back-transform it, and use
// it as unit vector on the back-transformed ray. Instead, we really must take two points
// on the ray and back-transform them.
gfxPoint3D p(aPoint.x, aPoint.y, 0);
gfxPoint3D q(aPoint.x, aPoint.y, 1);
// Find a value for z that will transform to 0.
// Back transform the vectors (using w = 1) and normalize
// back into 3d vectors by dividing by the w component.
gfxPoint3D pback = Transform3D(p);
gfxPoint3D qback = Transform3D(q);
gfxPoint3D uback = qback - pback;
// The transformed value of z is computed as:
// z' = aPoint.x * _13 + aPoint.y * _23 + z * _33 + _43;
// Find the point where the back transformed line intersects z=0
// and find t.
// Solving for z when z' = 0 gives us:
float z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
// Compute the transformed point
return Transform4D(gfxPointH3D(aPoint.x, aPoint.y, z, 1));
}
gfxPointH3D ComputePerspectivePlaneIntercept(const gfxPointH3D& aFirst,
const gfxPointH3D& aSecond)
{
// FIXME: See bug 1035611
// Since we can't easily deal with points as w=0 (since we divide by w), we
// approximate this by finding a point with w just greater than 0. Unfortunately
// this is a tradeoff between accuracy and floating point precision.
float t = -pback.z / uback.z;
// We want to interpolate aFirst and aSecond to find a point as close to
// the positive side of the w=0 plane as possible.
gfxPoint result(pback.x + t*uback.x, pback.y + t*uback.y);
// Since we know what we want the w component to be, we can rearrange the
// interpolation equation and solve for t.
float w = 0.00001f;
float t = (w - aFirst.w) / (aSecond.w - aFirst.w);
return result;
// Use t to find the remainder of the components
return aFirst + (aSecond - aFirst) * t;
}
gfxRect gfx3DMatrix::ProjectRectBounds(const gfxRect& aRect) const
{
gfxPoint points[4];
gfxPointH3D points[4];
points[0] = ProjectPoint(aRect.TopLeft());
points[1] = ProjectPoint(aRect.TopRight());
points[2] = ProjectPoint(aRect.BottomLeft());
points[3] = ProjectPoint(aRect.BottomRight());
gfxFloat min_x, max_x;
gfxFloat min_y, max_y;
gfxFloat min_x = std::numeric_limits<gfxFloat>::max();
gfxFloat min_y = std::numeric_limits<gfxFloat>::max();
gfxFloat max_x = -std::numeric_limits<gfxFloat>::max();
gfxFloat max_y = -std::numeric_limits<gfxFloat>::max();
min_x = max_x = points[0].x;
min_y = max_y = points[0].y;
bool foundPoint = false;
for (int i=0; i<4; i++) {
// Only use points that exist above the w=0 plane
if (points[i].HasPositiveWCoord()) {
foundPoint = true;
gfxPoint point2d = points[i].As2DPoint();
min_x = min(point2d.x, min_x);
max_x = max(point2d.x, max_x);
min_y = min(point2d.y, min_y);
max_y = max(point2d.y, max_y);
}
for (int i=1; i<4; i++) {
min_x = min(points[i].x, min_x);
max_x = max(points[i].x, max_x);
min_y = min(points[i].y, min_y);
max_y = max(points[i].y, max_y);
int next = (i == 3) ? 0 : i + 1;
if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
// If the line between two points crosses the w=0 plane, then interpolate a point
// as close to the w=0 plane as possible and use that instead.
gfxPointH3D intercept = ComputePerspectivePlaneIntercept(points[i], points[next]);
MOZ_ASSERT(intercept.HasPositiveWCoord());
gfxPoint point2d = intercept.As2DPoint();
min_x = min(point2d.x, min_x);
max_x = max(point2d.x, max_x);
min_y = min(point2d.y, min_y);
max_y = max(point2d.y, max_y);
}
}
if (!foundPoint) {
return gfxRect(0, 0, 0, 0);
}
return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
}
gfxRect gfx3DMatrix::UntransformBounds(const gfxRect& aRect, const gfxRect& aChildBounds) const
{
if (Is2D()) {
return Inverse().TransformBounds(aRect);
}
gfxRect bounds = TransformBounds(aChildBounds);
gfxRect rect = aRect.Intersect(bounds);
return Inverse().ProjectRectBounds(rect);
}
bool gfx3DMatrix::UntransformPoint(const gfxPoint& aPoint, const gfxRect& aChildBounds, gfxPoint* aOut) const
{
if (Is2D()) {
*aOut = Inverse().Transform(aPoint);
return true;
}
gfxRect bounds = TransformBounds(aChildBounds);
if (!bounds.Contains(aPoint)) {
return false;
}
*aOut = Inverse().ProjectPoint(aPoint);
return true;
}
gfxPoint3D gfx3DMatrix::GetNormalVector() const
{
// Define a plane in transformed space as the transformations

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

@ -247,29 +247,13 @@ public:
gfxPointH3D Transform4D(const gfxPointH3D& aPoint) const;
gfxPointH3D TransposeTransform4D(const gfxPointH3D& aPoint) const;
gfxPoint ProjectPoint(const gfxPoint& aPoint) const;
/**
* Given a point (x,y) find a value for z such that (x,y,z,1) transforms
* into (x',y',0,w') and returns the latter.
*/
gfxPointH3D ProjectPoint(const gfxPoint& aPoint) const;
gfxRect ProjectRectBounds(const gfxRect& aRect) const;
/**
* Transforms a point by the inverse of this matrix. In the case of perspective transforms, some screen
* points have no equivalent in the untransformed plane (if they exist past the vanishing point). To
* avoid this, we need to specify the bounds of the untransformed plane to restrict the search area.
*
* @param aPoint Point to untransform.
* @param aChildBounds Bounds of the untransformed plane.
* @param aOut Untransformed point.
* @return Returns true if a point was found within a ChildBounds, false otherwise.
*/
bool UntransformPoint(const gfxPoint& aPoint, const gfxRect& aChildBounds, gfxPoint* aOut) const;
/**
* Same as UntransformPoint, but untransforms a rect and returns the bounding rect of the result.
* Returns an empty rect if the result doesn't intersect aChildBounds.
*/
gfxRect UntransformBounds(const gfxRect& aRect, const gfxRect& aChildBounds) const;
/**
* Inverts this matrix, if possible. Otherwise, the matrix is left
* unchanged.

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

@ -8,12 +8,19 @@
#include "mozilla/gfx/BasePoint4D.h"
#include "gfxTypes.h"
#include "gfxPoint.h"
struct gfxPointH3D : public mozilla::gfx::BasePoint4D<float, gfxPointH3D> {
typedef mozilla::gfx::BasePoint4D<float, gfxPointH3D> Super;
gfxPointH3D() : Super() {}
gfxPointH3D(float aX, float aY, float aZ, float aW) : Super(aX, aY, aZ, aW) {}
bool HasPositiveWCoord() { return w > 0; }
gfxPoint As2DPoint() {
return gfxPoint(x / w, y / w);
}
};
#endif /* GFX_POINTH3D_H */

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