Merge mozilla-central and fx-team

This commit is contained in:
Ed Morley 2012-08-17 19:22:11 +01:00
commit 16f4f94306
235 changed files with 4116 additions and 1523 deletions

View File

@ -488,6 +488,13 @@ pref("javascript.options.mem.log", true);
// Increase mark slice time from 10ms to 30ms
pref("javascript.options.mem.gc_incremental_slice_ms", 30);
pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 120);
pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 101);
pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
pref("javascript.options.mem.high_water_mark", 16);
// Show/Hide scrollbars when active/inactive
pref("ui.showHideScrollbars", 1);

View File

@ -372,6 +372,7 @@ Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
url: msg.uri,
origin: origin,
manifest: msg.manifest,
isActivity: (msg.type == 'activity'),
target: msg.target
});
}, 'system-messages-open-app', false);

View File

@ -1,3 +1,5 @@
. $topsrcdir/build/macosx/common
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
@ -16,7 +18,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j12"
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
ac_add_options --with-ccache
# B2G Stuff
ac_add_options --enable-application=b2g

View File

@ -253,9 +253,6 @@ var SocialToolbar = {
init: function SocialToolbar_init() {
document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
let notifBrowser = document.getElementById("social-notification-browser");
notifBrowser.docShell.isAppTab = true;
let removeItem = document.getElementById("social-remove-menuitem");
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
let label = gNavigatorBundle.getFormattedString("social.remove.label",
@ -282,6 +279,14 @@ var SocialToolbar = {
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
this.button.hidden = !Social.uiVisible;
if (!Social.provider.profile || !Social.provider.profile.userName) {
["social-notification-box",
"social-status-iconbox"].forEach(function removeChildren(parentId) {
let parent = document.getElementById(parentId);
while(parent.hasChildNodes())
parent.removeChild(parent.firstChild);
});
}
},
updateProfile: function SocialToolbar_updateProfile() {
@ -306,42 +311,73 @@ var SocialToolbar = {
updateButton: function SocialToolbar_updateButton() {
this.updateButtonHiddenState();
let provider = Social.provider;
// if there are no ambient icons, we collapse them in the following loop
let iconNames = Object.keys(provider.ambientNotificationIcons);
let iconBox = document.getElementById("social-status-iconbox");
for (var i = 0; i < iconBox.childNodes.length; i++) {
let iconContainer = iconBox.childNodes[i];
if (i > iconNames.length - 1) {
iconContainer.collapsed = true;
continue;
let notifBox = document.getElementById("social-notification-box");
let notifBrowsers = document.createDocumentFragment();
let iconContainers = document.createDocumentFragment();
for each(let name in iconNames) {
let icon = provider.ambientNotificationIcons[name];
let notifBrowserId = "social-status-" + icon.name;
let notifBrowser = document.getElementById(notifBrowserId);
if (!notifBrowser) {
notifBrowser = document.createElement("iframe");
notifBrowser.setAttribute("type", "content");
notifBrowser.setAttribute("id", notifBrowserId);
notifBrowsers.appendChild(notifBrowser);
}
notifBrowser.setAttribute("origin", provider.origin);
if (notifBrowser.getAttribute("src") != icon.contentPanel)
notifBrowser.setAttribute("src", icon.contentPanel);
iconContainer.collapsed = false;
let icon = provider.ambientNotificationIcons[iconNames[i]];
let iconImage = iconContainer.firstChild;
let iconCounter = iconImage.nextSibling;
iconImage.setAttribute("contentPanel", icon.contentPanel);
iconImage.setAttribute("src", icon.iconURL);
if (iconCounter.firstChild)
iconCounter.removeChild(iconCounter.firstChild);
if (icon.counter) {
iconCounter.appendChild(document.createTextNode(icon.counter));
iconCounter.collapsed = false;
let iconId = "social-notification-icon-" + icon.name;
let iconContainer = document.getElementById(iconId);
let iconImage, iconCounter;
if (iconContainer) {
iconImage = iconContainer.getElementsByClassName("social-notification-icon-image")[0];
iconCounter = iconContainer.getElementsByClassName("social-notification-icon-counter")[0];
} else {
iconCounter.collapsed = true;
iconContainer = document.createElement("box");
iconContainer.setAttribute("id", iconId);
iconContainer.classList.add("social-notification-icon-container");
iconContainer.addEventListener("click", function (e) { SocialToolbar.showAmbientPopup(iconContainer); }, false);
iconImage = document.createElement("image");
iconImage.classList.add("social-notification-icon-image");
iconImage = iconContainer.appendChild(iconImage);
iconCounter = document.createElement("box");
iconCounter.classList.add("social-notification-icon-counter");
iconCounter.appendChild(document.createTextNode(""));
iconCounter = iconContainer.appendChild(iconCounter);
iconContainers.appendChild(iconContainer);
}
if (iconImage.getAttribute("src") != icon.iconURL)
iconImage.setAttribute("src", icon.iconURL);
iconImage.setAttribute("notifBrowserId", notifBrowserId);
iconCounter.collapsed = !icon.counter;
iconCounter.firstChild.textContent = icon.counter || "";
}
notifBox.appendChild(notifBrowsers);
iconBox.appendChild(iconContainers);
let browserIter = notifBox.firstElementChild;
while (browserIter) {
browserIter.docShell.isAppTab = true;
browserIter = browserIter.nextElementSibling;
}
},
showAmbientPopup: function SocialToolbar_showAmbientPopup(iconContainer) {
let iconImage = iconContainer.firstChild;
let panel = document.getElementById("social-notification-panel");
let notifBrowser = document.getElementById("social-notification-browser");
let notifBox = document.getElementById("social-notification-box");
let notifBrowser = document.getElementById(iconImage.getAttribute("notifBrowserId"));
panel.hidden = false;
@ -349,30 +385,36 @@ var SocialToolbar = {
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
// Need to handle dynamic sizing
let doc = notifBrowser.contentDocument;
if (!doc) {
return;
}
// "notif" is an implementation detail that we should get rid of
// eventually
let body = doc.getElementById("notif") || (doc.body && doc.body.firstChild);
if (!body)
let body = doc.getElementById("notif") || doc.body;
if (!body || !body.firstChild) {
return;
let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
notifBrowser.style.width = body.scrollWidth + "px";
notifBrowser.style.height = h + "px";
}
// Clear dimensions on all browsers so the panel size will
// only use the selected browser.
let browserIter = notifBox.firstElementChild;
while (browserIter) {
browserIter.hidden = (browserIter != notifBrowser);
browserIter = browserIter.nextElementSibling;
}
let [height, width] = [body.firstChild.offsetHeight || 300, 330];
notifBrowser.style.width = width + "px";
notifBrowser.style.height = height + "px";
}
notifBrowser.addEventListener("DOMContentLoaded", function onload() {
notifBrowser.removeEventListener("DOMContentLoaded", onload);
sizePanelToContent();
});
sizePanelToContent();
panel.addEventListener("popuphiding", function onpopuphiding() {
panel.removeEventListener("popuphiding", onpopuphiding);
// unload the panel
SocialToolbar.button.removeAttribute("open");
notifBrowser.setAttribute("src", "about:blank");
});
notifBrowser.setAttribute("origin", Social.provider.origin);
notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
this.button.setAttribute("open", "true");
panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
}

View File

@ -269,7 +269,7 @@
</panel>
<panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
<browser id="social-notification-browser" type="content" flex="1"/>
<box id="social-notification-box" flex="1"></box>
</panel>
<menupopup id="inspector-node-popup">
@ -685,21 +685,6 @@
</menupopup>
</button>
<hbox id="social-status-iconbox" flex="1">
<box class="social-notification-icon-container" collapsed="true"
onclick="SocialToolbar.showAmbientPopup(this);">
<image class="social-notification-icon-image"/>
<box class="social-notification-icon-counter" collapsed="true"/>
</box>
<box class="social-notification-icon-container" collapsed="true"
onclick="SocialToolbar.showAmbientPopup(this);">
<image class="social-notification-icon-image"/>
<box class="social-notification-icon-counter" collapsed="true"/>
</box>
<box class="social-notification-icon-container" collapsed="true"
onclick="SocialToolbar.showAmbientPopup(this);">
<image class="social-notification-icon-image"/>
<box class="social-notification-icon-counter" collapsed="true"/>
</box>
</hbox>
</hbox>
</toolbaritem>

View File

@ -64,6 +64,9 @@ endif
# browser_pageInfo.js + feed_tab.html is disabled for leaking (bug 767896)
# browser_social_shareButton.js is disabled for not properly
# tearing down the social providers (bug 780010).
_BROWSER_FILES = \
head.js \
browser_typeAheadFind.js \
@ -156,7 +159,6 @@ _BROWSER_FILES = \
browser_bug749738.js \
browser_bug763468.js \
browser_bug767836.js \
browser_social_shareButton.js \
browser_canonizeURL.js \
browser_customize.js \
browser_findbarClose.js \

View File

@ -29,7 +29,7 @@ var tests = {
function triggerIconPanel() {
let statusIcons = document.getElementById("social-status-iconbox");
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
ok(!statusIcons.firstChild.hidden, "status icon is visible");
// Click the button to trigger its contentPanel
let panel = document.getElementById("social-notification-panel");
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});

View File

@ -62,7 +62,7 @@ var tests = {
ok(userButton.hidden, "username is not visible");
let ambience = document.getElementById("social-status-iconbox").firstChild;
while (ambience) {
ok(ambience.collapsed, "ambient icon is collapsed");
ok(ambience.collapsed, "ambient icon (" + ambience.id + ") is collapsed");
ambience = ambience.nextSibling;
}

View File

@ -5796,7 +5796,7 @@ MOZ_ARG_DISABLE_BOOL(crashreporter,
if test -n "$MOZ_CRASHREPORTER"; then
AC_DEFINE(MOZ_CRASHREPORTER)
if (test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS") && \
if test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS" && \
test -z "$SKIP_LIBRARY_CHECKS"; then
PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
AC_SUBST(MOZ_GTHREAD_CFLAGS)
@ -5805,7 +5805,7 @@ if test -n "$MOZ_CRASHREPORTER"; then
MOZ_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter. Use --disable-crashreporter to disable the crash reporter.])])
fi
if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH. Use --disable-crashreporter.])
fi

View File

@ -13,6 +13,7 @@
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
@ -31,6 +32,41 @@ var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
.getService(Components.interfaces.nsIEffectiveTLDService);
// These regexps represent the concrete syntax on the w3 spec as of 7-5-2012
// scheme = <scheme production from RFC 3986>
const R_SCHEME = new RegExp ("([a-zA-Z0-9\\-]+)", 'i');
const R_GETSCHEME = new RegExp ("^" + R_SCHEME.source + "(?=\\:)", 'i');
// scheme-source = scheme ":"
const R_SCHEMESRC = new RegExp ("^" + R_SCHEME.source + "\\:$", 'i');
// host-char = ALPHA / DIGIT / "-"
const R_HOSTCHAR = new RegExp ("[a-zA-Z0-9\\-]", 'i');
// host = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
const R_HOST = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
"+)(\\." + R_HOSTCHAR.source +"+)+)",'i');
// port = ":" ( 1*DIGIT / "*" )
const R_PORT = new RegExp ("(\\:([0-9]+|\\*))", 'i');
// host-source = [ scheme "://" ] host [ port ]
const R_HOSTSRC = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
+ R_HOST.source + ")"
+ R_PORT.source + "?)$", 'i');
// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
// ; ext-host-source is reserved for future use.
const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
// keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
// source-exp = scheme-source / host-source / keyword-source
const R_SOURCEEXP = new RegExp (R_SCHEMESRC.source + "|" +
R_HOSTSRC.source + "|" +
R_KEYWORDSRC.source, 'i');
var gPrefObserver = {
get debugEnabled () {
if (!this._branch)
@ -588,11 +624,8 @@ function CSPSourceList() {
* an instance of CSPSourceList
*/
CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
// Source list is:
// <host-dir-value> ::= <source-list>
// | "'none'"
// <source-list> ::= <source>
// | <source-list>" "<source>
// source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
// / *WSP "'none'" *WSP
/* If self parameter is passed, convert to CSPSource,
unless it is already a CSPSource. */
@ -601,23 +634,33 @@ CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
}
var slObj = new CSPSourceList();
if (aStr === "'none'")
return slObj;
if (aStr === "*") {
slObj._permitAllSources = true;
aStr = aStr.trim();
// w3 specifies case insensitive equality
if (aStr.toUpperCase() === "'NONE'"){
slObj._permitAllSources = false;
return slObj;
}
var tokens = aStr.split(/\s+/);
for (var i in tokens) {
if (tokens[i] === "") continue;
var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
if (!src) {
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource", [tokens[i]]));
if (!R_SOURCEEXP.test(tokens[i])){
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
[tokens[i]]));
continue;
}
slObj._sources.push(src);
var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
if (!src) {
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
[tokens[i]]));
continue;
}
// if a source is a *, then we can permit all sources
if (src.permitAll){
slObj._permitAllSources = true;
return slObj;
} else {
slObj._sources.push(src);
}
}
return slObj;
@ -787,6 +830,9 @@ function CSPSource() {
this._port = undefined;
this._host = undefined;
//when set to true, this allows all source
this._permitAll = false;
// when set to true, this source represents 'self'
this._isSelf = false;
}
@ -924,6 +970,15 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
return null;
}
var sObj = new CSPSource();
sObj._self = self;
// if equal, return does match
if (aStr === "*"){
sObj._permitAll = true;
return sObj;
}
if (!self && enforceSelfChecks) {
CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
return null;
@ -933,12 +988,50 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
self = CSPSource.create(self, undefined, false);
}
var sObj = new CSPSource();
sObj._self = self;
// check for scheme-source match
if (R_SCHEMESRC.test(aStr)){
var schemeSrcMatch = R_GETSCHEME.exec(aStr);
sObj._scheme = schemeSrcMatch[0];
if (!sObj._host) sObj._host = CSPHost.fromString("*");
if (!sObj._port) sObj._port = "*";
return sObj;
}
// take care of 'self' keyword
if (aStr === "'self'") {
if (!self) {
// check for host-source or ext-host-source match
if (R_HOSTSRC.test(aStr) || R_EXTHOSTSRC.test(aStr)){
var schemeMatch = R_GETSCHEME.exec(aStr);
if (!schemeMatch)
sObj._scheme = self.scheme;
else {
sObj._scheme = schemeMatch[0];
}
var hostMatch = R_HOST.exec(aStr);
if (!hostMatch) {
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
return null;
}
sObj._host = CSPHost.fromString(hostMatch[0]);
var portMatch = R_PORT.exec(aStr);
if (!portMatch) {
// gets the default port for the given scheme
defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
if (!defPort) {
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
return null;
}
sObj._port = defPort;
}
else {
// strip the ':' from the port
sObj._port = portMatch[0].substr(1);
}
return sObj;
}
// check for 'self' (case insensitive)
if (aStr.toUpperCase() === "'SELF'"){
if (!self){
CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
return null;
}
@ -946,125 +1039,14 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
sObj._isSelf = true;
return sObj;
}
// We could just create a URI and then send this off to fromURI, but
// there's no way to leave out the scheme or wildcard the port in an nsURI.
// That has to be supported here.
// split it up
var chunks = aStr.split(":");
// If there is only one chunk, it's gotta be a host.
if (chunks.length == 1) {
sObj._host = CSPHost.fromString(chunks[0]);
if (!sObj._host) {
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
return null;
}
// enforce 'self' inheritance
if (enforceSelfChecks) {
// note: the non _scheme accessor checks sObj._self
if (!sObj.scheme || !sObj.port) {
CSPError(CSPLocalizer.getFormatStr("hostSourceWithoutData",[aStr]));
return null;
}
}
return sObj;
}
// If there are two chunks, it's either scheme://host or host:port
// ... but scheme://host can have an empty host.
// ... and host:port can have an empty host
if (chunks.length == 2) {
// is the last bit a port?
if (chunks[1] === "*" || chunks[1].match(/^\d+$/)) {
sObj._port = chunks[1];
// then the previous chunk *must* be a host or empty.
if (chunks[0] !== "") {
sObj._host = CSPHost.fromString(chunks[0]);
if (!sObj._host) {
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
return null;
}
}
// enforce 'self' inheritance
// (scheme:host requires port, host:port does too. Wildcard support is
// only available if the scheme and host are wildcarded)
if (enforceSelfChecks) {
// note: the non _scheme accessor checks sObj._self
if (!sObj.scheme || !sObj.host || !sObj.port) {
CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
return null;
}
}
}
// is the first bit a scheme?
else if (CSPSource.validSchemeName(chunks[0])) {
sObj._scheme = chunks[0];
// then the second bit *must* be a host or empty
if (chunks[1] === "") {
// Allow scheme-only sources! These default to wildcard host/port,
// especially since host and port don't always matter.
// Example: "javascript:" and "data:"
if (!sObj._host) sObj._host = CSPHost.fromString("*");
if (!sObj._port) sObj._port = "*";
} else {
// some host was defined.
// ... remove <= 3 leading slashes (from the scheme) and parse
var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
// ... and parse
sObj._host = CSPHost.fromString(cleanHost);
if (!sObj._host) {
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidHost",[cleanHost]));
return null;
}
}
// enforce 'self' inheritance (scheme-only should be scheme:*:* now, and
// if there was a host provided it should be scheme:host:selfport
if (enforceSelfChecks) {
// note: the non _scheme accessor checks sObj._self
if (!sObj.scheme || !sObj.host || !sObj.port) {
CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
return null;
}
}
}
else {
// AAAH! Don't know what to do! No valid scheme or port!
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
return null;
}
return sObj;
}
// If there are three chunks, we got 'em all!
if (!CSPSource.validSchemeName(chunks[0])) {
CSPError(CSPLocalizer.getFormatStr("couldntParseScheme",[aStr]));
return null;
}
sObj._scheme = chunks[0];
if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
CSPError(CSPLocalizer.getFormatStr("couldntParsePort",[aStr]));
return null;
}
sObj._port = chunks[2];
// ... remove <= 3 leading slashes (from the scheme) and parse
var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
sObj._host = CSPHost.fromString(cleanHost);
return sObj._host ? sObj : null;
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
return null;
};
CSPSource.validSchemeName = function(aStr) {
// <scheme-name> ::= <alpha><scheme-suffix>
// <scheme-suffix> ::= <scheme-chr>
// | <scheme-suffix><scheme-chr>
// <scheme-suffix> ::= <scheme-chr>
// | <scheme-suffix><scheme-chr>
// <scheme-chr> ::= <letter> | <digit> | "+" | "." | "-"
return aStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*$/);
@ -1088,7 +1070,13 @@ CSPSource.prototype = {
return this._host;
},
/**
get permitAll () {
if (this._isSelf && this._self)
return this._self.permitAll;
return this._permitAll;
},
/**
* If this doesn't have a nonstandard port (hard-defined), use the default
* port for this source's scheme. Should never inherit port from 'self'.
*/

View File

@ -8492,10 +8492,13 @@ DispatchFullScreenChange(nsIDocument* aTarget)
NS_IMETHODIMP
nsDocument::MozCancelFullScreen()
{
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
return NS_OK;
// Only perform fullscreen changes if we're running in a webapp
// same-origin to the web app, or if we're in a user generated event
// handler.
if (NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
nsContentUtils::IsRequestFullScreenAllowed()) {
RestorePreviousFullScreenState();
}
RestorePreviousFullScreenState();
return NS_OK;
}
@ -9124,6 +9127,7 @@ nsDocument::RequestFullScreen(Element* aElement,
// trusted and so are automatically approved.
if (!mIsApprovedForFullscreen) {
mIsApprovedForFullscreen =
!Preferences::GetBool("full-screen-api.approval-required") ||
NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
}

View File

@ -288,6 +288,7 @@ NS_INTERFACE_MAP_END
nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
: mOwnerContent(aOwner)
, mDetachedSubdocViews(nullptr)
, mDepthTooGreat(false)
, mIsTopLevelContent(false)
, mDestroyCalled(false)
@ -2377,3 +2378,18 @@ nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
ShowRemoteFrame(nsIntSize(0, 0));
}
void
nsFrameLoader::SetDetachedSubdocView(nsIView* aDetachedViews,
nsIDocument* aContainerDoc)
{
mDetachedSubdocViews = aDetachedViews;
mContainerDocWhileDetached = aContainerDoc;
}
nsIView*
nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
{
NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
return mDetachedSubdocViews;
}

View File

@ -268,6 +268,25 @@ public:
*/
void SetRemoteBrowser(nsITabParent* aTabParent);
/**
* Stashes a detached view on the frame loader. We do this when we're
* destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
* being reframed we'll restore the detached view when it's recreated,
* otherwise we'll discard the old presentation and set the detached
* subdoc view to null. aContainerDoc is the document containing the
* the subdoc frame. This enables us to detect when the containing
* document has changed during reframe, so we can discard the presentation
* in that case.
*/
void SetDetachedSubdocView(nsIView* aDetachedView,
nsIDocument* aContainerDoc);
/**
* Retrieves the detached view and the document containing the view,
* as set by SetDetachedSubdocView().
*/
nsIView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
private:
void SetOwnerContent(mozilla::dom::Element* aContent);
@ -326,6 +345,16 @@ public:
nsRefPtr<nsFrameMessageManager> mMessageManager;
nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
private:
// Stores the root view of the subdocument while the subdocument is being
// reframed. Used to restore the presentation after reframing.
nsIView* mDetachedSubdocViews;
// Stores the containing document of the frame corresponding to this
// frame loader. This is reference is kept valid while the subframe's
// presentation is detached and stored in mDetachedSubdocViews. This
// enables us to detect whether the frame has moved documents during
// a reframe, so that we know not to restore the presentation.
nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
bool mDepthTooGreat : 1;
bool mIsTopLevelContent : 1;
bool mDestroyCalled : 1;

View File

@ -82,7 +82,7 @@ nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
PRUint16 aNodeType, nsIAtom* aExtraName,
nsNodeInfoManager *aOwnerManager)
{
CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager");
// Initialize mInner

View File

@ -17,6 +17,8 @@
#include "plhash.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsIDOMNode.h"
#include "nsGkAtoms.h"
class nsFixedSizeAllocator;
@ -63,45 +65,49 @@ private:
* this object, instead of always deleting the object we'll put the
* object in the cache unless the cache is already full.
*/
void LastRelease();
void LastRelease();
};
#define CHECK_VALID_NODEINFO(_nodeType, _name, _namespaceID, _extraName) \
NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE || \
_nodeType == nsIDOMNode::ATTRIBUTE_NODE || \
_nodeType == nsIDOMNode::TEXT_NODE || \
_nodeType == nsIDOMNode::CDATA_SECTION_NODE || \
_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE || \
_nodeType == nsIDOMNode::COMMENT_NODE || \
_nodeType == nsIDOMNode::DOCUMENT_NODE || \
_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE || \
_nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE || \
_nodeType == PR_UINT16_MAX, \
"Invalid nodeType"); \
NS_ABORT_IF_FALSE((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE || \
_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) == \
(_extraName != nullptr), \
"Supply aExtraName for and only for PIs and doctypes"); \
NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE || \
_nodeType == nsIDOMNode::ATTRIBUTE_NODE || \
_nodeType == PR_UINT16_MAX || \
aNamespaceID == kNameSpaceID_None, \
"Only attributes and elements can be in a namespace"); \
NS_ABORT_IF_FALSE(_name && _name != nsGkAtoms::_empty, "Invalid localName");\
NS_ABORT_IF_FALSE(((_nodeType == nsIDOMNode::TEXT_NODE) == \
(_name == nsGkAtoms::textTagName)) && \
((_nodeType == nsIDOMNode::CDATA_SECTION_NODE) == \
(_name == nsGkAtoms::cdataTagName)) && \
((_nodeType == nsIDOMNode::COMMENT_NODE) == \
(_name == nsGkAtoms::commentTagName)) && \
((_nodeType == nsIDOMNode::DOCUMENT_NODE) == \
(_name == nsGkAtoms::documentNodeName)) && \
((_nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) == \
(_name == nsGkAtoms::documentFragmentNodeName)) && \
((_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) == \
(_name == nsGkAtoms::documentTypeNodeName)) && \
((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==\
(_name == nsGkAtoms::processingInstructionTagName)), \
"Wrong localName for nodeType");
inline void
CheckValidNodeInfo(PRUint16 aNodeType, nsIAtom *aName, PRInt32 aNamespaceID,
nsIAtom* aExtraName)
{
NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
aNodeType == nsIDOMNode::TEXT_NODE ||
aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
aNodeType == nsIDOMNode::COMMENT_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
aNodeType == PR_UINT16_MAX,
"Invalid nodeType");
NS_ABORT_IF_FALSE((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
!!aExtraName,
"Supply aExtraName for and only for PIs and doctypes");
NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
aNodeType == PR_UINT16_MAX ||
aNamespaceID == kNameSpaceID_None,
"Only attributes and elements can be in a namespace");
NS_ABORT_IF_FALSE(aName && aName != nsGkAtoms::_empty, "Invalid localName");
NS_ABORT_IF_FALSE(((aNodeType == nsIDOMNode::TEXT_NODE) ==
(aName == nsGkAtoms::textTagName)) &&
((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
(aName == nsGkAtoms::cdataTagName)) &&
((aNodeType == nsIDOMNode::COMMENT_NODE) ==
(aName == nsGkAtoms::commentTagName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
(aName == nsGkAtoms::documentNodeName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
(aName == nsGkAtoms::documentFragmentNodeName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
(aName == nsGkAtoms::documentTypeNodeName)) &&
((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
(aName == nsGkAtoms::processingInstructionTagName)),
"Wrong localName for nodeType");
}
#endif /* nsNodeInfo_h___ */

View File

@ -210,7 +210,7 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, PRUint16 aNodeType,
nsIAtom* aExtraName /* = nullptr */)
{
CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
aExtraName);
@ -256,7 +256,7 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
#ifdef DEBUG
{
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
CHECK_VALID_NODEINFO(aNodeType, nameAtom, aNamespaceID, nullptr);
CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
}
#endif

View File

@ -159,29 +159,35 @@ test(
function test_CSPSource_fromString() {
// can't do these tests because "self" is not defined.
//"basic source should not be null.");
do_check_neq(null, CSPSource.fromString("a.com"));
do_check_neq(null, CSPSource.fromString("a.com", "http://abc.com"));
//"ldh characters should all work for host.");
do_check_neq(null, CSPSource.fromString("a2-c.com"));
do_check_neq(null, CSPSource.fromString("a2-c.com", "https://a.com"));
//"wildcard should work in first token for host.");
do_check_neq(null, CSPSource.fromString("*.a.com"));
do_check_neq(null, CSPSource.fromString("*.a.com", "http://abc.com"));
//print(" --- Ignore the following two errors if they print ---");
//"wildcard should not work in non-first token for host.");
do_check_eq(null, CSPSource.fromString("x.*.a.com"));
do_check_eq(null, CSPSource.fromString("x.*.a.com", "http://a.com"));
//"funny characters (#) should not work for host.");
do_check_eq(null, CSPSource.fromString("a#2-c.com"));
do_check_eq(null, CSPSource.fromString("a#2-c.com", "http://a.com"));
//print(" --- Stop ignoring errors that print ---\n");
//"failed to parse host with port.");
do_check_neq(null, CSPSource.create("a.com:23"));
do_check_neq(null, CSPSource.create("a.com:23", "http://a.com"));
//"failed to parse host with scheme.");
do_check_neq(null, CSPSource.create("https://a.com"));
do_check_neq(null, CSPSource.create("https://a.com", "http://a.com"));
//"failed to parse host with scheme and port.");
do_check_neq(null, CSPSource.create("https://a.com:200"));
do_check_neq(null, CSPSource.create("https://a.com:200", "http://a.com"));
//Check to make sure we don't match multiple instances with regex
do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23"));
//Port parsing should work for all schemes
do_check_neq(null, CSPSource.create("data:"));
do_check_neq(null, CSPSource.create("javascript:"));
});
test(
@ -270,6 +276,7 @@ test(
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
URI("http://self.com:88"));
var allSourceList = CSPSourceList.fromString("*");
var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'");
//'none' should permit none."
do_check_false( nullSourceList.permits("http://a.com"));
@ -293,6 +300,8 @@ test(
//"* does not permit a long host with no port"
do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com"));
//* short circuts parsing
do_check_true(allAndMoreSourceList.permits("http://a.com"));
});
test(
@ -301,7 +310,7 @@ test(
// policy a /\ policy b intersects policies, not context (where 'self'
// values come into play)
var nullSourceList = CSPSourceList.fromString("'none'");
var simpleSourceList = CSPSourceList.fromString("a.com");
var simpleSourceList = CSPSourceList.fromString("http://a.com");
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
var singleFooSourceList = CSPSourceList.fromString("https://foo.com");
var allSourceList = CSPSourceList.fromString("*");

View File

@ -1118,6 +1118,11 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
widget::WheelEvent* wheelEvent = static_cast<widget::WheelEvent*>(aEvent);
WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
// If we won't dispatch a DOM event for this event, nothing to do anymore.
if (!NS_IsAllowedToDispatchDOMEvent(wheelEvent)) {
break;
}
// Init lineOrPageDelta values for line scroll events for some devices
// on some platforms which might dispatch wheel events which don't have
// lineOrPageDelta values. And also, if delta values are customized by
@ -5086,10 +5091,10 @@ nsEventStateManager::DeltaAccumulator::InitLineOrPageDelta(
// If the delta direction is changed, we should reset only the
// accumulated values.
if (mX && aEvent->deltaX && ((aEvent->deltaX > 0.0) != (mX > 0.0))) {
mX = 0.0;
mX = mPendingScrollAmountX = 0.0;
}
if (mY && aEvent->deltaY && ((aEvent->deltaY > 0.0) != (mY > 0.0))) {
mY = 0.0;
mY = mPendingScrollAmountY = 0.0;
}
}
}
@ -5104,6 +5109,17 @@ nsEventStateManager::DeltaAccumulator::InitLineOrPageDelta(
mHandlingPixelOnlyDevice) &&
!nsEventStateManager::WheelPrefs::GetInstance()->
NeedToComputeLineOrPageDelta(aEvent)) {
// Set the delta values to mX and mY. They would be used when above block
// resets mX/mY/mPendingScrollAmountX/mPendingScrollAmountY if the direction
// is changed.
// NOTE: We shouldn't accumulate the delta values, it might could cause
// overflow even though it's not a realistic situation.
if (aEvent->deltaX) {
mX = aEvent->deltaX;
}
if (aEvent->deltaY) {
mY = aEvent->deltaY;
}
mLastTime = TimeStamp::Now();
return;
}
@ -5315,25 +5331,16 @@ nsEventStateManager::WheelPrefs::Init(
prefNameX.AppendLiteral("delta_multiplier_x");
mMultiplierX[aIndex] =
static_cast<double>(Preferences::GetInt(prefNameX.get(), 100)) / 100;
if (mMultiplierX[aIndex] < 1.0 && mMultiplierX[aIndex] > -1.0) {
mMultiplierX[aIndex] = mMultiplierX[aIndex] < 0.0 ? -1.0 : 1.0;
}
nsCAutoString prefNameY(basePrefName);
prefNameY.AppendLiteral("delta_multiplier_y");
mMultiplierY[aIndex] =
static_cast<double>(Preferences::GetInt(prefNameY.get(), 100)) / 100;
if (mMultiplierY[aIndex] < 1.0 && mMultiplierY[aIndex] > -1.0) {
mMultiplierY[aIndex] = mMultiplierY[aIndex] < 0.0 ? -1.0 : 1.0;
}
nsCAutoString prefNameZ(basePrefName);
prefNameZ.AppendLiteral("delta_multiplier_z");
mMultiplierZ[aIndex] =
static_cast<double>(Preferences::GetInt(prefNameZ.get(), 100)) / 100;
if (mMultiplierZ[aIndex] < 1.0 && mMultiplierZ[aIndex] > -1.0) {
mMultiplierZ[aIndex] = mMultiplierZ[aIndex] < 0.0 ? -1.0 : 1.0;
}
nsCAutoString prefNameAction(basePrefName);
prefNameAction.AppendLiteral("action");
@ -5380,10 +5387,12 @@ nsEventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
Index index = GetIndexFor(aEvent);
Init(index);
NS_ASSERTION(mMultiplierX[index] && mMultiplierY[index],
"The absolute values of both multipliers must be 1 or larger");
aEvent->overflowDeltaX /= mMultiplierX[index];
aEvent->overflowDeltaY /= mMultiplierY[index];
if (mMultiplierX[index]) {
aEvent->overflowDeltaX /= mMultiplierX[index];
}
if (mMultiplierY[index]) {
aEvent->overflowDeltaY /= mMultiplierY[index];
}
}
nsEventStateManager::WheelPrefs::Action

View File

@ -301,9 +301,6 @@ function testDeltaMultiplierPrefs()
for (var j = 0; j < kPrefValues.length; j++) {
currentMultiplier = kPrefValues[j] / 100;
if (currentMultiplier > -1.0 && currentMultiplier < 1.0) {
currentMultiplier = currentMultiplier < 0 ? -1.0 : 1.0;
}
for (var k = 0; k < kDeltaMultiplierPrefs.length; k++) {
currentPref = "mousewheel." + currentTest.name + "." + kDeltaMultiplierPrefs[k];
@ -318,15 +315,29 @@ function testDeltaMultiplierPrefs()
", deltaMode: " + currentEvent.deltaMode + ", modifiers: \"" + modifierList + "\", (trusted event): ";
synthesizeWheel(gScrollableElement, 10, 10, currentEvent);
ok(calledHandlers.wheel, description + "wheel event was not fired");
ok(calledHandlers.DOMMouseScroll.horizontal,
description + "Horizontal DOMMouseScroll event was not fired");
ok(calledHandlers.DOMMouseScroll.vertical,
description + "Vertical DOMMouseScroll event was not fired");
ok(calledHandlers.MozMousePixelScroll.horizontal,
description + "Horizontal MozMousePixelScroll event was not fired");
ok(calledHandlers.MozMousePixelScroll.vertical,
description + "Vertical MozMousePixelScroll event was not fired");
var expectedProps = {
deltaX: currentEvent.deltaX * currentMultiplier,
deltaY: currentEvent.deltaY * currentMultiplier,
dletaZ: currentEvent.deltaZ * currentMultiplier,
lineOrPageDeltaX: currentEvent.lineOrPageDeltaX * currentMultiplier,
lineOrPageDeltaY: currentEvent.lineOrPageDeltaY * currentMultiplier,
};
is(calledHandlers.wheel,
expectedProps.deltaX != 0 || expectedProps.deltaY != 0 || expectedProps.deltaZ != 0,
description + "wheel event was (not) fired");
is(calledHandlers.DOMMouseScroll.horizontal,
expectedProps.lineOrPageDeltaX >= 1 || expectedProps.lineOrPageDeltaX <= -1,
description + "Horizontal DOMMouseScroll event was (not) fired");
is(calledHandlers.DOMMouseScroll.vertical,
expectedProps.lineOrPageDeltaY >= 1 || expectedProps.lineOrPageDeltaY <= -1,
description + "Vertical DOMMouseScroll event was (not) fired");
is(calledHandlers.MozMousePixelScroll.horizontal,
expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1,
description + "Horizontal MozMousePixelScroll event was (not) fired");
is(calledHandlers.MozMousePixelScroll.vertical,
expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1,
description + "Vertical MozMousePixelScroll event was (not) fired");
calledHandlers = { wheel: false,
DOMMouseScroll: { horizontal: false, vertical: false },

View File

@ -213,7 +213,7 @@ public:
mSource,
NS_LITERAL_STRING("error"),
false,
true);
false);
}
};
@ -3069,7 +3069,7 @@ nsresult nsHTMLMediaElement::DispatchAudioAvailableEvent(float* aFrameBuffer,
NS_ENSURE_SUCCESS(rv, rv);
rv = audioavailableEvent->InitAudioAvailableEvent(NS_LITERAL_STRING("MozAudioAvailable"),
true, true, frameBuffer.forget(), aFrameBufferLength,
false, false, frameBuffer.forget(), aFrameBufferLength,
aTime, mAllowAudioData);
NS_ENSURE_SUCCESS(rv, rv);
@ -3093,7 +3093,7 @@ nsresult nsHTMLMediaElement::DispatchEvent(const nsAString& aName)
static_cast<nsIContent*>(this),
aName,
false,
true);
false);
}
nsresult nsHTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)

View File

@ -1,7 +1,5 @@
function test_fragment_noplay(v, start, end, is, ok, finish) {
var completed = false;
function onLoadedMetadata() {
var s = start == null ? 0 : start;
var e = end == null ? v.duration : end;
@ -10,9 +8,7 @@ function onLoadedMetadata() {
ok(v.currentTime >= a && v.currentTime <= b, "loadedmetadata currentTime is " + a + " < " + v.currentTime + " < " + b);
ok(v.initialTime == s, "initialTime (" + v.initialTime + ") == start Time (" + s + ")");
ok(v.mozFragmentEnd == e, "mozFragmentEnd (" + v.mozFragmentEnd + ") == end Time (" + e + ")");
completed = true;
finish();
return false;
}
v.addEventListener("loadedmetadata", onLoadedMetadata, false);

View File

@ -13,32 +13,28 @@ function onLoadedMetadata() {
ok(v.mozFragmentEnd == e, "mozFragmentEnd (" + v.mozFragmentEnd + ") == end Time (" + e + ")");
loadedMetadataRaised = true;
v.play();
return false;
}
function onSeeked() {
if (completed)
return false;
return;
var s = start == null ? 0 : start;
ok(v.currentTime == s, "seeked currentTime is " + v.currentTime + " != " + s);
seekedRaised = true;
return false;
}
function onTimeUpdate() {
if (completed)
return false;
return;
v._lastTimeUpdate = v.currentTime;
return false;
}
function onPause() {
if (completed)
return false;
return;
var e = end == null ? v.duration : end;
var a = e - 0.05;
@ -46,13 +42,12 @@ function onPause() {
ok(v.currentTime >= a && v.currentTime <= b, "paused currentTime is " + a + " < " + v.currentTime + " < " + b + " ? " + v._lastTimeUpdate);
pausedRaised = true;
v.play();
return false;
}
function onEnded() {
if (completed)
return false;
return;
completed = true;
ok(loadedMetadataRaised, "loadedmetadata event");
@ -63,7 +58,6 @@ function onEnded() {
ok(pausedRaised, "paused event: " + end + " " + v.duration);
}
finish();
return false;
}
v.addEventListener("ended", onEnded, false);

View File

@ -9,7 +9,7 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
ok(!v.seeking, "seeking should default to false");
try {
v.seeking = true;
@ -23,22 +23,20 @@ function startTest() {
v.play();
v.currentTime=seekTime;
seekFlagStart = v.seeking;
return false;
}
function seekStarted() {
if (completed)
return false;
return;
ok(v.currentTime >= seekTime - 0.1,
"Video currentTime should be around " + seekTime + ": " + v.currentTime + " (seeking)");
v.pause();
startPassed = true;
return false;
}
function seekEnded() {
if (completed)
return false;
return;
var t = v.currentTime;
// Since we were playing, and we only paused asynchronously, we can't be
@ -48,12 +46,11 @@ function seekEnded() {
v.play();
endPassed = true;
seekFlagEnd = v.seeking;
return false;
}
function playbackEnded() {
if (completed)
return false;
return;
completed = true;
ok(startPassed, "seeking event");
@ -61,7 +58,6 @@ function playbackEnded() {
ok(seekFlagStart, "seeking flag on start should be true");
ok(!seekFlagEnd, "seeking flag on end should be false");
finish();
return false;
}
v.addEventListener("ended", playbackEnded, false);

View File

@ -8,12 +8,11 @@ var target = 0;
function startTest() {
if (completed)
return false;
return;
target = v.duration / 2;
v.currentTime = target;
v.currentTime = target;
v._seekTarget = target;
return false;
}
function startSeeking() {
@ -28,7 +27,7 @@ function startSeeking() {
function seekEnded() {
if (completed)
return false;
return;
if (v.currentTime > 0) {
ok(v.currentTime > target - 0.1 && v.currentTime < target + 0.1,
@ -41,8 +40,6 @@ function seekEnded() {
completed = true;
finish();
}
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -3,31 +3,28 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
ok(!v.seeking, "seeking should default to false");
v.currentTime = seekTime;
is(v.currentTime, seekTime, "currentTime must report seek target immediately");
is(v.seeking, true, "seeking flag on start should be true");
return false;
}
function seekStarted() {
if (completed)
return false;
return;
//is(v.currentTime, seekTime, "seeking: currentTime must be seekTime");
ok(Math.abs(v.currentTime - seekTime) < 0.01, "seeking: currentTime must be seekTime");
return false;
}
function seekEnded() {
if (completed)
return false;
return;
completed = true;
//is(v.currentTime, seekTime, "seeked: currentTime must be seekTime");
ok(Math.abs(v.currentTime - seekTime) < 0.01, "seeked: currentTime must be seekTime");
is(v.seeking, false, "seeking flag on end should be false");
finish();
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -3,41 +3,37 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
ok(!v.seeking, "seeking should default to false");
v.currentTime = v.duration;
is(v.currentTime, v.duration, "currentTime must report seek target immediately");
is(v.seeking, true, "seeking flag on start should be true");
return false;
}
function seekStarted() {
if (completed)
return false;
return;
//is(v.currentTime, v.duration, "seeking: currentTime must be duration");
ok(Math.abs(v.currentTime - v.duration) < 0.01, "seeking: currentTime must be duration");
return false;
}
function seekEnded() {
if (completed)
return false;
return;
//is(v.currentTime, v.duration, "seeked: currentTime must be duration");
ok(Math.abs(v.currentTime - v.duration) < 0.01, "seeked: currentTime must be duration");
is(v.seeking, false, "seeking flag on end should be false");
return false;
}
function playbackEnded() {
if (completed)
return false;
return;
completed = true;
//is(v.currentTime, v.duration, "ended: currentTime must be duration");
ok(Math.abs(v.currentTime - v.duration) < 0.01, "ended: currentTime must be duration");
is(v.seeking, false, "seeking flag on end should be false");
is(v.ended, true, "ended must be true");
finish();
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -8,33 +8,30 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
v.currentTime=seekTime;
v.play();
return false;
}
function seekStarted() {
if (completed)
return false;
return;
ok(v.currentTime >= seekTime - 0.1, "Video currentTime should be around " + seekTime + ": " + v.currentTime);
startPassed = true;
return false;
}
function seekEnded() {
if (completed)
return false;
return;
endPassed = true;
return false;
}
function playbackEnded() {
if (completed)
return false
return;
completed = true;
ok(startPassed, "send seeking event");
@ -42,7 +39,6 @@ function playbackEnded() {
ok(v.ended, "Checking playback has ended");
ok(Math.abs(v.currentTime - v.duration) <= 0.1, "Checking currentTime at end: " + v.currentTime);
finish();
return false;
}
v.addEventListener("ended", playbackEnded, false);

View File

@ -7,10 +7,9 @@ var gotTimeupdate = false;
function startTest() {
if (completed)
return false;
return;
v.currentTime=seekTime;
return false;
}
function timeupdate() {
@ -20,24 +19,22 @@ function timeupdate() {
function seekStarted() {
if (completed)
return false;
return;
ok(v.currentTime >= seekTime - 0.1, "Video currentTime should be around " + seekTime + ": " + v.currentTime);
v.addEventListener("timeupdate", timeupdate, false);
startPassed = true;
return false;
}
function seekEnded() {
if (completed)
return false;
return;
var t = v.currentTime;
ok(Math.abs(t - seekTime) <= 0.1, "Video currentTime should be around " + seekTime + ": " + t);
ok(gotTimeupdate, "Should have got timeupdate between seeking and seekended");
completed = true;
finish();
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -6,16 +6,15 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
v.currentTime=seekTime;
v._seekTarget=seekTime;
return false;
}
function seekStarted() {
if (completed)
return false;
return;
seekCount += 1;
@ -25,20 +24,17 @@ function seekStarted() {
v.currentTime=seekTime/2;
v._seekTarget=seekTime/2;
}
return false;
}
function seekEnded() {
if (completed)
return false;
return;
if (seekCount == 2) {
ok(Math.abs(v.currentTime - seekTime/2) <= 0.1, "seek on target: " + v.currentTime);
completed = true;
finish();
}
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -7,36 +7,32 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
v.currentTime=seekTime;
return false;
}
function seekStarted() {
if (completed)
return false;
return;
ok(v.currentTime >= seekTime - 0.1, "Video currentTime should be around " + seekTime + ": " + v.currentTime);
startPassed = true;
v.play();
return false;
}
function seekEnded() {
if (completed)
return false;
return;
endPassed = true;
return false;
}
function playbackEnded() {
if (completed)
return false;
return;
ok(startPassed, "Got seeking event");
ok(endPassed, "Got seeked event");
completed = true;
finish();
return false;
}
v.addEventListener("ended", playbackEnded, false);

View File

@ -13,15 +13,14 @@ function poll() {
function startTest() {
if (completed)
return false;
return;
interval = setInterval(poll, 10);
v.currentTime = Math.random() * v.duration;
return false;
}
function seekEnded() {
if (completed)
return false;
return;
seekCount++;
ok(true, "Seek " + seekCount);
@ -32,7 +31,6 @@ function seekEnded() {
} else {
v.currentTime = Math.random() * v.duration;
}
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -9,7 +9,7 @@ var thrown3 = false;
function startTest() {
if (completed)
return false;
return;
try {
v.currentTime = NaN;
@ -27,7 +27,6 @@ function startTest() {
ok(thrown1, "Setting currentTime to invalid value of NaN");
ok(thrown3, "Setting currentTime to invalid value of a function");
finish();
return false;
}
v.addEventListener("loadedmetadata", startTest, false);

View File

@ -1,15 +1,10 @@
function test_seek8(v, seekTime, is, ok, finish) {
var completed = false;
function startTest() {
v.currentTime = 1000;
}
function seekEnded() {
if (completed)
return false;
ok(Math.abs(v.currentTime - v.duration) < 0.2,
"currentTime " + v.currentTime + " close to " + v.duration);
finish();

View File

@ -1,15 +1,10 @@
function test_seek9(v, seekTime, is, ok, finish) {
var completed = false;
function startTest() {
v.currentTime = -1000;
}
function seekEnded() {
if (completed)
return false;
is(v.currentTime, 0, "currentTime clamped to 0");
finish();
}

View File

@ -69,8 +69,6 @@ function ended(e) {
v.src = "";
v.parentNode.removeChild(v);
manager.finished(v.token);
return false;
}
function startTest(test, token) {

View File

@ -20,29 +20,26 @@ var manager = new MediaTestManager;
function loaded(event) {
var v = event.target;
if (v._finished)
return false;
return;
v.play();
return false;
}
function started(event) {
var v = event.target;
if (v._finished)
return false;
return;
ok(!v.paused, "Video should not be paused while playing");
v.parentNode.removeChild(v);
v._played = true;
return false;
}
function stopped(event) {
var v = event.target;
if (v._finished)
return false;
return;
v._finished = true;
ok(v.paused, "Video should be paused after removing from the Document");
manager.finished(v.token);
return false;
}

View File

@ -20,7 +20,7 @@ var manager = new MediaTestManager;
function onloaded(event) {
var v = event.target;
v.currentTime = v.duration;
return false;
return;
}
function checkNotPlaying(v) {
@ -32,16 +32,14 @@ function checkNotPlaying(v) {
function onseeked(event) {
var v = event.target;
setTimeout(function() { checkNotPlaying(v); }, 500);
return false;
}
function onended(event) {
var v = event.target;
if (v._finished)
return false;
return;
v.addEventListener("seeked", onseeked, false);
v.currentTime = 0;
return false;
}
function startTest(test, token) {

View File

@ -42,7 +42,6 @@ function FinishedLoads() {
}
function loadError(evt) {
// Prevent mochitest's onerror handler catching the 'error' event on bubble.
var v = evt.target;
is(v._loadError, false, "Shouldn't receive multiple error events for " + v.src);
v._loadError = true;

View File

@ -47,7 +47,6 @@ function loadedMetaData(evt) {
ok(v._loadedMetaDataCount <= 1, "No more than 1 onloadedmetadata event for " + v._name);
checkMetadata(v._name, v, v._test);
v.play();
return false;
}
function playing(evt) {
@ -76,7 +75,6 @@ function playbackEnded(evt) {
v.parentNode.removeChild(v);
manager.finished(v.token);
}
return false;
}
function startTest(test, token) {

View File

@ -37,7 +37,6 @@ function loaded(e) {
v._finished = true;
v.parentNode.removeChild(v);
manager.finished(v.token);
return false;
}
function startTest(test, token) {

View File

@ -14,15 +14,14 @@ var completed = false;
function startTest() {
if (completed)
return false;
return;
var v = document.getElementById('v');
v.play();
return false;
}
function playbackEnded() {
if (completed)
return false
return;
var v = document.getElementById('v');
completed = true;
@ -30,7 +29,6 @@ function playbackEnded() {
"Checking currentTime at end: " + v.currentTime);
ok(v.ended, "Checking playback has ended");
SimpleTest.finish();
return false;
}
SimpleTest.waitForExplicitFinish();

View File

@ -16,23 +16,22 @@ var endCount = 0;
function startTest() {
if (completed)
return false;
return;
var v = document.getElementById('v');
v.play();
return false;
}
function playbackStarted() {
if (completed)
return false;
return;
playingCount++;
}
function playbackEnded() {
if (completed)
return false
return;
endCount++;
var v = document.getElementById('v');
@ -48,7 +47,6 @@ function playbackEnded() {
completed = true;
SimpleTest.finish();
}
return false;
}
SimpleTest.waitForExplicitFinish();

View File

@ -14,7 +14,7 @@ var completed = false;
function audioavailable(e) {
if (completed)
return false;
return;
completed = true;
var samples = e.frameBuffer;
@ -29,16 +29,14 @@ function audioavailable(e) {
// Only care about the first few samples
SimpleTest.finish();
return false;
}
function startTest() {
if (completed)
return false;
return;
var v = document.getElementById('v');
v.addEventListener('MozAudioAvailable', audioavailable, false);
v.play();
return false;
}
SimpleTest.waitForExplicitFinish();

View File

@ -14,7 +14,7 @@ var completed = false;
function audioavailable(e) {
if (completed)
return false;
return;
completed = true;
var samples = e.frameBuffer;
@ -29,16 +29,14 @@ function audioavailable(e) {
// Only care about the first few samples
SimpleTest.finish();
return false;
}
function startTest() {
if (completed)
return false;
return;
var v = document.getElementById('v');
v.addEventListener('MozAudioAvailable', audioavailable, false);
v.play();
return false;
}
SimpleTest.waitForExplicitFinish();

View File

@ -103,7 +103,7 @@ XBLFinalize(JSFreeOp *fop, JSObject *obj)
static const uint32_t XBLPROTO_SLOT = 0;
static const uint32_t FIELD_SLOT = 1;
static bool
bool
ValueHasISupportsPrivate(const JS::Value &v)
{
if (!v.isObject()) {
@ -214,7 +214,7 @@ InstallXBLField(JSContext* cx,
return false;
}
static bool
bool
FieldGetterImpl(JSContext *cx, JS::CallArgs args)
{
const JS::Value &thisv = args.thisv();
@ -246,11 +246,11 @@ static JSBool
FieldGetter(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
return JS::CallNonGenericMethod(cx, ValueHasISupportsPrivate, FieldGetterImpl,
args);
return JS::CallNonGenericMethod<ValueHasISupportsPrivate, FieldGetterImpl>
(cx, args);
}
static bool
bool
FieldSetterImpl(JSContext *cx, JS::CallArgs args)
{
const JS::Value &thisv = args.thisv();
@ -274,8 +274,8 @@ static JSBool
FieldSetter(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
return JS::CallNonGenericMethod(cx, ValueHasISupportsPrivate, FieldSetterImpl,
args);
return JS::CallNonGenericMethod<ValueHasISupportsPrivate, FieldSetterImpl>
(cx, args);
}
static JSBool

View File

@ -38,6 +38,7 @@
#include "Connection.h"
#include "MobileConnection.h"
#include "nsIIdleObserver.h"
#include "nsIPermissionManager.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "MediaManager.h"
@ -1243,20 +1244,20 @@ Navigator::GetMozMobileConnection(nsIDOMMozMobileConnection** aMobileConnection)
if (!mMobileConnection) {
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
NS_ENSURE_TRUE(window, NS_OK);
// Chrome is always allowed access, so do the permission check only
// for non-chrome pages.
if (!nsContentUtils::IsCallerChrome()) {
nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument());
NS_ENSURE_TRUE(doc, NS_OK);
nsCOMPtr<nsIDocument> document = do_QueryInterface(window->GetExtantDocument());
NS_ENSURE_TRUE(document, NS_OK);
nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
nsCOMPtr<nsIPermissionManager> permMgr =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
NS_ENSURE_TRUE(permMgr, NS_OK);
nsCOMPtr<nsIURI> uri;
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
PRUint32 permission = nsIPermissionManager::DENY_ACTION;
permMgr->TestPermissionFromPrincipal(principal, "mobileconnection", &permission);
if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.mobileconnection.whitelist")) {
return NS_OK;
}
if (permission != nsIPermissionManager::ALLOW_ACTION) {
return NS_OK;
}
mMobileConnection = new network::MobileConnection();

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */
@ -62,6 +62,71 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
class GetPairedDevicesTask : public BluetoothReplyRunnable
{
public:
GetPairedDevicesTask(BluetoothAdapter* aAdapterPtr,
nsIDOMDOMRequest* aReq) :
mAdapterPtr(aAdapterPtr),
BluetoothReplyRunnable(aReq)
{
MOZ_ASSERT(aReq && aAdapterPtr);
}
virtual bool ParseSuccessfulReply(jsval* aValue)
{
*aValue = JSVAL_VOID;
BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
NS_WARNING("Not a BluetoothNamedValue array!");
return false;
}
const InfallibleTArray<BluetoothNamedValue>& reply =
mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
nsTArray<nsRefPtr<BluetoothDevice> > devices;
JSObject* JsDevices;
for (uint32_t i = 0; i < reply.Length(); i++) {
if (reply[i].value().type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
NS_WARNING("Not a BluetoothNamedValue array!");
return false;
}
nsRefPtr<BluetoothDevice> d = BluetoothDevice::Create(mAdapterPtr->GetOwner(),
mAdapterPtr->GetPath(),
reply[i].value());
devices.AppendElement(d);
}
nsresult rv;
nsIScriptContext* sc = mAdapterPtr->GetContextForEventHandlers(&rv);
if (!sc) {
NS_WARNING("Cannot create script context!");
return false;
}
rv = BluetoothDeviceArrayToJSArray(sc->GetNativeContext(),
sc->GetNativeGlobal(), devices, &JsDevices);
if (JsDevices) {
aValue->setObject(*JsDevices);
}
else {
NS_WARNING("Paird not yet set!");
return false;
}
return true;
}
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mAdapterPtr = nullptr;
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
};
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue)
: BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
, mEnabled(false)
@ -395,6 +460,36 @@ BluetoothAdapter::SetDiscoverableTimeout(const PRUint32 aDiscoverableTimeout,
return SetProperty(GetOwner(), property, aRequest);
}
NS_IMETHODIMP
BluetoothAdapter::GetPairedDevices(nsIDOMDOMRequest** aRequest)
{
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMDOMRequest> request;
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
if (NS_FAILED(rv)) {
NS_WARNING("Can't create DOMRequest!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> results = new GetPairedDevicesTask(this, request);
if (NS_FAILED(bs->GetPairedDevicePropertiesInternal(mDeviceAddresses, results))) {
return NS_ERROR_FAILURE;
}
request.forget(aRequest);
return NS_OK;
}
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, propertychanged)
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicefound)
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicedisappeared)

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */
@ -107,6 +107,15 @@ public:
*/
virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
/**
* Returns the properties of paired devices, implemented via a platform
* specific method.
*
* @return NS_OK on success, NS_ERROR_FAILURE otherwise
*/
virtual nsresult GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Stop device discovery (platform specific implementation)
*

View File

@ -1,10 +1,12 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */
#include "BluetoothUtils.h"
#include "nsContentUtils.h"
#include "BluetoothDevice.h"
#include "jsapi.h"
#include "nsTArray.h"
#include "nsString.h"
@ -59,3 +61,47 @@ mozilla::dom::bluetooth::StringArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
return NS_OK;
}
nsresult
mozilla::dom::bluetooth::BluetoothDeviceArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
const nsTArray<nsRefPtr<BluetoothDevice> >& aSourceArray,
JSObject** aResultArray)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aGlobal, "Null global!");
JSAutoRequest ar(aCx);
JSAutoEnterCompartment ac;
if (!ac.enter(aCx, aGlobal)) {
NS_WARNING("Failed to enter compartment!");
return NS_ERROR_FAILURE;
}
JSObject* arrayObj;
if (aSourceArray.IsEmpty()) {
arrayObj = JS_NewArrayObject(aCx, 0, nullptr);
} else {
uint32_t valLength = aSourceArray.Length();
mozilla::ScopedDeleteArray<jsval> valArray(new jsval[valLength]);
JS::AutoArrayRooter tvr(aCx, valLength, valArray);
for (PRUint32 index = 0; index < valLength; index++) {
nsISupports* obj = aSourceArray[index]->ToISupports();
nsresult rv =
nsContentUtils::WrapNative(aCx, aGlobal, obj, &valArray[index]);
NS_ENSURE_SUCCESS(rv, rv);
}
arrayObj = JS_NewArrayObject(aCx, valLength, valArray);
}
if (!arrayObj) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (!JS_FreezeObject(aCx, arrayObj)) {
return NS_ERROR_FAILURE;
}
*aResultArray = arrayObj;
return NS_OK;
}

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */
@ -14,11 +14,18 @@ class JSObject;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothDevice;
nsresult
StringArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
const nsTArray<nsString>& aSourceArray,
JSObject** aResultArray);
nsresult
BluetoothDeviceArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
const nsTArray<nsRefPtr<BluetoothDevice> >& aSourceArray,
JSObject** aResultArray);
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=2 et sw=2 tw=80: */
/*
** Copyright 2006, The Android Open Source Project
**
@ -839,6 +839,76 @@ BluetoothDBusService::StartDiscoveryInternal(const nsAString& aAdapterPath,
return SendDiscoveryMessage(aAdapterPath, "StartDiscovery", aRunnable);
}
class BluetoothPairedDevicePropertiesRunnable : public nsRunnable
{
public:
BluetoothPairedDevicePropertiesRunnable(BluetoothReplyRunnable* aRunnable,
const nsTArray<nsString>& aDeviceAddresses)
: mRunnable(dont_AddRef(aRunnable)),
mDeviceAddresses(aDeviceAddresses)
{
}
nsresult
Run()
{
MOZ_ASSERT(!NS_IsMainThread());
DBusError err;
dbus_error_init(&err);
nsString replyError;
DBusMessage* msg;
BluetoothValue values = InfallibleTArray<BluetoothNamedValue>();
for (int i = 0; i < mDeviceAddresses.Length(); i++) {
BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
1000,
&err,
NS_ConvertUTF16toUTF8(mDeviceAddresses[i]).get(),
DBUS_DEVICE_IFACE,
"GetProperties",
DBUS_TYPE_INVALID);
UnpackDevicePropertiesMessage(msg, &err, v, replyError);
if (!replyError.IsEmpty()) {
DispatchBluetoothReply(mRunnable, v, replyError);
return NS_ERROR_FAILURE;
}
if (msg) {
dbus_message_unref(msg);
}
v.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Path"), mDeviceAddresses[i])
);
InfallibleTArray<BluetoothNamedValue>& deviceProperties = v.get_ArrayOfBluetoothNamedValue();
for (uint32_t p = 0; p < v.get_ArrayOfBluetoothNamedValue().Length(); ++p) {
BluetoothNamedValue& property = v.get_ArrayOfBluetoothNamedValue()[p];
// Only paired devices will be return back to main thread
if (property.name().EqualsLiteral("Paired")) {
bool paired = property.value();
if (paired) {
values.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(mDeviceAddresses[i], deviceProperties)
);
}
break;
}
}
}
mRunnable->SetReply(new BluetoothReply(BluetoothReplySuccess(values)));
if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
NS_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}
private:
nsRefPtr<BluetoothReplyRunnable> mRunnable;
nsTArray<nsString> mDeviceAddresses;
};
nsresult
BluetoothDBusService::GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
@ -869,6 +939,27 @@ BluetoothDBusService::GetProperties(BluetoothObjectType aType,
return NS_OK;
}
nsresult
BluetoothDBusService::GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable)
{
if (!mConnection || !gThreadConnection) {
NS_ERROR("Bluetooth service not started yet!");
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(!NS_IsMainThread());
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
nsRefPtr<nsRunnable> func(new BluetoothPairedDevicePropertiesRunnable(runnable, aDeviceAddresses));
if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
NS_WARNING("Cannot dispatch firmware loading task!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
nsresult
BluetoothDBusService::SetProperty(BluetoothObjectType aType,
const nsAString& aPath,

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */
@ -27,6 +27,8 @@ public:
virtual nsresult StartInternal();
virtual nsresult StopInternal();
virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable);
virtual nsresult GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable);
virtual nsresult StartDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable);
virtual nsresult StopDiscoveryInternal(const nsAString& aAdapterPath,

View File

@ -1,5 +1,5 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=40: */
/* vim: set ts=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/. */
@ -33,6 +33,7 @@ interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
nsIDOMDOMRequest setDiscoverableTimeout(in unsigned long timeout);
nsIDOMDOMRequest startDiscovery();
nsIDOMDOMRequest stopDiscovery();
nsIDOMDOMRequest getPairedDevices();
// Fired when discoverying and any device is discovered.
attribute nsIDOMEventListener ondevicefound;
// Fired when any device is out of discoverable range.

View File

@ -316,18 +316,8 @@ DeviceStorageRequestParent::StatFileEvent::CancelableRun()
NS_DispatchToMainThread(r);
return NS_OK;
}
nsString state;
state.Assign(NS_LITERAL_STRING("available"));
#ifdef MOZ_WIDGET_GONK
rv = GetSDCardStatus(state);
if (NS_FAILED(rv)) {
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
NS_DispatchToMainThread(r);
return NS_OK;
}
#endif
r = new PostStatResultEvent(mParent, diskUsage, freeSpace, state);
r = new PostStatResultEvent(mParent, diskUsage, freeSpace);
NS_DispatchToMainThread(r);
return NS_OK;
}
@ -380,7 +370,7 @@ DeviceStorageRequestParent::ReadFileEvent::CancelableRun()
DeviceStorageRequestParent::EnumerateFileEvent::EnumerateFileEvent(DeviceStorageRequestParent* aParent,
DeviceStorageFile* aFile,
PRUint32 aSince)
PRUint64 aSince)
: CancelableRunnable(aParent)
, mFile(aFile)
, mSince(aSince)
@ -447,12 +437,10 @@ DeviceStorageRequestParent::PostPathResultEvent::CancelableRun()
DeviceStorageRequestParent::PostStatResultEvent::PostStatResultEvent(DeviceStorageRequestParent* aParent,
PRInt64 aFreeBytes,
PRInt64 aTotalBytes,
nsAString& aState)
PRInt64 aTotalBytes)
: CancelableRunnable(aParent)
, mFreeBytes(aFreeBytes)
, mTotalBytes(aTotalBytes)
, mState(aState)
{
}
@ -465,7 +453,16 @@ DeviceStorageRequestParent::PostStatResultEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
StatStorageResponse response(mFreeBytes, mTotalBytes, mState);
nsString state;
state.Assign(NS_LITERAL_STRING("available"));
#ifdef MOZ_WIDGET_GONK
nsresult rv = GetSDCardStatus(state);
if (NS_FAILED(rv)) {
state.Assign(NS_LITERAL_STRING("unavailable"));
}
#endif
StatStorageResponse response(mFreeBytes, mTotalBytes, state);
unused << mParent->Send__delete__(mParent, response);
return NS_OK;
}

View File

@ -151,12 +151,12 @@ private:
class EnumerateFileEvent : public CancelableRunnable
{
public:
EnumerateFileEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile, PRUint32 aSince);
EnumerateFileEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile, PRUint64 aSince);
virtual ~EnumerateFileEvent();
virtual nsresult CancelableRun();
private:
nsRefPtr<DeviceStorageFile> mFile;
PRUint32 mSince;
PRUint64 mSince;
};
class PostPathResultEvent : public CancelableRunnable
@ -175,13 +175,11 @@ private:
public:
PostStatResultEvent(DeviceStorageRequestParent* aParent,
PRInt64 aFreeBytes,
PRInt64 aTotalBytes,
nsAString& aState);
PRInt64 aTotalBytes);
virtual ~PostStatResultEvent();
virtual nsresult CancelableRun();
private:
PRInt64 mFreeBytes, mTotalBytes;
nsString mState;
};
protected:

View File

@ -856,10 +856,9 @@ nsDOMDeviceStorageCursor::IPDLRelease()
class PostStatResultEvent : public nsRunnable
{
public:
PostStatResultEvent(nsRefPtr<DOMRequest>& aRequest, PRInt64 aFreeBytes, PRInt64 aTotalBytes, nsAString& aState)
PostStatResultEvent(nsRefPtr<DOMRequest>& aRequest, PRInt64 aFreeBytes, PRInt64 aTotalBytes)
: mFreeBytes(aFreeBytes)
, mTotalBytes(aTotalBytes)
, mState(aState)
{
mRequest.swap(aRequest);
}
@ -870,7 +869,18 @@ public:
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<nsIDOMDeviceStorageStat> domstat = new nsDOMDeviceStorageStat(mFreeBytes, mTotalBytes, mState);
nsString state;
state.Assign(NS_LITERAL_STRING("available"));
#ifdef MOZ_WIDGET_GONK
nsresult rv = GetSDCardStatus(state);
if (NS_FAILED(rv)) {
mRequest->FireError(NS_ERROR_FAILURE);
mRequest = nullptr;
return NS_OK;
}
#endif
nsRefPtr<nsIDOMDeviceStorageStat> domstat = new nsDOMDeviceStorageStat(mFreeBytes, mTotalBytes, state);
jsval result = InterfaceToJsval(mRequest->GetOwner(),
domstat,
@ -1062,24 +1072,13 @@ public:
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
PRUint64 diskUsage = DeviceStorageFile::DirectoryDiskUsage(mFile->mFile);
PRInt64 freeSpace = 0;
PRInt64 freeSpace;
nsresult rv = mFile->mFile->GetDiskSpaceAvailable(&freeSpace);
if (NS_FAILED(rv)) {
r = new PostErrorEvent(mRequest, POST_ERROR_EVENT_UNKNOWN, mFile);
NS_DispatchToMainThread(r);
return NS_OK;
freeSpace = 0;
}
nsString state;
state.Assign(NS_LITERAL_STRING("available"));
#ifdef MOZ_WIDGET_GONK
rv = GetSDCardStatus(state);
if (NS_FAILED(rv)) {
r = new PostErrorEvent(mRequest, POST_ERROR_EVENT_UNKNOWN, mFile);
NS_DispatchToMainThread(r);
return NS_OK;
}
#endif
r = new PostStatResultEvent(mRequest, diskUsage, freeSpace, state);
r = new PostStatResultEvent(mRequest, diskUsage, freeSpace);
NS_DispatchToMainThread(r);
return NS_OK;
}

View File

@ -35,36 +35,26 @@ function statError(e) {
devicestorage_cleanup();
}
var isMac = /Mac/.test(navigator.platform);
var isWin = /Win/.test(navigator.platform);
var storage = navigator.getDeviceStorage("testing");
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
if (isMac || isWin) {
todo(false, "stat is not available on mac or windows yet. see bug xxxx");
function addError(e) {
ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup();
} else {
var storage = navigator.getDeviceStorage("testing");
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
function addError(e) {
ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup();
}
function addSuccess(e) {
request = storage.stat();
ok(request, "Should have a non-null request");
request.onsuccess = statSuccess;
request.onerror = statError;
}
request = storage.addNamed(createRandomBlob(), "a/b");
request.onsuccess = addSuccess;
request.onerror = addError;
}
function addSuccess(e) {
request = storage.stat();
ok(request, "Should have a non-null request");
request.onsuccess = statSuccess;
request.onerror = statError;
}
request = storage.addNamed(createRandomBlob(), "a/b");
request.onsuccess = addSuccess;
request.onerror = addError;
</script>
</pre>
</body>

View File

@ -212,7 +212,7 @@ IDBTransaction::OnRequestFinished()
NS_ASSERTION(mPendingRequests, "Mismatched calls!");
--mPendingRequests;
if (!mPendingRequests) {
NS_ASSERTION(mAbortCode || mReadyState == IDBTransaction::LOADING,
NS_ASSERTION(NS_FAILED(mAbortCode) || mReadyState == IDBTransaction::LOADING,
"Bad state!");
mReadyState = IDBTransaction::COMMITTING;
CommitOrRollback();
@ -843,7 +843,7 @@ CommitHelper::Run()
}
nsCOMPtr<nsIDOMEvent> event;
if (mAbortCode) {
if (NS_FAILED(mAbortCode)) {
if (mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE) {
// This will make the database take a snapshot of it's DatabaseInfo
mTransaction->Database()->Close();
@ -898,16 +898,16 @@ CommitHelper::Run()
if (mConnection) {
IndexedDatabaseManager::SetCurrentWindow(database->GetOwner());
if (!mAbortCode && mUpdateFileRefcountFunction &&
if (NS_SUCCEEDED(mAbortCode) && mUpdateFileRefcountFunction &&
NS_FAILED(mUpdateFileRefcountFunction->UpdateDatabase(mConnection))) {
mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (!mAbortCode && NS_FAILED(WriteAutoIncrementCounts())) {
if (NS_SUCCEEDED(mAbortCode) && NS_FAILED(WriteAutoIncrementCounts())) {
mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (!mAbortCode) {
if (NS_SUCCEEDED(mAbortCode)) {
NS_NAMED_LITERAL_CSTRING(release, "COMMIT TRANSACTION");
nsresult rv = mConnection->ExecuteSimpleSQL(release);
if (NS_SUCCEEDED(rv)) {
@ -926,7 +926,7 @@ CommitHelper::Run()
}
}
if (mAbortCode) {
if (NS_FAILED(mAbortCode)) {
RevertAutoIncrementCounts();
NS_NAMED_LITERAL_CSTRING(rollback, "ROLLBACK TRANSACTION");
if (NS_FAILED(mConnection->ExecuteSimpleSQL(rollback))) {

View File

@ -8,10 +8,12 @@
#include "AppProcessPermissions.h"
#include "ContentParent.h"
#include "mozIApplication.h"
#include "mozilla/hal_sandbox/PHalParent.h"
#include "nsIDOMApplicationRegistry.h"
#include "TabParent.h"
using namespace mozilla::dom;
using namespace mozilla::hal_sandbox;
using namespace mozilla::services;
namespace mozilla {
@ -51,4 +53,10 @@ AppProcessHasPermission(PContentParent* aActor, const char* aPermission)
return false;
}
bool
AppProcessHasPermission(PHalParent* aActor, const char* aPermission)
{
return AppProcessHasPermission(aActor->Manager(), aPermission);
}
} // namespace mozilla

View File

@ -15,6 +15,10 @@ class PBrowserParent;
class PContentParent;
}
namespace hal_sandbox {
class PHalParent;
}
/**
* Return true iff the specified browser has the specified capability.
*/
@ -30,6 +34,10 @@ bool
AppProcessHasPermission(mozilla::dom::PContentParent* aActor,
const char* aPermission);
bool
AppProcessHasPermission(mozilla::hal_sandbox::PHalParent* aActor,
const char* aPermission);
// NB: when adding capability checks for other IPDL actors, please add
// them to this file and have them delegate to the two functions above
// as appropriate. For example,

View File

@ -15,6 +15,7 @@
#include "chrome/common/process_watcher.h"
#include "AppProcessPermissions.h"
#include "CrashReporterParent.h"
#include "History.h"
#include "IDBFactory.h"
@ -1358,6 +1359,9 @@ ContentParent::DeallocPExternalHelperApp(PExternalHelperAppParent* aService)
PSmsParent*
ContentParent::AllocPSms()
{
if (!AppProcessHasPermission(this, "sms")) {
return nullptr;
}
return new SmsParent();
}

View File

@ -97,7 +97,7 @@ struct DeviceStorageDeleteParams
struct DeviceStorageEnumerationParams
{
nsString fullpath;
PRUint32 since;
PRUint64 since;
};
union DeviceStorageParams

View File

@ -4,9 +4,7 @@
// getNetworks() can take some time..
MARIONETTE_TIMEOUT = 60000;
const WHITELIST_PREF = "dom.mobileconnection.whitelist";
let uriPrePath = window.location.protocol + "//" + window.location.host;
SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
SpecialPowers.addPermission("mobileconnection", true, document);
let connection = navigator.mozMobileConnection;
ok(connection instanceof MozMobileConnection,
@ -233,7 +231,7 @@ function testSelectExistingNetworkAuto() {
}
function cleanUp() {
SpecialPowers.clearUserPref(WHITELIST_PREF);
SpecialPowers.removePermission("mobileconnection", document);
finish();
}

View File

@ -3,9 +3,7 @@
MARIONETTE_TIMEOUT = 30000;
const WHITELIST_PREF = "dom.mobileconnection.whitelist";
let uriPrePath = window.location.protocol + "//" + window.location.host;
SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
SpecialPowers.addPermission("mobileconnection", true, document);
let connection = navigator.mozMobileConnection;
ok(connection instanceof MozMobileConnection,
@ -138,7 +136,7 @@ function testHome() {
}
function cleanUp() {
SpecialPowers.clearUserPref(WHITELIST_PREF);
SpecialPowers.removePermission("mobileconnection", document);
finish();
}

View File

@ -2443,7 +2443,8 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
case NPPVpluginKeepLibraryInMemory: {
NPBool bCached = (result != nullptr);
return inst->SetCached(bCached);
inst->SetCached(bCached);
return NPERR_NO_ERROR;
}
case NPPVpluginUsesDOMForCursorBool: {

View File

@ -88,15 +88,12 @@ class SharedPluginTexture {
public:
NS_INLINE_DECL_REFCOUNTING(SharedPluginTexture)
SharedPluginTexture() :
mCurrentHandle(0), mNeedNewImage(false), mLock("SharedPluginTexture.mLock")
SharedPluginTexture() : mLock("SharedPluginTexture.mLock")
{
}
~SharedPluginTexture()
{
// This will be destroyed in the compositor (as it normally is)
mCurrentHandle = 0;
}
TextureInfo Lock()
@ -115,9 +112,7 @@ public:
}
void Release(TextureInfo& aTextureInfo)
{
mNeedNewImage = true;
{
mTextureInfo = aTextureInfo;
mLock.Unlock();
}
@ -126,33 +121,25 @@ public:
{
MutexAutoLock lock(mLock);
if (!mNeedNewImage)
return mCurrentHandle;
if (!EnsureGLContext())
return 0;
mNeedNewImage = false;
if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
return 0;
mCurrentHandle = sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, (void*)mTextureInfo.mTexture, GLContext::TextureID);
SharedTextureHandle handle = sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, (void*)mTextureInfo.mTexture, GLContext::TextureID);
// We want forget about this now, so delete the texture. Assigning it to zero
// ensures that we create a new one in Lock()
sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
mTextureInfo.mTexture = 0;
return mCurrentHandle;
return handle;
}
private:
TextureInfo mTextureInfo;
SharedTextureHandle mCurrentHandle;
bool mNeedNewImage;
Mutex mLock;
};
@ -1002,7 +989,7 @@ nsSurfaceTexture* nsNPAPIPluginInstance::CreateSurfaceTexture()
void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
{
if (mRunning == RUNNING && mOwner)
RedrawPlugin();
AndroidBridge::Bridge()->ScheduleComposite();
}
void* nsNPAPIPluginInstance::AcquireContentWindow()
@ -1120,11 +1107,10 @@ nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
return NS_OK;
}
nsresult
void
nsNPAPIPluginInstance::SetCached(bool aCache)
{
mCached = aCache;
return NS_OK;
}
bool

View File

@ -232,7 +232,7 @@ public:
mozilla::TimeStamp StopTime();
// cache this NPAPI plugin
nsresult SetCached(bool aCache);
void SetCached(bool aCache);
already_AddRefed<nsPIDOMWindow> GetDOMWindow();

View File

@ -3777,6 +3777,12 @@ void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
}
}
#endif
nsFocusManager* fm = nsFocusManager::GetFocusManager();
const nsIContent* content = aFrame->GetContent();
if (fm && content) {
mContentFocused = (content == fm->GetFocusedContent());
}
}
}

View File

@ -64,6 +64,7 @@ MOCHITEST_FILES = \
test_bug771202.html \
file_bug771202.html \
test_bug777098.html \
test_bug751809.html \
test_enumerate.html \
test_npruntime_construct.html \
307-xo-redirect.sjs \

View File

@ -0,0 +1,89 @@
<html>
<head>
<title>Bug 751809</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
const Ci = Components.interfaces;
const clickToPlayPref = "plugins.click_to_play";
const utils = window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
function waitForCondition(condition, nextTest, errorMsg) {
var tries = 0;
var interval = setInterval(function() {
if (tries >= 30) {
ok(false, errorMsg);
moveOn();
}
if (condition()) {
moveOn();
}
tries++;
}, 100);
var moveOn = function() { clearInterval(interval); nextTest(); };
}
function startFocusTest() {
var plugin = document.getElementById('plugin');
ok(plugin, "Got plugin element.");
var condition = function() plugin.getBoundingClientRect().width == 400;
waitForCondition(condition, afterPluginInsertion, "Waited too long for plugin to show up in page");
}
function afterPluginInsertion() {
var plugin = document.getElementById('plugin');
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "plugin should not be activated");
synthesizeMouseAtCenter(plugin, {}, window);
var condition = function() objLoadingContent.activated;
waitForCondition(condition, afterPluginActivation, "Waited too long for plugin to activate");
}
function afterPluginActivation() {
var plugin = document.getElementById('plugin');
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(objLoadingContent.activated, "plugin should be activated now");
is(plugin.getMouseUpEventCount(), 0, "Plugin should not have received mouse events yet.");
synthesizeMouseAtCenter(plugin, {}, window);
var condition = function() plugin.getMouseUpEventCount() > 0;
waitForCondition(condition, afterFirstClick, "Waited too long for plugin to receive the mouse click");
}
function afterFirstClick() {
var plugin = document.getElementById('plugin');
is(plugin.getMouseUpEventCount(), 1, "Plugin should have received 1 mouse up event.");
testsFinished();
}
function testsFinished() {
try {
SpecialPowers.clearUserPref(clickToPlayPref);
}
catch(e) {
ok(false, "Couldn't reset click-to-play pref");
}
SimpleTest.finish();
}
SpecialPowers.setBoolPref(clickToPlayPref, true);
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
document.write('<embed id="plugin" type="application/x-test" width="400" height="400" drawmode="solid" color="FF00FFFF"></embed>');
SimpleTest.executeSoon(startFocusTest);
</script>
</body>
</html>

View File

@ -24,4 +24,4 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) =
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-5-step.html plugin-background-ref.html
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-10-step.html plugin-background-ref.html
random-if(!haveTestPlugin) == plugin-transform-1.html plugin-transform-1-ref.html
fails-if(!haveTestPlugin) fails-if(http.platform=="X11"&&!layersGPUAccelerated) == plugin-transform-2.html plugin-transform-2-ref.html # bug 468496
fails-if(!haveTestPlugin) == plugin-transform-2.html plugin-transform-2-ref.html

View File

@ -163,6 +163,7 @@ static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t ar
static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static const NPUTF8* sPluginMethodIdentifierNames[] = {
"npnEvaluateTest",
@ -222,7 +223,8 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"setSitesWithData",
"setSitesWithDataCapabilities",
"getLastKeyText",
"getNPNVdocumentOrigin"
"getNPNVdocumentOrigin",
"getMouseUpEventCount"
};
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
static const ScriptableFunction sPluginMethodFunctions[] = {
@ -283,7 +285,8 @@ static const ScriptableFunction sPluginMethodFunctions[] = {
setSitesWithData,
setSitesWithDataCapabilities,
getLastKeyText,
getNPNVdocumentOrigin
getNPNVdocumentOrigin,
getMouseUpEventCount
};
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
@ -777,6 +780,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
instanceData->asyncDrawing = AD_NONE;
instanceData->frontBuffer = NULL;
instanceData->backBuffer = NULL;
instanceData->mouseUpEventCount = 0;
instance->pdata = instanceData;
TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass);
@ -3649,3 +3653,15 @@ bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argC
STRINGZ_TO_NPVARIANT(origin, *result);
return true;
}
bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
if (argCount != 0) {
return false;
}
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
INT32_TO_NPVARIANT(id->mouseUpEventCount, *result);
return true;
}

View File

@ -149,6 +149,7 @@ typedef struct InstanceData {
AsyncDrawing asyncDrawing;
NPAsyncSurface *frontBuffer;
NPAsyncSurface *backBuffer;
int32_t mouseUpEventCount;
} InstanceData;
void notifyDidPaint(InstanceData* instanceData);

View File

@ -254,6 +254,9 @@ ButtonEvent(GtkWidget* widget, GdkEventButton* event,
InstanceData* instanceData = static_cast<InstanceData*>(user_data);
instanceData->lastMouseX = event->x;
instanceData->lastMouseY = event->y;
if (event->type == GDK_BUTTON_RELEASE) {
instanceData->mouseUpEventCount++;
}
return TRUE;
}
@ -418,6 +421,9 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
XButtonEvent* button = &nsEvent->xbutton;
instanceData->lastMouseX = button->x;
instanceData->lastMouseY = button->y;
if (nsEvent->type == ButtonRelease) {
instanceData->mouseUpEventCount++;
}
break;
}
default:

View File

@ -276,6 +276,9 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
::GetWindowBounds(nativeWindow, kWindowStructureRgn, &globalBounds);
instanceData->lastMouseX = carbonEvent->where.h - w->x - globalBounds.left;
instanceData->lastMouseY = carbonEvent->where.v - w->y - globalBounds.top;
if (carbonEvent->what == mouseUp) {
instanceData->mouseUpEventCount++;
}
break;
}
default:
@ -299,6 +302,9 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
case NPCocoaEventMouseMoved:
instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX;
instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY;
if (cocoaEvent->type == NPCocoaEventMouseUp) {
instanceData->mouseUpEventCount++;
}
break;
case NPCocoaEventWindowFocusChanged:
instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus ?

View File

@ -193,6 +193,7 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
XButtonEvent* button = &nsEvent->xbutton;
instanceData->lastMouseX = button->x;
instanceData->lastMouseY = button->y;
instanceData->mouseUpEventCount++;
break;
}
default:

View File

@ -602,6 +602,9 @@ handleEventInternal(InstanceData* instanceData, NPEvent* pe, LRESULT* result)
int y = instanceData->hasWidget ? 0 : instanceData->winY;
instanceData->lastMouseX = GET_X_LPARAM(pe->lParam) - x;
instanceData->lastMouseY = GET_Y_LPARAM(pe->lParam) - y;
if ((UINT)pe->event == WM_LBUTTONUP) {
instanceData->mouseUpEventCount++;
}
return true;
}

View File

@ -30,7 +30,8 @@ sms.onreceived = function onreceived(event) {
is(message.receiver, null);
is(message.body, body);
ok(message.timestamp instanceof Date);
ok(message.timestamp.getTime() > now);
// SMSC timestamp is in seconds.
ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(now / 1000));
cleanUp();
};

View File

@ -68,6 +68,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIFrameMessageManager");
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
function MobileConnectionInfo() {}
MobileConnectionInfo.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileConnectionInfo]),
@ -240,7 +244,7 @@ RILContentHelper.prototype = {
let request = Services.DOMRequest.createRequest(window);
let requestId = this.getRequestId(request);
cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", requestId);
cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", {requestId: requestId});
return request;
},
@ -313,7 +317,7 @@ RILContentHelper.prototype = {
}
this._selectingNetwork = "automatic";
cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", requestId);
cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", {requestId: requestId});
return request;
},
@ -427,7 +431,10 @@ RILContentHelper.prototype = {
enumerateCalls: function enumerateCalls(callback) {
debug("Requesting enumeration of calls for callback: " + callback);
cpmm.sendAsyncMessage("RIL:EnumerateCalls");
// We need 'requestId' to meet the 'RILContentHelper <--> RadioInterfaceLayer'
// protocol.
let requestId = this._getRandomId();
cpmm.sendAsyncMessage("RIL:EnumerateCalls", {requestId: requestId});
if (!this._enumerationTelephonyCallbacks) {
this._enumerationTelephonyCallbacks = [];
}
@ -563,7 +570,7 @@ RILContentHelper.prototype = {
Services.obs.notifyObservers(null, kDataChangedTopic, null);
break;
case "RIL:EnumerateCalls":
this.handleEnumerateCalls(msg.json);
this.handleEnumerateCalls(msg.json.calls);
break;
case "RIL:GetAvailableNetworks":
this.handleGetAvailableNetworks(msg.json);
@ -722,6 +729,10 @@ RILContentHelper.prototype = {
}
},
_getRandomId: function _getRandomId() {
return gUUIDGenerator.generateUUID().toString();
},
_deliverCallback: function _deliverCallback(callbackType, name, args) {
let thisCallbacks = this[callbackType];
if (!thisCallbacks) {

View File

@ -194,6 +194,8 @@ function RadioInterfaceLayer() {
"ril.data.httpProxyHost",
"ril.data.httpProxyPort"];
this._messageManagerByRequest = {};
for each (let msgname in RIL_IPC_MSG_NAMES) {
ppmm.addMessageListener(msgname, this);
}
@ -228,7 +230,8 @@ RadioInterfaceLayer.prototype = {
// This message is sync.
return this.rilContext;
case "RIL:EnumerateCalls":
this.enumerateCalls();
this.saveRequestTarget(msg);
this.enumerateCalls(msg.json);
break;
case "RIL:GetMicrophoneMuted":
// This message is sync.
@ -270,26 +273,34 @@ RadioInterfaceLayer.prototype = {
this.resumeCall(msg.json);
break;
case "RIL:GetAvailableNetworks":
this.getAvailableNetworks(msg.json);
this.saveRequestTarget(msg);
this.getAvailableNetworks(msg.json.requestId);
break;
case "RIL:SelectNetwork":
this.saveRequestTarget(msg);
this.selectNetwork(msg.json);
break;
case "RIL:SelectNetworkAuto":
this.selectNetworkAuto(msg.json);
this.saveRequestTarget(msg);
this.selectNetworkAuto(msg.json.requestId);
case "RIL:GetCardLock":
this.saveRequestTarget(msg);
this.getCardLock(msg.json);
break;
case "RIL:UnlockCardLock":
this.saveRequestTarget(msg);
this.unlockCardLock(msg.json);
break;
case "RIL:SetCardLock":
this.saveRequestTarget(msg);
this.setCardLock(msg.json);
break;
case "RIL:SendUSSD":
this.saveRequestTarget(msg);
this.sendUSSD(msg.json);
break;
case "RIL:CancelUSSD":
this.saveRequestTarget(msg);
this.cancelUSSD(msg.json);
break;
}
@ -322,7 +333,7 @@ RadioInterfaceLayer.prototype = {
break;
case "enumerateCalls":
// This one will handle its own notifications.
this.handleEnumerateCalls(message.calls);
this.handleEnumerateCalls(message);
break;
case "callError":
this.handleCallError(message);
@ -435,6 +446,29 @@ RadioInterfaceLayer.prototype = {
}
},
_messageManagerByRequest: null,
saveRequestTarget: function saveRequestTarget(msg) {
let requestId = msg.json.requestId;
if (!requestId) {
// The content is not interested in a response;
return;
}
let mm = msg.target.QueryInterface(Ci.nsIFrameMessageManager);
this._messageManagerByRequest[requestId] = mm;
},
_sendRequestResults: function _sendRequestResults(requestType, options) {
let target = this._messageManagerByRequest[options.requestId];
delete this._messageManagerByRequest[options.requestId];
if (!target) {
return;
}
target.sendAsyncMessage(requestType, options);
},
updateNetworkInfo: function updateNetworkInfo(message) {
let voiceMessage = message[RIL.NETWORK_INFO_VOICE_REGISTRATION_STATE];
let dataMessage = message[RIL.NETWORK_INFO_DATA_REGISTRATION_STATE];
@ -733,12 +767,12 @@ RadioInterfaceLayer.prototype = {
/**
* Handle calls delivered in response to a 'enumerateCalls' request.
*/
handleEnumerateCalls: function handleEnumerateCalls(calls) {
debug("handleEnumerateCalls: " + JSON.stringify(calls));
for (let i in calls) {
calls[i].state = convertRILCallState(calls[i].state);
handleEnumerateCalls: function handleEnumerateCalls(options) {
debug("handleEnumerateCalls: " + JSON.stringify(options));
for (let i in options.calls) {
options.calls[i].state = convertRILCallState(options.calls[i].state);
}
ppmm.sendAsyncMessage("RIL:EnumerateCalls", calls);
this._sendRequestResults("RIL:EnumerateCalls", options);
},
/**
@ -747,7 +781,7 @@ RadioInterfaceLayer.prototype = {
handleGetAvailableNetworks: function handleGetAvailableNetworks(message) {
debug("handleGetAvailableNetworks: " + JSON.stringify(message));
ppmm.sendAsyncMessage("RIL:GetAvailableNetworks", message);
this._sendRequestResults("RIL:GetAvailableNetworks", message);
},
/**
@ -763,7 +797,7 @@ RadioInterfaceLayer.prototype = {
*/
handleSelectNetwork: function handleSelectNetwork(message) {
debug("handleSelectNetwork: " + JSON.stringify(message));
ppmm.sendAsyncMessage("RIL:SelectNetwork", message);
this._sendRequestResults("RIL:SelectNetwork", message);
},
/**
@ -771,7 +805,7 @@ RadioInterfaceLayer.prototype = {
*/
handleSelectNetworkAuto: function handleSelectNetworkAuto(message) {
debug("handleSelectNetworkAuto: " + JSON.stringify(message));
ppmm.sendAsyncMessage("RIL:SelectNetworkAuto", message);
this._sendRequestResults("RIL:SelectNetworkAuto", message);
},
/**
@ -957,7 +991,7 @@ RadioInterfaceLayer.prototype = {
},
handleICCCardLockResult: function handleICCCardLockResult(message) {
ppmm.sendAsyncMessage("RIL:CardLockResult", message);
this._sendRequestResults("RIL:CardLockResult", message);
},
handleUSSDReceived: function handleUSSDReceived(ussd) {
@ -969,14 +1003,14 @@ RadioInterfaceLayer.prototype = {
debug("handleSendUSSD " + JSON.stringify(message));
let messageType = message.success ? "RIL:SendUssd:Return:OK" :
"RIL:SendUssd:Return:KO";
ppmm.sendAsyncMessage(messageType, message);
this._sendRequestResults(messageType, message);
},
handleCancelUSSD: function handleCancelUSSD(message) {
debug("handleCancelUSSD " + JSON.stringify(message));
let messageType = message.success ? "RIL:CancelUssd:Return:OK" :
"RIL:CancelUssd:Return:KO";
ppmm.sendAsyncMessage(messageType, message);
this._sendRequestResults(messageType, message);
},
// nsIObserver
@ -1065,9 +1099,10 @@ RadioInterfaceLayer.prototype = {
// Handle phone functions of nsIRILContentHelper
enumerateCalls: function enumerateCalls() {
enumerateCalls: function enumerateCalls(message) {
debug("Requesting enumeration of calls for callback");
this.worker.postMessage({rilMessageType: "enumerateCalls"});
message.rilMessageType = "enumerateCalls";
this.worker.postMessage(message);
},
dial: function dial(number) {

View File

@ -638,11 +638,6 @@ let RIL = {
*/
currentCalls: {},
/**
* Current calls length.
*/
currentCallsLength: null,
/**
* Existing data calls.
*/
@ -2380,13 +2375,6 @@ let RIL = {
// Go through the calls we currently have on file and see if any of them
// changed state. Remove them from the newCalls map as we deal with them
// so that only new calls remain in the map after we're done.
let lastCallsLength = this.currentCallsLength;
if (newCalls) {
this.currentCallsLength = newCalls.length;
} else {
this.currentCallsLength = 0;
}
for each (let currentCall in this.currentCalls) {
let newCall;
if (newCalls) {
@ -2396,10 +2384,8 @@ let RIL = {
if (newCall) {
// Call is still valid.
if (newCall.state != currentCall.state ||
this.currentCallsLength != lastCallsLength) {
// State has changed. Active call may have changed as valid
// calls change.
if (newCall.state != currentCall.state) {
// State has changed.
currentCall.state = newCall.state;
currentCall.isActive = this._isActiveCall(currentCall.state);
this._handleChangedCallState(currentCall);
@ -2447,19 +2433,14 @@ let RIL = {
_isActiveCall: function _isActiveCall(callState) {
switch (callState) {
case CALL_STATE_INCOMING:
case CALL_STATE_ACTIVE:
case CALL_STATE_DIALING:
case CALL_STATE_ALERTING:
case CALL_STATE_ACTIVE:
return true;
case CALL_STATE_HOLDING:
return false;
case CALL_STATE_INCOMING:
case CALL_STATE_WAITING:
if (this.currentCallsLength == 1) {
return true;
} else {
return false;
}
return false;
}
},
@ -2824,13 +2805,14 @@ let RIL = {
/**
* Get a list of current voice calls.
*/
enumerateCalls: function enumerateCalls() {
enumerateCalls: function enumerateCalls(options) {
if (DEBUG) debug("Sending all current calls");
let calls = [];
for each (let call in this.currentCalls) {
calls.push(call);
}
this.sendDOMMessage({rilMessageType: "enumerateCalls", calls: calls});
options.calls = calls;
this.sendDOMMessage(options);
},
/**
@ -2977,7 +2959,6 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, opti
calls[call.callIndex] = call;
}
calls.length = calls_length;
this._processCalls(calls);
};
RIL[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
@ -3278,6 +3259,7 @@ RIL[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
}
options.rilMessageType = "sendussd";
options.success = options.rilRequestError == 0 ? true : false;
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
this.sendDOMMessage(options);
};
RIL[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
@ -3286,6 +3268,7 @@ RIL[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
}
options.rilMessageType = "cancelussd";
options.success = options.rilRequestError == 0 ? true : false;
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
this.sendDOMMessage(options);
};
RIL[REQUEST_GET_CLIR] = null;

View File

@ -78,10 +78,12 @@ DOMWifiManager.prototype = {
"WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
"WifiManager:associate:Return:OK", "WifiManager:associate:Return:NO",
"WifiManager:forget:Return:OK", "WifiManager:forget:Return:NO",
"WifiManager:wps:Return:OK", "WifiManager:wps:Return:NO",
"WifiManager:wifiDown", "WifiManager:wifiUp",
"WifiManager:onconnecting", "WifiManager:onassociate",
"WifiManager:onconnect", "WifiManager:ondisconnect",
"WifiManager:connectionInfoUpdate"];
"WifiManager:onwpstimeout", "WifiManager:onwpsfail",
"WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate"];
this.initHelper(aWindow, messages);
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
@ -163,6 +165,16 @@ DOMWifiManager.prototype = {
Services.DOMRequest.fireError(request, msg.data);
break;
case "WifiManager:wps:Return:OK":
request = this.takeRequest(msg.rid);
Services.DOMRequest.fireSuccess(request, true);
break;
case "WifiManager:wps:Return:NO":
request = this.takeRequest(msg.rid);
Services.DOMRequest.fireError(request, msg.data);
break;
case "WifiManager:wifiDown":
this._enabled = false;
this._currentNetwork = null;
@ -202,6 +214,27 @@ DOMWifiManager.prototype = {
this._fireStatusChangeEvent();
break;
case "WifiManager:onwpstimeout":
this._currentNetwork = null;
this._connectionStatus = "wps-timedout";
this._lastConnectionInfo = null;
this._fireStatusChangeEvent();
break;
case "WifiManager:onwpsfail":
this._currentNetwork = null;
this._connectionStatus = "wps-failed";
this._lastConnectionInfo = null;
this._fireStatusChangeEvent();
break;
case "WifiManager:onwpsoverlap":
this._currentNetwork = null;
this._connectionStatus = "wps-overlapped";
this._lastConnectionInfo = null;
this._fireStatusChangeEvent();
break;
case "WifiManager:connectionInfoUpdate":
this._lastConnectionInfo = msg;
this._fireConnectionInfoUpdate(msg);
@ -274,6 +307,14 @@ DOMWifiManager.prototype = {
return request;
},
wps: function nsIDOMWifiManager_wps(detail) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
var request = this.createRequest();
this._sendMessageForRequest("WifiManager:wps", detail, request);
return request;
},
get enabled() {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);

View File

@ -274,6 +274,14 @@ var WifiManager = (function() {
doSetScanModeCommand(setActive, callback);
}
function wpsPbcCommand(callback) {
doBooleanCommand("WPS_PBC", "OK", callback);
}
function wpsCancelCommand(callback) {
doBooleanCommand("WPS_CANCEL", "OK", callback);
}
function startDriverCommand(callback) {
doBooleanCommand("DRIVER START", "OK");
}
@ -747,7 +755,7 @@ var WifiManager = (function() {
// handle events sent to us by the event worker
function handleEvent(event) {
debug("Event coming in: " + event);
if (event.indexOf("CTRL-EVENT-") !== 0) {
if (event.indexOf("CTRL-EVENT-") !== 0 && event.indexOf("WPS") !== 0) {
if (event.indexOf("WPA:") == 0 &&
event.indexOf("pre-shared key may be incorrect") != -1) {
notify("passwordmaybeincorrect");
@ -835,6 +843,18 @@ var WifiManager = (function() {
notify("scanresultsavailable");
return true;
}
if (eventData.indexOf("WPS-TIMEOUT") === 0) {
notifyStateChange({ state: "WPS_TIMEOUT", BSSID: null, id: -1 });
return true;
}
if (eventData.indexOf("WPS-FAIL") === 0) {
notifyStateChange({ state: "WPS_FAIL", BSSID: null, id: -1 });
return true;
}
if (eventData.indexOf("WPS-OVERLAP-DETECTED") === 0) {
notifyStateChange({ state: "WPS_OVERLAP_DETECTED", BSSID: null, id: -1 });
return true;
}
// unknown event
return true;
}
@ -1155,6 +1175,8 @@ var WifiManager = (function() {
setScanModeCommand(mode === "active", callback);
}
manager.scan = scanCommand;
manager.wpsPbc = wpsPbcCommand;
manager.wpsCancel = wpsCancelCommand;
manager.getRssiApprox = getRssiApproxCommand;
manager.getLinkSpeed = getLinkSpeedCommand;
manager.getDhcpInfo = function() { return dhcpInfo; }
@ -1301,7 +1323,7 @@ function WifiWorker() {
this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
const messages = ["WifiManager:setEnabled", "WifiManager:getNetworks",
"WifiManager:associate", "WifiManager:forget",
"WifiManager:getState"];
"WifiManager:wps", "WifiManager:getState"];
messages.forEach((function(msgName) {
this._mm.addMessageListener(msgName, this);
@ -1528,6 +1550,15 @@ function WifiWorker() {
null);
break;
case "WPS_TIMEOUT":
self._fireEvent("onwpstimeout", {});
break;
case "WPS_FAIL":
self._fireEvent("onwpsfail", {});
break;
case "WPS_OVERLAP_DETECTED":
self._fireEvent("onwpsoverlap", {});
break;
}
};
@ -1861,6 +1892,9 @@ WifiWorker.prototype = {
case "WifiManager:forget":
this.forget(msg.data, msg.rid, msg.mid);
break;
case "WifiManager:wps":
this.wps(msg.data, msg.rid, msg.mid);
break;
case "WifiManager:getState": {
let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
return { network: net,
@ -2048,6 +2082,29 @@ WifiWorker.prototype = {
});
},
wps: function(detail, rid, mid) {
const message = "WifiManager:wps:Return";
let self = this;
if (detail.method === "pbc") {
WifiManager.wpsPbc(function(ok) {
if (ok)
self._sendMessage(message, true, true, rid, mid);
else
self._sendMessage(message, false, "WPS PBC failed", rid, mid);
});
} else if (detail.method === "cancel") {
WifiManager.wpsCancel(function(ok) {
if (ok)
self._sendMessage(message, true, true, rid, mid);
else
self._sendMessage(message, false, "WPS Cancel failed", rid, mid);
});
} else {
self._sendMessage(message, false, "Unknown wps method=" + detail.method +
" was received", rid, mid);
}
},
// This is a bit ugly, but works. In particular, this depends on the fact
// that RadioManager never actually tries to get the worker from us.
get worker() { throw "Not implemented"; },

View File

@ -17,7 +17,7 @@ interface nsIWifi : nsISupports
void shutdown();
};
[scriptable, uuid(eda793cd-0bb3-475e-9223-0e778856ebd1)]
[scriptable, uuid(b1f2e67f-75a8-4781-bf7f-eb21662ae9f3)]
interface nsIDOMWifiManager : nsISupports
{
/**
@ -63,6 +63,20 @@ interface nsIDOMWifiManager : nsISupports
*/
nsIDOMDOMRequest forget(in jsval network);
/**
* Wi-Fi Protected Setup functionality.
* @param detail WPS detail which has 'method' and 'pin' field.
* The possible method field values are:
* - pbc: The Push Button Configuration.
* - pin: The PIN configuration.
* - cancel: Request to cancel WPS in progress.
* If method field is 'pin', 'pin' field can exist and has
* a PIN number.
* onsuccess: We have successfully started/canceled wps.
* onerror: We have failed to start/cancel wps.
*/
nsIDOMDOMRequest wps(in jsval detail);
/**
* TODO Remove in favor of a settings API.
* Returns whether or not wifi is currently enabled.

View File

@ -1499,7 +1499,7 @@ XMLHttpRequest::ReleaseProxy(ReleaseType aType)
new AsyncTeardownRunnable(mProxy);
mProxy = nullptr;
if (NS_DispatchToMainThread(runnable)) {
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_ERROR("Failed to dispatch teardown runnable!");
}
} else {

View File

@ -1664,7 +1664,7 @@ void nsWebBrowser::WindowRaised(nsIWidget* aWidget)
nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(mDocShell);
nsAutoString documentURI;
domDocument->GetDocumentURI(documentURI);
printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)browser,
printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this,
NS_ConvertUTF16toUTF8(documentURI).get());
#endif
Activate();
@ -1676,7 +1676,7 @@ void nsWebBrowser::WindowLowered(nsIWidget* aWidget)
nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(mDocShell);
nsAutoString documentURI;
domDocument->GetDocumentURI(documentURI);
printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)browser,
printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this,
NS_ConvertUTF16toUTF8(documentURI).get());
#endif
Deactivate();

View File

@ -348,7 +348,8 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
mHasDirtyRect = false;
}
if (rect.IsEmpty()) {
mRect = IntRect(rect.x, rect.y, rect.width, rect.height);
if (mRect.IsEmpty()) {
return;
}
@ -361,19 +362,15 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
skipRect.Deflate(Size(aBlurRadius + aSpreadRadius));
mSkipRect = IntRect(skipRect.x, skipRect.y, skipRect.width, skipRect.height);
IntRect shadowIntRect(rect.x, rect.y, rect.width, rect.height);
mSkipRect.IntersectRect(mSkipRect, shadowIntRect);
if (mSkipRect.IsEqualInterior(shadowIntRect))
mSkipRect = mSkipRect.Intersect(mRect);
if (mSkipRect.IsEqualInterior(mRect))
return;
mSkipRect -= shadowIntRect.TopLeft();
mSkipRect -= mRect.TopLeft();
} else {
mSkipRect = IntRect(0, 0, 0, 0);
}
mRect = IntRect(rect.x, rect.y, rect.width, rect.height);
CheckedInt<int32_t> stride = RoundUpToMultipleOf4(mRect.width);
if (stride.isValid()) {
mStride = stride.value();

View File

@ -10,6 +10,7 @@
#include "gfxImageSurface.h"
#include "gfxSharedImageSurface.h"
#include "yuv_convert.h"
#include "gfxUtils.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/ImageContainerChild.h"
@ -464,28 +465,22 @@ PlanarYCbCrImage::GetAsSurface()
return result.forget();
}
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
gfx::YUVType type =
gfx::TypeFromSize(mData.mYSize.width,
mData.mYSize.height,
mData.mCbCrSize.width,
mData.mCbCrSize.height);
gfxASurface::gfxImageFormat format = GetOffscreenFormat();
// Convert from YCbCr to RGB now
gfx::ConvertYCbCrToRGB32(mData.mYChannel,
mData.mCbChannel,
mData.mCrChannel,
imageSurface->Data(),
mData.mPicX,
mData.mPicY,
mData.mPicSize.width,
mData.mPicSize.height,
mData.mYStride,
mData.mCbCrStride,
imageSurface->Stride(),
type);
gfxIntSize size(mSize);
gfxUtils::GetYCbCrToRGBDestFormatAndSize(mData, format, size);
if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
size.height > PlanarYCbCrImage::MAX_DIMENSION) {
NS_ERROR("Illegal image dest width or height");
return nullptr;
}
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(mSize, format);
gfxUtils::ConvertYCbCrToRGB(mData, format, mSize,
imageSurface->Data(),
imageSurface->Stride());
mSurface = imageSurface;

View File

@ -9,6 +9,9 @@
#include "gfxUtils.h"
#include "gfxSharedImageSurface.h"
#include "mozilla/layers/ImageContainerChild.h"
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
using namespace mozilla::gfx;
@ -130,17 +133,17 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
// outside the bounds of the video image.
gfxPattern::GraphicsExtend extend = gfxPattern::EXTEND_PAD;
#ifdef MOZ_X11
// PAD is slow with cairo and old X11 servers, so prefer speed over
// correctness and use NONE.
if (aContext->IsCairo()) {
// PAD is slow with X11 and Quartz surfaces, so prefer speed over correctness
// and use NONE.
nsRefPtr<gfxASurface> target = aContext->CurrentSurface();
gfxASurface::gfxSurfaceType type = target->GetType();
if (type == gfxASurface::SurfaceTypeXlib ||
type == gfxASurface::SurfaceTypeXcb ||
type == gfxASurface::SurfaceTypeQuartz) {
if (target->GetType() == gfxASurface::SurfaceTypeXlib &&
static_cast<gfxXlibSurface*>(target.get())->IsPadSlow()) {
extend = gfxPattern::EXTEND_NONE;
}
}
#endif
aContext->NewPath();
// No need to snap here; our transform has already taken care of it.

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>glyph clipping (reference)</title>
<style>
#clip { position: absolute;
overflow: hidden;
font-size: 16px;
width: 500px;
height: 300px;}
/* Offsets keep the text far enough away from clip boundaries so that
cairo knows the text is within the clip. Non-unit alpha color makes
the bug show even without antialiasing. */
#text { position: absolute;
left: 100px;
top: 100px;
color: rgba(0,0,0,0.4)}
#cover { position: absolute;
top: 90px;
left: 120px;
height: 50px;
width: 60px;
background: transparent; }
#mod { position: absolute;
top: 400px;
left: 0px;
height: 2000px;
width: 600px;
background: transparent; }
</style>
</head>
<body>
<div id="clip">
<div id="text">
Some text that was</br>
initially partially covered.</br>
</div>
</div>
<div id="cover">
</div>
<div id="mod">
</div>
</body>
<script>
scrollTo(0,1);
</script>
</html>

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<title>glyph clipping (test)</title>
<style>
#clip { position: absolute;
overflow: hidden;
font-size: 16px;
width: 500px;
height: 300px;}
/* Offsets keep the text far enough away from clip boundaries so that
cairo knows the text is within the clip. Non-unit alpha color makes
the bug show even without antialiasing. */
#text { position: absolute;
left: 100px;
top: 100px;
color: rgba(0,0,0,0.4)}
#cover { position: absolute;
top: 90px;
left: 120px;
height: 50px;
width: 60px;
background: green; }
#mod { position: absolute;
top: 400px;
left: 0px;
height: 2000px;
width: 600px;
background: green; }
</style>
<script>
function doPaint()
{
window.addEventListener("MozAfterPaint", doScroll, false);
var cover = document.getElementById("cover");
cover.style.background = "transparent";
var mod = document.getElementById("mod");
mod.style.background = "transparent";
}
function doScroll()
{
window.removeEventListener("MozAfterPaint", doScroll, false);
window.addEventListener("MozAfterPaint", endTest, false);
scrollTo(0,1);
}
function endTest()
{
document.documentElement.removeAttribute("class");
}
document.addEventListener("MozReftestInvalidate", doPaint, false);
</script>
</head>
<body>
<div id="clip">
<div id="text">
Some text that was</br>
initially partially covered.</br>
</div>
</div>
<div id="cover">
</div>
<div id="mod">
</div>
</body>
</html>

View File

@ -1,3 +1,4 @@
# 468496-1 will also detect bugs in video drivers.
fails-if(/Mac\x20OS\x20X\x2010\.5/.test(http.oscpu)) == 468496-1.html 468496-1-ref.html # bug 486761, 660740
== 611498-1.html 611498-ref.html
# fails-if(/Mac\x20OS\x20X\x2010\.5/.test(http.oscpu)) == 468496-1.html 468496-1-ref.html # bug 486761, 660740
random-if(bug685516) == 611498-1.html 611498-ref.html
fails-if(http.platform=="X11") == 709477-1.html 709477-1-ref.html

View File

@ -73,15 +73,7 @@ PreparePatternForUntiledDrawing(gfxPattern* aPattern,
// Cairo, and hence Gecko, can use RepeatPad on Xorg 1.7. We
// enable EXTEND_PAD provided that we're running on a recent
// enough X server.
gfxXlibSurface *xlibSurface =
static_cast<gfxXlibSurface *>(currentTarget);
Display *dpy = xlibSurface->XDisplay();
// This is the exact condition for cairo to avoid XRender for
// EXTEND_PAD
if (VendorRelease(dpy) >= 60700000 ||
VendorRelease(dpy) < 10699000) {
if (static_cast<gfxXlibSurface*>(currentTarget)->IsPadSlow()) {
bool isDownscale =
aDeviceToImage.xx >= 1.0 && aDeviceToImage.yy >= 1.0 &&
aDeviceToImage.xy == 0.0 && aDeviceToImage.yx == 0.0;

View File

@ -79,6 +79,18 @@ public:
GLXPixmap GetGLXPixmap();
#endif
// Return true if cairo will take its slow path when this surface is used
// in a pattern with EXTEND_PAD. As a workaround for XRender's RepeatPad
// not being implemented correctly on old X servers, cairo avoids XRender
// and instead reads back to perform EXTEND_PAD with pixman. Cairo does
// this for servers older than xorg-server 1.7.
bool IsPadSlow() {
// The test here matches that for buggy_pad_reflect in
// _cairo_xlib_device_create.
return VendorRelease(mDisplay) >= 60700000 ||
VendorRelease(mDisplay) < 10699000;
}
protected:
// if TakePixmap() has been called on this
bool mPixmapTaken;

View File

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Hal.h"
#include "mozilla/AppProcessPermissions.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/hal_sandbox/PHalChild.h"
#include "mozilla/hal_sandbox/PHalParent.h"
@ -300,12 +301,15 @@ public:
const InfallibleTArray<uint64_t> &id,
PBrowserParent *browserParent) MOZ_OVERRIDE
{
// We give all content vibration permission.
// Check whether browserParent is active. We should have already
// checked that the corresponding window is active, but this check
// isn't redundant. A window may be inactive in an active
// browser. And a window is not notified synchronously when it's
// deactivated, so the window may think it's active when the tab
// is actually inactive.
// is actually inactive. This also mitigates user annoyance that
// buggy/malicious processes could cause.
TabParent *tabParent = static_cast<TabParent*>(browserParent);
if (!tabParent->Active()) {
HAL_LOG(("RecvVibrate: Tab is not active. Cancelling."));
@ -336,6 +340,7 @@ public:
virtual bool
RecvEnableBatteryNotifications() MOZ_OVERRIDE {
// We give all content battery-status permission.
hal::RegisterBatteryObserver(this);
return true;
}
@ -348,6 +353,7 @@ public:
virtual bool
RecvGetCurrentBatteryInformation(BatteryInformation* aBatteryInfo) MOZ_OVERRIDE {
// We give all content battery-status permission.
hal::GetCurrentBatteryInformation(aBatteryInfo);
return true;
}
@ -358,6 +364,7 @@ public:
virtual bool
RecvEnableNetworkNotifications() MOZ_OVERRIDE {
// We give all content access to this network-status information.
hal::RegisterNetworkObserver(this);
return true;
}
@ -380,6 +387,8 @@ public:
virtual bool
RecvEnableScreenConfigurationNotifications() MOZ_OVERRIDE {
// Screen configuration is used to implement CSS and DOM
// properties, so all content already has access to this.
hal::RegisterScreenConfigurationObserver(this);
return true;
}
@ -399,6 +408,10 @@ public:
virtual bool
RecvLockScreenOrientation(const dom::ScreenOrientation& aOrientation, bool* aAllowed) MOZ_OVERRIDE
{
// FIXME/bug 777980: unprivileged content may only lock
// orientation while fullscreen. We should check whether the
// request comes from an actor in a process that might be
// fullscreen. We don't have that information currently.
*aAllowed = hal::LockScreenOrientation(aOrientation);
return true;
}
@ -417,6 +430,9 @@ public:
virtual bool
RecvGetScreenEnabled(bool *enabled) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
*enabled = hal::GetScreenEnabled();
return true;
}
@ -424,6 +440,9 @@ public:
virtual bool
RecvSetScreenEnabled(const bool &enabled) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::SetScreenEnabled(enabled);
return true;
}
@ -431,6 +450,9 @@ public:
virtual bool
RecvGetCpuSleepAllowed(bool *allowed) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
*allowed = hal::GetCpuSleepAllowed();
return true;
}
@ -438,6 +460,9 @@ public:
virtual bool
RecvSetCpuSleepAllowed(const bool &allowed) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::SetCpuSleepAllowed(allowed);
return true;
}
@ -445,6 +470,9 @@ public:
virtual bool
RecvGetScreenBrightness(double *brightness) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
*brightness = hal::GetScreenBrightness();
return true;
}
@ -452,6 +480,9 @@ public:
virtual bool
RecvSetScreenBrightness(const double &brightness) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::SetScreenBrightness(brightness);
return true;
}
@ -459,6 +490,13 @@ public:
virtual bool
RecvSetLight(const LightType& aLight, const hal::LightConfiguration& aConfig, bool *status) MOZ_OVERRIDE
{
// XXX currently, the hardware key light and screen backlight are
// controlled as a unit. Those are set through the power API, and
// there's no other way to poke lights currently, so we require
// "power" privileges here.
if (!AppProcessHasPermission(this, "power")) {
return false;
}
*status = hal::SetLight(aLight, aConfig);
return true;
}
@ -466,6 +504,9 @@ public:
virtual bool
RecvGetLight(const LightType& aLight, LightConfiguration* aConfig, bool* status) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
*status = hal::GetLight(aLight, aConfig);
return true;
}
@ -473,6 +514,9 @@ public:
virtual bool
RecvAdjustSystemClock(const int32_t &aDeltaMilliseconds) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "systemclock-write")) {
return false;
}
hal::AdjustSystemClock(aDeltaMilliseconds);
return true;
}
@ -480,6 +524,9 @@ public:
virtual bool
RecvSetTimezone(const nsCString& aTimezoneSpec) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "systemclock-write")) {
return false;
}
hal::SetTimezone(aTimezoneSpec);
return true;
}
@ -487,6 +534,9 @@ public:
virtual bool
RecvReboot() MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::Reboot();
return true;
}
@ -494,12 +544,17 @@ public:
virtual bool
RecvPowerOff() MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::PowerOff();
return true;
}
virtual bool
RecvEnableSensorNotifications(const SensorType &aSensor) MOZ_OVERRIDE {
// We currently allow any content to register device-sensor
// listeners.
hal::RegisterSensorObserver(aSensor, this);
return true;
}
@ -519,6 +574,9 @@ public:
const WakeLockControl &aLockAdjust,
const WakeLockControl &aHiddenAdjust) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust);
return true;
}
@ -526,6 +584,9 @@ public:
virtual bool
RecvEnableWakeLockNotifications() MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::RegisterWakeLockObserver(this);
return true;
}
@ -540,6 +601,9 @@ public:
virtual bool
RecvGetWakeLockInfo(const nsString &aTopic, WakeLockInformation *aWakeLockInfo) MOZ_OVERRIDE
{
if (!AppProcessHasPermission(this, "power")) {
return false;
}
hal::GetWakeLockInfo(aTopic, aWakeLockInfo);
return true;
}
@ -552,8 +616,8 @@ public:
virtual bool
RecvEnableSwitchNotifications(const SwitchDevice& aDevice) MOZ_OVERRIDE
{
hal::RegisterSwitchObserver(aDevice, this);
return true;
// Content has no reason to listen to switch events currently.
return false;
}
virtual bool
@ -571,8 +635,8 @@ public:
virtual bool
RecvGetCurrentSwitchState(const SwitchDevice& aDevice, hal::SwitchState *aState) MOZ_OVERRIDE
{
*aState = hal::GetCurrentSwitchState(aDevice);
return true;
// Content has no reason to listen to switch events currently.
return false;
}
virtual bool

View File

@ -93,7 +93,7 @@ InitPrefCaches()
#define CONTAINER_ENSURE_SUCCESS(status) \
PR_BEGIN_MACRO \
nsresult _status = status; /* eval once */ \
if (_status) { \
if (NS_FAILED(_status)) { \
LOG_CONTAINER_ERROR; \
DoError(); \
return _status; \

View File

@ -47,4 +47,4 @@ random-if(bug685516) == jpg-srgb-icc.jpg jpg-srgb-icc.png
# won't be in the text of the contents themselves. --$(boundary)\r\n means
# "Here is the beginning of a boundary," and --$(boundary)-- means "All done
# sending you parts.")
HTTP == webcam-simulacrum.mjpg blue.jpg
random-if(bug685516) HTTP == webcam-simulacrum.mjpg blue.jpg

Some files were not shown because too many files have changed in this diff Show More