Merge m-c to inbound.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2013-10-09 15:34:02 -04:00
commit 700df6f454
70 changed files with 958 additions and 525 deletions

View File

@ -1,4 +1,4 @@
{
"revision": "064b829074c2088d866b022c8d942c07744ff9b9",
"revision": "916fa42b75d23393752647ef2b44da15e2e1dd52",
"repo_path": "/integration/gaia-central"
}

View File

@ -6433,6 +6433,14 @@ var gIdentityHandler = {
this._permissionList = document.getElementById("identity-popup-permission-list");
},
/**
* Handler for commands on the help button in the "identity-popup" panel.
*/
handleHelpCommand : function(event) {
openHelpLink("secure-connection");
this._identityPopup.hidePopup();
},
/**
* Handler for mouseclicks on the "More Information" button in the
* "identity-popup" panel.

View File

@ -342,7 +342,11 @@
</vbox>
</hbox>
<!-- Footer button to open security page info -->
<hbox id="identity-popup-button-container" pack="end">
<hbox id="identity-popup-button-container" align="center">
<button id="identity-popup-help-icon"
oncommand="gIdentityHandler.handleHelpCommand(event);"
tooltiptext="&identity.help.tooltip;"/>
<spacer flex="1"/>
<button id="identity-popup-more-info-button"
label="&identity.moreInfoLinkText;"
oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>

View File

@ -557,10 +557,7 @@ var BookmarkPropertiesPanel = {
if (this._loadInSidebar) {
let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
type : Ci.nsIAnnotationService.TYPE_INT32,
flags : 0,
value : this._loadInSidebar,
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
value : true };
let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
childTransactions.push(setLoadTxn);
}

View File

@ -589,14 +589,10 @@ var gEditItemOverlay = {
onLoadInSidebarCheckboxCommand:
function EIO_onLoadInSidebarCheckboxCommand() {
var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
var annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
type : Ci.nsIAnnotationService.TYPE_INT32,
flags : 0,
value : loadInSidebarChecked,
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
var txn = new PlacesSetItemAnnotationTransaction(this._itemId,
annoObj);
let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO };
if (this._element("loadInSidebarCheckbox").checked)
annoObj.value = true;
let txn = new PlacesSetItemAnnotationTransaction(this._itemId, annoObj);
PlacesUtils.transactionManager.doTransaction(txn);
},

View File

@ -40,7 +40,14 @@ const IDB = {
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
projects.push(cursor.value);
if (cursor.value.location) {
// We need to make sure this object has a `.location` property.
// The UI depends on this property.
// This should not be needed as we make sure to register valid
// projects, but in the past (before bug 924568), we might have
// registered invalid objects.
projects.push(cursor.value);
}
cursor.continue();
} else {
deferred.resolve(projects);
@ -54,16 +61,21 @@ const IDB = {
add: function(project) {
let deferred = promise.defer();
var transaction = IDB._db.transaction(["projects"], "readwrite");
var objectStore = transaction.objectStore("projects");
var request = objectStore.add(project);
request.onerror = function(event) {
deferred.reject("Unable to add project to the AppProjects indexedDB: " +
this.error.name + " - " + this.error.message );
};
request.onsuccess = function() {
deferred.resolve();
};
if (!project.location) {
// We need to make sure this object has a `.location` property.
deferred.reject("Missing location property on project object.");
} else {
let transaction = IDB._db.transaction(["projects"], "readwrite");
let objectStore = transaction.objectStore("projects");
let request = objectStore.add(project);
request.onerror = function(event) {
deferred.reject("Unable to add project to the AppProjects indexedDB: " +
this.error.name + " - " + this.error.message );
};
request.onsuccess = function() {
deferred.resolve();
};
}
return deferred.promise;
},

View File

@ -82,6 +82,10 @@ let UI = {
},
addHosted: function() {
let form = document.querySelector("#new-hosted-project-wrapper")
if (!form.checkValidity())
return;
let urlInput = document.querySelector("#url-input");
let manifestURL = urlInput.value;
AppProjects.addHosted(manifestURL)
@ -208,8 +212,10 @@ let UI = {
},
install: function(project) {
this.connection.log("Installing the " + project.manifest.name + " app...");
let installPromise;
if (project.type == "packaged") {
return installPackaged(this.connection.client, this.listTabsResponse.webappsActor, project.location, project.packagedAppOrigin)
installPromise = installPackaged(this.connection.client, this.listTabsResponse.webappsActor, project.location, project.packagedAppOrigin)
.then(({ appId }) => {
// If the packaged app specified a custom origin override,
// we need to update the local project origin
@ -225,8 +231,16 @@ let UI = {
origin: origin.spec,
manifestURL: project.location
};
return installHosted(this.connection.client, this.listTabsResponse.webappsActor, appId, metadata, project.manifest);
installPromise = installHosted(this.connection.client, this.listTabsResponse.webappsActor, appId, metadata, project.manifest);
}
installPromise.then(() => {
this.connection.log("Install completed.");
}, () => {
this.connection.log("Install failed.");
});
return installPromise;
},
start: function(project) {

View File

@ -25,7 +25,7 @@
<div id="new-packaged-project" onclick="UI.addPackaged()" title="&projects.addPackagedTooltip;">&projects.addPackaged;</div>
<div id="new-hosted-project">&projects.addHosted;
<form onsubmit="UI.addHosted(); return false;" id="new-hosted-project-wrapper">
<input value="" id="url-input" type="url" pattern="https?://.+" placeholder="&projects.hostedManifestPlaceHolder2;" size="50" />
<input value="" id="url-input" type="url" required="true" pattern="https?://.+" placeholder="&projects.hostedManifestPlaceHolder2;" size="50" />
<div onclick="UI.addHosted()" id="new-hosted-project-click" title="&projects.addHostedTooltip;"></div>
<input type="submit" hidden="true"></input>
</form>

View File

@ -18,7 +18,6 @@ const CONTAINER_FLASHING_DURATION = 500;
const {UndoStack} = require("devtools/shared/undo");
const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
const {colorUtils} = require("devtools/css-color");
const promise = require("sdk/core/promise");
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
@ -410,7 +409,7 @@ MarkupView.prototype = {
continue;
}
if (type === "attributes" || type === "characterData") {
container.update(false);
container.update();
} else if (type === "childList") {
container.childrenDirty = true;
// Update the children to take care of changes in the DOM
@ -1151,9 +1150,9 @@ MarkupContainer.prototype = {
* Update the container's editor to the current state of the
* viewed node.
*/
update: function(parseColors=true) {
update: function() {
if (this.editor.update) {
this.editor.update(parseColors);
this.editor.update();
}
},
@ -1367,7 +1366,7 @@ ElementEditor.prototype = {
/**
* Update the state of the editor from the node.
*/
update: function(parseColors=true) {
update: function() {
let attrs = this.node.attributes;
if (!attrs) {
return;
@ -1386,9 +1385,6 @@ ElementEditor.prototype = {
// Get the attribute editor for each attribute that exists on
// the node and show it.
for (let attr of attrs) {
if (parseColors && typeof attr.value !== "undefined") {
attr.value = colorUtils.processCSSString(attr.value);
}
let attribute = this._createAttribute(attr);
if (!attribute.inplaceEditor) {
attribute.style.removeProperty("display");

View File

@ -4,7 +4,6 @@ support-files = head.js
[browser_bug896181_css_mixed_completion_new_attribute.js]
# Bug 916763 - too many intermittent failures
skip-if = true
[browser_inspector_markup_colorconversion.js]
[browser_inspector_markup_edit.html]
[browser_inspector_markup_edit.js]
[browser_inspector_markup_mutation.html]

View File

@ -1,90 +0,0 @@
/* Any copyright", " is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
let inspector;
let doc;
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html,browser_inspector_markupview_colorconversion.js";
function createDocument() {
doc.body.innerHTML = '' +
'<span style="color:red; border-radius:10px; ' +
'background-color:rgba(0, 255, 0, 1); display: inline-block;">' +
'Some styled text</span>';
doc.title = "Style Inspector key binding test";
setupTest();
}
function setupTest() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.once("inspector-updated", checkColors);
});
}
function checkColors() {
let node = content.document.querySelector("span");
assertAttributes(node, {
style: "color:#F00; border-radius:10px; background-color:#0F0; display: inline-block;"
}).then(() => {
finishUp();
});
}
// This version of assertAttributes is different from that in other markup
// view tests. This is because in most tests we are checking the node
// attributes but here we need the actual values displayed in the markup panel.
function assertAttributes(node, attributes) {
let deferred = promise.defer();
let attrsToCheck = Object.getOwnPropertyNames(attributes);
ok(node, "captain, we have the node");
let checkAttrs = function() {
let container = inspector.markup._selectedContainer;
let nodeAttrs = container.editor.attrs;
is(node.attributes.length, attrsToCheck.length,
"Node has the correct number of attributes");
for (let attr of attrsToCheck) {
ok(nodeAttrs[attr], "Node has a " + attr + "attribute");
let nodeAttributeText = nodeAttrs[attr].textContent;
[, nodeAttributeText] = nodeAttributeText.match(/^\s*[\w-]+\s*=\s*"(.*)"$/);
is(nodeAttributeText, attributes[attr],
"Node has the correct " + attr + " attribute value.");
}
deferred.resolve();
};
if (inspector.selection.node == node) {
checkAttrs();
} else {
inspector.once("inspector-updated", () => {
checkAttrs();
});
inspector.selection.setNode(node);
}
return deferred.promise;
}
function finishUp() {
doc = inspector = null;
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -1748,8 +1748,8 @@ function TextPropertyEditor(aRuleEditor, aProperty)
this.browserWindow = this.doc.defaultView.top;
this.removeOnRevert = this.prop.value === "";
let sheet = this.prop.rule.sheet;
let href = sheet ? (sheet.href || sheet.nodeHref) : null;
let domRule = this.prop.rule.domRule;
let href = domRule ? domRule.href : null;
if (href) {
this.sheetURI = IOService.newURI(href, null, null);
}

View File

@ -14,7 +14,9 @@
<div class="base64">Background image with base64 url (loaded from external css)</div>
<div class="inline" style="background: url(test-image.png);">Background image with relative path (loaded from style attribute)</div>';
<div class="inline" style="background: url(test-image.png);">Background image with relative path (loaded from style attribute)</div>
<div class="inline-resolved" style="background-image: url(./test-image.png)">Background image with resolved relative path (loaded from style attribute)</div>
<div class="noimage">No background image :(</div>
</body>

View File

@ -26,12 +26,14 @@ function selectNode(aInspector, aRuleView)
let inline = doc.querySelector(".inline");
let base64 = doc.querySelector(".base64");
let noimage = doc.querySelector(".noimage");
let inlineresolved = doc.querySelector(".inline-resolved");
ok(relative, "captain, we have the relative div");
ok(absolute, "captain, we have the absolute div");
ok(inline, "captain, we have the inline div");
ok(base64, "captain, we have the base64 div");
ok(noimage, "captain, we have the noimage div");
ok(inlineresolved, "captain, we have the inlineresolved div");
inspector.selection.setNode(relative);
inspector.once("inspector-updated", () => {
@ -61,12 +63,20 @@ function selectNode(aInspector, aRuleView)
ok (base64Link, "Link exists for base64 node");
ok (base64Link.getAttribute("href"), BASE_64_URL);
inspector.selection.setNode(noimage);
inspector.selection.setNode(inlineresolved);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, noimage, "selection matches the inline element");
let noimageLink = contentDoc.querySelector(".ruleview-propertycontainer a");
ok (!noimageLink, "There is no link for the node with no background image");
finishUp();
is(inspector.selection.node, inlineresolved, "selection matches the style tag element");
let inlineResolvedLink = contentDoc.querySelector(".ruleview-propertycontainer a");
ok (inlineResolvedLink, "Link exists for style tag node");
ok (inlineResolvedLink.getAttribute("href"), TEST_IMAGE);
inspector.selection.setNode(noimage);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, noimage, "selection matches the inline element");
let noimageLink = contentDoc.querySelector(".ruleview-propertycontainer a");
ok (!noimageLink, "There is no link for the node with no background image");
finishUp();
});
});
});
});

View File

@ -606,6 +606,11 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY identity.permissions "Permissions">
<!-- LOCALIZATION NOTE (identity.help.tooltip) : This string should be the
localized title of this SUMO article
https://support.mozilla.org/kb/how-do-i-tell-if-my-connection-is-secure -->
<!ENTITY identity.help.tooltip "How do I tell if my connection to a website is secure?">
<!-- Name for the tabs toolbar as spoken by screen readers.
The word "toolbar" is appended automatically and should not be contained below! -->
<!ENTITY tabsToolbar.label "Browser tabs">

View File

@ -631,16 +631,6 @@
#endif
<flyoutpanel id="prefs-flyoutpanel" class="flyout-narrow" headertext="&optionsHeader.title;">
<settings id="prefs-startup" label="&optionsHeader.startup.title;"> <!-- note, this element has a custom margin-top -->
<setting id="prefs-homepage" title="&optionsHeader.homepage.title;" type="menulist" pref="browser.startup.sessionRestore" class="setting-expanded">
<menulist id="prefs-homepage-options">
<menupopup id="prefs-homepage-popup" position="after_end">
<menuitem id="prefs-homepage-default" label="&optionsHeader.homepage.startPage.button;" value="false"/>
<menuitem id="prefs-homepage-session" label="&optionsHeader.homepage.sessionRestore.button;" value="true"/>
</menupopup>
</menulist>
</setting>
</settings>
<settings id="prefs-charencoding" label="&optionsHeader.char.title;">
<setting pref="browser.menu.showCharacterEncoding" title="&optionsHeader.char.options.label;" type="bool"/>
</settings>

View File

@ -7,10 +7,6 @@
<!-- ## Options Flyout Panel ## -->
<!ENTITY optionsHeader.title "Options">
<!ENTITY optionsHeader.startup.title "Startup">
<!ENTITY optionsHeader.homepage.title "When &brandShortName; starts, show">
<!ENTITY optionsHeader.homepage.startPage.button "start page">
<!ENTITY optionsHeader.homepage.sessionRestore.button "tabs from last time">
<!ENTITY optionsHeader.char.title "Character Encoding">
<!ENTITY optionsHeader.char.autodetect.label "Auto-detect">
<!ENTITY optionsHeader.char.options.label "Show encoding options on the App Bar">

View File

@ -1096,6 +1096,30 @@ toolbar[iconsize="small"] #webrtc-status-button {
list-style-image: url("chrome://browser/skin/Secure.png");
}
#identity-popup-help-icon {
-moz-appearance: none;
margin-left: 0px;
border: none;
background: none;
min-width: 0;
list-style-image: url("chrome://global/skin/icons/question-16.png");
cursor: pointer;
}
#identity-popup-help-icon > .button-box > .button-text {
display: none;
}
#identity-popup-help-icon > .button-box > .button-icon {
height: 16px;
width: 16px;
}
#identity-popup-help-icon:-moz-focusring {
outline: 1px dotted;
outline-offset: 1px;
}
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}

View File

@ -3036,12 +3036,43 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
list-style-image: url("chrome://browser/skin/Secure-Glyph.png");
}
#identity-popup-help-icon {
-moz-appearance: none;
border: none;
margin: 10px 0 0 2px;
background: none;
min-width: 0;
list-style-image: url("chrome://global/skin/icons/question-16.png");
cursor: pointer;
}
#identity-popup-help-icon > .button-box > .button-text {
display: none;
}
#identity-popup-help-icon > .button-box > .button-icon {
height: 16px;
width: 16px;
}
#identity-popup-help-icon:focus {
@hudButtonFocused@
}
#identity-popup-help-icon:hover:active {
@hudButtonPressed@
}
@media (min-resolution: 2dppx) {
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
list-style-image: url("chrome://browser/skin/Secure-Glyph@2x.png");
width: 24px;
}
#identity-popup-help-icon {
list-style-image: url("chrome://global/skin/icons/question-32.png");
}
}
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {

View File

@ -85,6 +85,12 @@ button {
display: none;
}
.app-buttons > button[disabled] {
background-color: transparent;
opacity: 0.4;
pointer-events: none;
}
.app[running="false"] > .app-buttons > .button-start,
.app[running="true"] > .app-buttons > .button-stop,
.app[running="true"] > .app-buttons > .button-debug {
@ -100,6 +106,10 @@ button {
color: #FFF;
}
.button-debug[disabled] {
color: #3498DB;
}
.button-start {
color: #18BC9C
}
@ -109,6 +119,10 @@ button {
color: #FFF;
}
.button-start[disabled] {
color: #18BC9C
}
.button-stop {
color: #E74C3C;
}
@ -118,6 +132,10 @@ button {
color: #FFF;
}
.button-stop[disabled] {
color: #E74C3C;
}
/***************** PERMISSIONS *****************/

View File

@ -345,6 +345,12 @@ strong {
text-transform: uppercase;
}
.project-buttons > button[disabled] {
background-color: transparent;
opacity: 0.4;
pointer-events: none;
}
.project-buttons > button:first-child {
border-left-width: 1px;
}
@ -358,6 +364,10 @@ strong {
color: #FFF;
}
.project-button-debug[disabled] {
color: #3498DB;
}
.project-button-update {
color: #777;
}
@ -367,6 +377,10 @@ strong {
color: #FFF;
}
.project-button-update[disabled] {
color: #777;
}
/********* ERRORS AND WARNINGS ***********/

View File

@ -2361,6 +2361,30 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
list-style-image: url("chrome://browser/skin/Secure24.png");
}
#identity-popup-help-icon {
-moz-appearance: none;
border: none;
margin: 7px 0 0 -3px;
background: none;
min-width: 0;
list-style-image: url("chrome://global/skin/icons/question-16.png");
cursor: pointer;
}
#identity-popup-help-icon > .button-box > .button-text {
display: none;
}
#identity-popup-help-icon > .button-box > .button-icon {
height: 16px;
width: 16px;
}
#identity-popup-help-icon:-moz-focusring {
outline: 1px dotted;
outline-offset: 1px;
}
#identity-popup-more-info-button {
margin-top: 6px;
margin-bottom: 0;

View File

@ -31,6 +31,9 @@ a11y.ini
xpcshell.ini
For *xpcshell* tests.
webapprt.ini
For the *chrome* flavor of webapp runtime mochitests.
.. _manifest_destiny_manifests:
Manifest Destiny Manifests

View File

@ -47,11 +47,6 @@ MOCHITEST_ROBOCOP_DEST := $(call mochitestdir,tests/robocop,flat_hierarchy)
INSTALL_TARGETS += MOCHITEST_ROBOCOP
endif
ifdef MOCHITEST_WEBAPPRT_CHROME_FILES
MOCHITEST_WEBAPPRT_CHROME_DEST := $(call mochitestdir,webapprtChrome)
INSTALL_TARGETS += MOCHITEST_WEBAPPRT_CHROME
endif
INCLUDED_TESTS_MOCHITEST_MK := 1
endif #} INCLUDED_TESTS_MOCHITEST_MK

View File

@ -52,6 +52,7 @@ _DEPRECATED_VARIABLES := \
XPIDL_FLAGS \
MOCHITEST_FILES_PARTS \
MOCHITEST_BROWSER_FILES_PARTS \
MOCHITEST_WEBAPPRT_CHROME_FILES \
$(NULL)
ifndef EXTERNALLY_MANAGED_MAKE_FILE
@ -1728,7 +1729,6 @@ FREEZE_VARIABLES = \
MOCHITEST_A11Y_FILES \
MOCHITEST_METRO_FILES \
MOCHITEST_ROBOCOP_FILES \
MOCHITEST_WEBAPPRT_CHROME_FILES \
$(NULL)
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))

View File

@ -134,9 +134,6 @@ DOMInterfaces = {
'nativeType': 'nsDOMBeforeUnloadEvent',
},
'AudioStreamTrack': {
},
'BarProp': {
'headerFile': 'mozilla/dom/BarProps.h',
},
@ -173,10 +170,6 @@ DOMInterfaces = {
'headerFile': 'BluetoothManager.h'
},
'CallEvent': {},
'CallsList': {},
'CameraControl': {
'nativeType': 'mozilla::nsDOMCameraControl',
'headerFile': 'DOMCameraControl.h',
@ -1191,12 +1184,6 @@ DOMInterfaces = {
'concrete': False,
},
'Telephony' : {},
'TelephonyCall' : {},
'TelephonyCallGroup' : {},
'Text': {
# Total hack to allow binding code to realize that nsTextNode can
# in fact be cast to Text.
@ -1834,7 +1821,6 @@ addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
notflattened=True)
addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
addExternalIface('MozTelephony', nativeType='nsIDOMTelephony')
addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject',
notflattened=True)
addExternalIface('MozTreeColumn', nativeType='nsITreeColumn',

View File

@ -1626,7 +1626,9 @@ BluetoothDBusService::StartInternal()
return NS_OK;
}
if (NS_FAILED(EstablishDBusConnection())) {
mConnection = new RawDBusConnection();
if (NS_FAILED(mConnection->EstablishDBusConnection())) {
BT_WARNING("Cannot start Main Thread DBus connection!");
StopDBus();
return NS_ERROR_FAILURE;
@ -1648,7 +1650,7 @@ BluetoothDBusService::StartInternal()
// signals we want, register all of them in this thread at startup.
// The event handler will sort the destinations out as needed.
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
dbus_bus_add_match(mConnection,
dbus_bus_add_match(mConnection->GetConnection(),
sBluetoothDBusSignals[i],
&err);
if (dbus_error_is_set(&err)) {
@ -1657,8 +1659,8 @@ BluetoothDBusService::StartInternal()
}
// Add a filter for all incoming messages_base
if (!dbus_connection_add_filter(mConnection, EventFilter,
NULL, NULL)) {
if (!dbus_connection_add_filter(mConnection->GetConnection(),
EventFilter, NULL, NULL)) {
BT_WARNING("Cannot create DBus Event Filter for DBus Thread!");
return NS_ERROR_FAILURE;
}
@ -1712,7 +1714,7 @@ BluetoothDBusService::StopInternal()
DBusError err;
dbus_error_init(&err);
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
dbus_bus_remove_match(mConnection,
dbus_bus_remove_match(mConnection->GetConnection(),
sBluetoothDBusSignals[i],
&err);
if (dbus_error_is_set(&err)) {
@ -1720,7 +1722,8 @@ BluetoothDBusService::StopInternal()
}
}
dbus_connection_remove_filter(mConnection, EventFilter, nullptr);
dbus_connection_remove_filter(mConnection->GetConnection(),
EventFilter, nullptr);
if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(),
KEY_LOCAL_AGENT)) {
@ -1885,10 +1888,11 @@ BluetoothDBusService::GetDefaultAdapterPathInternal(
nsRefPtr<DefaultAdapterPathReplyHandler> handler =
new DefaultAdapterPathReplyHandler(aRunnable);
bool success = SendWithReply(DefaultAdapterPathReplyHandler::Callback,
handler.get(), 1000,
"/", DBUS_MANAGER_IFACE, "DefaultAdapter",
DBUS_TYPE_INVALID);
bool success = mConnection->SendWithReply(
DefaultAdapterPathReplyHandler::Callback,
handler.get(), 1000,
"/", DBUS_MANAGER_IFACE, "DefaultAdapter",
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
@ -1928,11 +1932,12 @@ BluetoothDBusService::SendDiscoveryMessage(const char* aMessageName,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool success = SendWithReply(OnSendDiscoveryMessageReply,
static_cast<void*>(aRunnable), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, aMessageName,
DBUS_TYPE_INVALID);
bool success = mConnection->SendWithReply(
OnSendDiscoveryMessageReply,
static_cast<void*>(aRunnable), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, aMessageName,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
@ -1982,11 +1987,11 @@ BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
return NS_ERROR_FAILURE;
}
bool ret = SendWithReply(aCallback,
static_cast<void*>(serviceClass.forget()), -1,
NS_ConvertUTF16toUTF8(aObjectPath).get(),
aInterface, NS_ConvertUTF16toUTF8(aMessage).get(),
DBUS_TYPE_INVALID);
bool ret = mConnection->SendWithReply(
aCallback, static_cast<void*>(serviceClass.forget()), -1,
NS_ConvertUTF16toUTF8(aObjectPath).get(),
aInterface, NS_ConvertUTF16toUTF8(aMessage).get(),
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(ret, NS_ERROR_FAILURE);
@ -2294,7 +2299,10 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
// msg is unref'd as part of SendWithReply
if (!SendWithReply(GetVoidCallback, (void*)aRunnable, 1000, msg)) {
bool success = mConnection->SendWithReply(GetVoidCallback,
(void*)aRunnable,
1000, msg);
if (!success) {
BT_WARNING("SendWithReply failed");
return NS_ERROR_FAILURE;
}
@ -2341,14 +2349,15 @@ BluetoothDBusService::CreatePairedDeviceInternal(
// Then send CreatePairedDevice, it will register a temp device agent then
// unregister it after pairing process is over
bool ret = SendWithReply(GetObjectPathCallback, (void*)runnable, aTimeout,
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE,
"CreatePairedDevice",
DBUS_TYPE_STRING, &deviceAddress,
DBUS_TYPE_OBJECT_PATH, &deviceAgentPath,
DBUS_TYPE_STRING, &capabilities,
DBUS_TYPE_INVALID);
bool ret = mConnection->SendWithReply(
GetObjectPathCallback, (void*)runnable, aTimeout,
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE,
"CreatePairedDevice",
DBUS_TYPE_STRING, &deviceAddress,
DBUS_TYPE_OBJECT_PATH, &deviceAgentPath,
DBUS_TYPE_STRING, &capabilities,
DBUS_TYPE_INVALID);
if (!ret) {
BT_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
@ -2392,12 +2401,12 @@ BluetoothDBusService::RemoveDeviceInternal(const nsAString& aDeviceAddress,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool success = SendWithReply(OnRemoveDeviceReply,
static_cast<void*>(runnable.get()), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, "RemoveDevice",
DBUS_TYPE_OBJECT_PATH, &cstrDeviceObjectPath,
DBUS_TYPE_INVALID);
bool success = mConnection->SendWithReply(
OnRemoveDeviceReply, static_cast<void*>(runnable.get()), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, "RemoveDevice",
DBUS_TYPE_OBJECT_PATH, &cstrDeviceObjectPath,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
@ -2443,7 +2452,7 @@ BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
result = false;
} else {
result = Send(reply);
result = mConnection->Send(reply);
}
dbus_message_unref(msg);
@ -2489,7 +2498,7 @@ BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
result = false;
} else {
result = Send(reply);
result = mConnection->Send(reply);
}
dbus_message_unref(msg);
@ -2533,7 +2542,7 @@ BluetoothDBusService::SetPairingConfirmationInternal(
return false;
}
bool result = Send(reply);
bool result = mConnection->Send(reply);
if (!result) {
errorStr.AssignLiteral("Can't send message!");
}
@ -2746,13 +2755,13 @@ BluetoothDBusService::GetServiceChannel(const nsAString& aDeviceAddress,
nsRefPtr<OnGetServiceChannelReplyHandler> handler =
new OnGetServiceChannelReplyHandler(objectPath, aServiceUUID, aManager);
bool success = SendWithReply(OnGetServiceChannelReplyHandler::Callback,
handler, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
DBUS_TYPE_STRING, &cstrServiceUUID,
DBUS_TYPE_UINT16, &sProtocolDescriptorList,
DBUS_TYPE_INVALID);
bool success = mConnection->SendWithReply(
OnGetServiceChannelReplyHandler::Callback, handler, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
DBUS_TYPE_STRING, &cstrServiceUUID,
DBUS_TYPE_UINT16, &sProtocolDescriptorList,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
handler.forget();
@ -2799,13 +2808,13 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
OnUpdateSdpRecordsRunnable* callbackRunnable =
new OnUpdateSdpRecordsRunnable(objectPath, aManager);
return SendWithReply(DiscoverServicesCallback,
(void*)callbackRunnable, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE,
"DiscoverServices",
DBUS_TYPE_STRING, &EmptyCString(),
DBUS_TYPE_INVALID);
return mConnection->SendWithReply(DiscoverServicesCallback,
(void*)callbackRunnable, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE,
"DiscoverServices",
DBUS_TYPE_STRING, &EmptyCString(),
DBUS_TYPE_INVALID);
}
nsresult
@ -3014,16 +3023,17 @@ BluetoothDBusService::SendMetaData(const nsAString& aTitle,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool ret = SendWithReply(GetVoidCallback, (void*)runnable.get(), -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdateMetaData",
DBUS_TYPE_STRING, &title,
DBUS_TYPE_STRING, &artist,
DBUS_TYPE_STRING, &album,
DBUS_TYPE_STRING, &mediaNumber,
DBUS_TYPE_STRING, &totalMediaCount,
DBUS_TYPE_STRING, &duration,
DBUS_TYPE_INVALID);
bool ret = mConnection->SendWithReply(
GetVoidCallback, (void*)runnable.get(), -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdateMetaData",
DBUS_TYPE_STRING, &title,
DBUS_TYPE_STRING, &artist,
DBUS_TYPE_STRING, &album,
DBUS_TYPE_STRING, &mediaNumber,
DBUS_TYPE_STRING, &totalMediaCount,
DBUS_TYPE_STRING, &duration,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(ret);
runnable.forget();
@ -3111,13 +3121,14 @@ BluetoothDBusService::SendPlayStatus(int64_t aDuration,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool ret = SendWithReply(GetVoidCallback, (void*)runnable.get(), -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdatePlayStatus",
DBUS_TYPE_UINT32, &aDuration,
DBUS_TYPE_UINT32, &aPosition,
DBUS_TYPE_UINT32, &tempPlayStatus,
DBUS_TYPE_INVALID);
bool ret = mConnection->SendWithReply(
GetVoidCallback, (void*)runnable.get(), -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdatePlayStatus",
DBUS_TYPE_UINT32, &aDuration,
DBUS_TYPE_UINT32, &aPosition,
DBUS_TYPE_UINT32, &tempPlayStatus,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(ret);
runnable.forget();
@ -3158,13 +3169,14 @@ BluetoothDBusService::UpdatePlayStatus(uint32_t aDuration,
uint32_t tempPlayStatus = aPlayStatus;
bool ret = SendWithReply(ControlCallback, nullptr, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdatePlayStatus",
DBUS_TYPE_UINT32, &aDuration,
DBUS_TYPE_UINT32, &aPosition,
DBUS_TYPE_UINT32, &tempPlayStatus,
DBUS_TYPE_INVALID);
bool ret = mConnection->SendWithReply(
ControlCallback, nullptr, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdatePlayStatus",
DBUS_TYPE_UINT32, &aDuration,
DBUS_TYPE_UINT32, &aPosition,
DBUS_TYPE_UINT32, &tempPlayStatus,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(ret);
}
@ -3186,12 +3198,12 @@ BluetoothDBusService::UpdateNotification(ControlEventId aEventId,
GetObjectPathFromAddress(sAdapterPath, address);
uint16_t eventId = aEventId;
bool ret = SendWithReply(ControlCallback, nullptr, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE,
"UpdateNotification",
DBUS_TYPE_UINT16, &eventId,
DBUS_TYPE_UINT64, &aData,
DBUS_TYPE_INVALID);
bool ret = mConnection->SendWithReply(
ControlCallback, nullptr, -1,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdateNotification",
DBUS_TYPE_UINT16, &eventId,
DBUS_TYPE_UINT64, &aData,
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(ret);
}

View File

@ -22,7 +22,6 @@ BEGIN_BLUETOOTH_NAMESPACE
*/
class BluetoothDBusService : public BluetoothService
, private mozilla::ipc::RawDBusConnection
{
public:
bool IsReady();
@ -201,6 +200,8 @@ private:
const char* aInterface,
const nsAString& aMessage,
mozilla::ipc::DBusReplyCallback aCallback);
nsRefPtr<mozilla::ipc::RawDBusConnection> mConnection;
};
END_BLUETOOTH_NAMESPACE

View File

@ -576,6 +576,10 @@ NetworkManager.prototype = {
},
resetRoutingTable: function resetRoutingTable(network) {
if (!network.ip || !network.netmask) {
debug("Either ip or netmask is null. Cannot reset routing table.");
return;
}
let options = {
cmd: "removeNetworkRoute",
ifname: network.name,

View File

@ -605,9 +605,13 @@ public:
{
if (mSurface && !mPlatformContext) {
#ifdef MOZ_WIDGET_GONK
if (!mIsOffscreen)
return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), mSurface);
else
if (!mIsOffscreen) {
if (mHwc) {
return mHwc->Render(EGL_DISPLAY(), mSurface);
} else {
return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), mSurface);
}
} else
#endif
return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), mSurface);
} else {

View File

@ -43,7 +43,7 @@ SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
MOZ_ASSERT(allocator);
mAllocator = allocator;
mAllocator = allocator->asWeakPtr();
}
SharedSurface_Gralloc*
@ -132,7 +132,10 @@ SharedSurface_Gralloc::~SharedSurface_Gralloc()
mGL->fDeleteTextures(1, (GLuint*)&mProdTex);
SurfaceDescriptor desc(mDesc);
mAllocator->DestroySharedSurface(&desc);
if (mAllocator) {
mAllocator->DestroySharedSurface(&desc);
}
}
void

View File

@ -8,6 +8,7 @@
#include "SharedSurfaceGL.h"
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/layers/ISurfaceAllocator.h"
namespace mozilla {
namespace layers {
@ -92,7 +93,7 @@ class SurfaceFactory_Gralloc
: public SurfaceFactory_GL
{
protected:
layers::ISurfaceAllocator* mAllocator;
WeakPtr<layers::ISurfaceAllocator> mAllocator;
public:
SurfaceFactory_Gralloc(GLContext* prodGL,
@ -101,6 +102,9 @@ public:
virtual SharedSurface* CreateShared(const gfxIntSize& size) {
bool hasAlpha = mReadCaps.alpha;
if (!mAllocator) {
return nullptr;
}
return SharedSurface_Gralloc::Create(mGL, mFormats, size, hasAlpha, mAllocator);
}
};

View File

@ -11,6 +11,7 @@
#include "gfxTypes.h"
#include "gfxPoint.h" // for gfxIntSize
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/WeakPtr.h"
/*
* FIXME [bjacob] *** PURE CRAZYNESS WARNING ***
@ -68,7 +69,7 @@ bool ReleaseOwnedSurfaceDescriptor(const SurfaceDescriptor& aDescriptor);
* These methods should be only called in the ipdl implementor's thread, unless
* specified otherwise in the implementing class.
*/
class ISurfaceAllocator
class ISurfaceAllocator : public SupportsWeakPtr<ISurfaceAllocator>
{
public:
ISurfaceAllocator() {}

View File

@ -47,11 +47,6 @@ MOCHITEST_ROBOCOP_DEST := $(call mochitestdir,tests/robocop,flat_hierarchy)
INSTALL_TARGETS += MOCHITEST_ROBOCOP
endif
ifdef MOCHITEST_WEBAPPRT_CHROME_FILES
MOCHITEST_WEBAPPRT_CHROME_DEST := $(call mochitestdir,webapprtChrome)
INSTALL_TARGETS += MOCHITEST_WEBAPPRT_CHROME
endif
INCLUDED_TESTS_MOCHITEST_MK := 1
endif #} INCLUDED_TESTS_MOCHITEST_MK

View File

@ -52,6 +52,7 @@ _DEPRECATED_VARIABLES := \
XPIDL_FLAGS \
MOCHITEST_FILES_PARTS \
MOCHITEST_BROWSER_FILES_PARTS \
MOCHITEST_WEBAPPRT_CHROME_FILES \
$(NULL)
ifndef EXTERNALLY_MANAGED_MAKE_FILE
@ -1728,7 +1729,6 @@ FREEZE_VARIABLES = \
MOCHITEST_A11Y_FILES \
MOCHITEST_METRO_FILES \
MOCHITEST_ROBOCOP_FILES \
MOCHITEST_WEBAPPRT_CHROME_FILES \
$(NULL)
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))

View File

@ -1274,7 +1274,7 @@ abstract public class BrowserApp extends GeckoApp
}
final Tabs tabs = Tabs.getInstance();
final int tabId = tabs.getTabIdForUrl(url);
final int tabId = tabs.getTabIdForUrl(url, tabs.getSelectedTab().isPrivate());
if (tabId < 0) {
return false;
}

View File

@ -587,13 +587,19 @@ public class Tabs implements GeckoEventListener {
/**
* Looks for an open tab with the given URL.
* @param url the URL of the tab we're looking for
* @param isPrivate if true, only look for tabs that are private. if false,
* only look for tabs that are non-private.
*
* @return id of an open tab with the given URL; -1 if the tab doesn't exist.
*/
public int getTabIdForUrl(String url) {
public int getTabIdForUrl(String url, boolean isPrivate) {
for (Tab tab : mOrder) {
if (TextUtils.equals(tab.getURL(), url) ||
TextUtils.equals(ReaderModeUtils.getUrlFromAboutReader(tab.getURL()), url)) {
String tabUrl = tab.getURL();
if (ReaderModeUtils.isAboutReader(tabUrl)) {
tabUrl = ReaderModeUtils.getUrlFromAboutReader(tabUrl);
}
if (TextUtils.equals(tabUrl, url) && isPrivate == tab.isPrivate()) {
return tab.getId();
}
}

View File

@ -151,9 +151,12 @@ public class TwoLinePageRow extends LinearLayout
/**
* Replaces the page URL with "Switch to tab" if there is already a tab open with that URL.
* Only looks for tabs that are either private or non-private, depending on the current
* selected tab.
*/
private void updateDisplayedUrl() {
int tabId = Tabs.getInstance().getTabIdForUrl(mPageUrl);
boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
int tabId = Tabs.getInstance().getTabIdForUrl(mPageUrl, isPrivate);
if (!mShowIcons || tabId < 0) {
setUrl(mPageUrl);
setUrlIcon(NO_ICON);

View File

@ -82,8 +82,10 @@ BackgroundFileSaver::BackgroundFileSaver()
, mComplete(false)
, mStatus(NS_OK)
, mAppend(false)
, mAssignedTarget(nullptr)
, mAssignedTargetKeepPartial(false)
, mInitialTarget(nullptr)
, mInitialTargetKeepPartial(false)
, mRenamedTarget(nullptr)
, mRenamedTargetKeepPartial(false)
, mAsyncCopyContext(nullptr)
, mSha256Enabled(false)
, mActualTarget(nullptr)
@ -181,8 +183,13 @@ BackgroundFileSaver::SetTarget(nsIFile *aTarget, bool aKeepPartial)
NS_ENSURE_ARG(aTarget);
{
MutexAutoLock lock(mLock);
aTarget->Clone(getter_AddRefs(mAssignedTarget));
mAssignedTargetKeepPartial = aKeepPartial;
if (!mInitialTarget) {
aTarget->Clone(getter_AddRefs(mInitialTarget));
mInitialTargetKeepPartial = aKeepPartial;
} else {
aTarget->Clone(getter_AddRefs(mRenamedTarget));
mRenamedTargetKeepPartial = aKeepPartial;
}
}
// After the worker thread wakes up because attention is requested, it will
@ -373,15 +380,19 @@ BackgroundFileSaver::ProcessStateChange()
}
// Get a copy of the current shared state for the worker thread.
nsCOMPtr<nsIFile> target;
bool targetKeepPartial;
bool sha256Enabled = false;
bool append = false;
nsCOMPtr<nsIFile> initialTarget;
bool initialTargetKeepPartial;
nsCOMPtr<nsIFile> renamedTarget;
bool renamedTargetKeepPartial;
bool sha256Enabled;
bool append;
{
MutexAutoLock lock(mLock);
target = mAssignedTarget;
targetKeepPartial = mAssignedTargetKeepPartial;
initialTarget = mInitialTarget;
initialTargetKeepPartial = mInitialTargetKeepPartial;
renamedTarget = mRenamedTarget;
renamedTargetKeepPartial = mRenamedTargetKeepPartial;
sha256Enabled = mSha256Enabled;
append = mAppend;
@ -389,61 +400,70 @@ BackgroundFileSaver::ProcessStateChange()
mWorkerThreadAttentionRequested = false;
}
// The target can only be null if it has never been assigned. In this case,
// there is nothing to do since we never created any output file.
if (!target) {
// The initial target can only be null if it has never been assigned. In this
// case, there is nothing to do since we never created any output file.
if (!initialTarget) {
return NS_OK;
}
// Determine if we are processing the attention request for the first time.
bool isContinuation = !!mActualTarget;
// We will append to the initial target file only if it was requested by the
// caller, but we'll always append on subsequent accesses to the target file.
int32_t creationIoFlags;
if (isContinuation) {
creationIoFlags = PR_APPEND;
} else {
creationIoFlags = (append ? PR_APPEND : PR_TRUNCATE) | PR_CREATE_FILE;
if (!isContinuation) {
// Assign the target file for the first time.
mActualTarget = initialTarget;
mActualTargetKeepPartial = initialTargetKeepPartial;
}
// Verify whether we have actually been instructed to use a different file.
// This may happen the first time this function is executed, if SetTarget was
// called two times before the worker thread processed the attention request.
bool equalToCurrent = false;
if (isContinuation) {
rv = mActualTarget->Equals(target, &equalToCurrent);
if (renamedTarget) {
rv = mActualTarget->Equals(renamedTarget, &equalToCurrent);
NS_ENSURE_SUCCESS(rv, rv);
if (!equalToCurrent)
{
// We are moving the previous target file to a different location.
nsCOMPtr<nsIFile> targetParentDir;
rv = target->GetParent(getter_AddRefs(targetParentDir));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString targetName;
rv = target->GetLeafName(targetName);
NS_ENSURE_SUCCESS(rv, rv);
// We must delete any existing target file before moving the current one.
bool exists = false;
rv = target->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
// If we were asked to rename the file but the initial file did not exist,
// we simply create the file in the renamed location. We avoid this check
// if we have already started writing the output file ourselves.
bool exists = true;
if (!isContinuation) {
rv = mActualTarget->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
}
if (exists) {
rv = target->Remove(false);
// We are moving the previous target file to a different location.
nsCOMPtr<nsIFile> renamedTargetParentDir;
rv = renamedTarget->GetParent(getter_AddRefs(renamedTargetParentDir));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString renamedTargetName;
rv = renamedTarget->GetLeafName(renamedTargetName);
NS_ENSURE_SUCCESS(rv, rv);
// We must delete any existing target file before moving the current
// one.
rv = renamedTarget->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (exists) {
rv = renamedTarget->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
}
// Move the file. If this fails, we still reference the original file
// in mActualTarget, so that it is deleted if requested. If this
// succeeds, the nsIFile instance referenced by mActualTarget mutates
// and starts pointing to the new file, but we'll discard the reference.
rv = mActualTarget->MoveTo(renamedTargetParentDir, renamedTargetName);
NS_ENSURE_SUCCESS(rv, rv);
}
// Move the file. If this fails, we still reference the original file
// in mActualTarget, so that it is deleted if requested. If this
// succeeds, the nsIFile instance referenced by mActualTarget mutates and
// starts pointing to the new file, but we'll discard the reference.
rv = mActualTarget->MoveTo(targetParentDir, targetName);
NS_ENSURE_SUCCESS(rv, rv);
// Now we can update the actual target file name.
mActualTarget = renamedTarget;
mActualTargetKeepPartial = renamedTargetKeepPartial;
}
}
// Now we can update the actual target file name.
mActualTarget = target;
mActualTargetKeepPartial = targetKeepPartial;
// Notify if the target file name actually changed.
if (!equalToCurrent) {
// We must clone the nsIFile instance because mActualTarget is not
@ -528,6 +548,15 @@ BackgroundFileSaver::ProcessStateChange()
}
}
// We will append to the initial target file only if it was requested by the
// caller, but we'll always append on subsequent accesses to the target file.
int32_t creationIoFlags;
if (isContinuation) {
creationIoFlags = PR_APPEND;
} else {
creationIoFlags = (append ? PR_APPEND : PR_TRUNCATE) | PR_CREATE_FILE;
}
// Create the target file, or append to it if we already started writing it.
nsCOMPtr<nsIOutputStream> outputStream;
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream),
@ -602,16 +631,24 @@ BackgroundFileSaver::CheckCompletion()
if (NS_SUCCEEDED(mStatus)) {
failed = false;
// On success, if there is a pending rename operation, we must process it
// before finishing. Otherwise, we can finish now if requested.
if ((mAssignedTarget && mAssignedTarget != mActualTarget) ||
!mFinishRequested) {
// We did not incur in an error, so we must determine if we can stop now.
// If the Finish method has not been called, we can just continue now.
if (!mFinishRequested) {
return false;
}
// If completion was requested, but we still have data to write to the
// output file, allow the copy operation to resume. The Available getter
// may return an error if one of the pipe's streams has been already closed.
// We can only stop when all the operations requested by the control
// thread have been processed. First, we check whether we have processed
// the first SetTarget call, if any. Then, we check whether we have
// processed any rename requested by subsequent SetTarget calls.
if ((mInitialTarget && !mActualTarget) ||
(mRenamedTarget && mRenamedTarget != mActualTarget)) {
return false;
}
// If we still have data to write to the output file, allow the copy
// operation to resume. The Available getter may return an error if one
// of the pipe's streams has been already closed.
uint64_t available;
rv = mPipeInputStream->Available(&available);
if (NS_SUCCEEDED(rv) && available != 0) {

View File

@ -161,17 +161,37 @@ private:
bool mAppend;
/**
* Set by the control thread to the target file name that will be used by the
* worker thread, as soon as it is possible to update mActualTarget and open
* the file. This is null if no target was ever assigned to this object.
* This is set by the first SetTarget call on the control thread, and contains
* the target file name that will be used by the worker thread, as soon as it
* is possible to update mActualTarget and open the file. This is null if no
* target was ever assigned to this object.
*/
nsCOMPtr<nsIFile> mAssignedTarget;
nsCOMPtr<nsIFile> mInitialTarget;
/**
* Indicates whether mAssignedTarget should be kept as partially completed,
* This is set by the first SetTarget call on the control thread, and
* indicates whether mInitialTarget should be kept as partially completed,
* rather than deleted, if the operation fails or is canceled.
*/
bool mAssignedTargetKeepPartial;
bool mInitialTargetKeepPartial;
/**
* This is set by subsequent SetTarget calls on the control thread, and
* contains the new target file name to which the worker thread will move the
* target file, as soon as it can be done. This is null if SetTarget was
* called only once, or no target was ever assigned to this object.
*
* The target file can be renamed multiple times, though only the most recent
* rename is guaranteed to be processed by the worker thread.
*/
nsCOMPtr<nsIFile> mRenamedTarget;
/**
* This is set by subsequent SetTarget calls on the control thread, and
* indicates whether mRenamedTarget should be kept as partially completed,
* rather than deleted, if the operation fails or is canceled.
*/
bool mRenamedTargetKeepPartial;
/**
* While NS_AsyncCopy is in progress, allows canceling it. Null otherwise.

View File

@ -429,6 +429,29 @@ add_task(function test_setTarget_after_close_stream()
destFile.remove(false);
});
add_task(function test_setTarget_fast()
{
// This test checks a fast rename of the target file.
let destFile1 = getTempFile(TEST_FILE_NAME_1);
let destFile2 = getTempFile(TEST_FILE_NAME_2);
let saver = new BackgroundFileSaverOutputStream();
let completionPromise = promiseSaverComplete(saver);
// Set the initial name after the stream is closed, then rename immediately.
yield promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
saver.setTarget(destFile1, false);
saver.setTarget(destFile2, false);
// Wait for all the operations to complete.
saver.finish(Cr.NS_OK);
yield completionPromise;
// Verify results and clean up.
do_check_false(destFile1.exists());
yield promiseVerifyContents(destFile2, TEST_DATA_SHORT);
destFile2.remove(false);
});
add_task(function test_setTarget_multiple()
{
// This test checks multiple renames of the target file.
@ -482,6 +505,43 @@ add_task(function test_enableAppend()
destFile.remove(false);
});
add_task(function test_enableAppend_setTarget_fast()
{
// This test checks a fast rename of the target file in append mode.
let destFile1 = getTempFile(TEST_FILE_NAME_1);
let destFile2 = getTempFile(TEST_FILE_NAME_2);
// Test the case where the file does not already exists first, then the case
// where the file already exists.
for (let i = 0; i < 2; i++) {
let saver = new BackgroundFileSaverOutputStream();
saver.enableAppend();
let completionPromise = promiseSaverComplete(saver);
yield promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
// The first time, we start appending to the first file and rename to the
// second file. The second time, we start appending to the second file,
// that was created the first time, and rename back to the first file.
let firstFile = (i == 0) ? destFile1 : destFile2;
let secondFile = (i == 0) ? destFile2 : destFile1;
saver.setTarget(firstFile, false);
saver.setTarget(secondFile, false);
saver.finish(Cr.NS_OK);
yield completionPromise;
// Verify results.
do_check_false(firstFile.exists());
let expectedContents = (i == 0 ? TEST_DATA_SHORT
: TEST_DATA_SHORT + TEST_DATA_SHORT);
yield promiseVerifyContents(secondFile, expectedContents);
}
// Clean up.
destFile1.remove(false);
});
add_task(function test_enableAppend_hash()
{
// This test checks append mode, also verifying that the computed hash

View File

@ -231,6 +231,7 @@ class TreeMetadataEmitter(LoggingMixin):
METRO_CHROME=('metro-chrome', 'testing/mochitest/metro', True),
MOCHITEST=('mochitest', 'testing/mochitest/tests', True),
MOCHITEST_CHROME=('chrome', 'testing/mochitest/chrome', True),
MOCHITEST_WEBAPPRT_CHROME=('webapprt-chrome', 'testing/mochitest/webapprtChrome', True),
WEBRTC_SIGNALLING_TEST=('steeplechase', 'steeplechase', True),
XPCSHELL_TESTS=('xpcshell', 'xpcshell', False),
)

View File

@ -481,12 +481,16 @@ VARIABLES = {
"""List of manifest files defining metro browser chrome tests.
""", None),
'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
"""List of manifest files defining mochitest chrome tests.
""", None),
'MOCHITEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
"""List of manifest files defining mochitest tests.
""", None),
'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
"""List of manifest files defining mochitest chrome tests.
'MOCHITEST_WEBAPPRT_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
"""List of manifest files defining webapprt mochitest chrome tests.
""", None),
'WEBRTC_SIGNALLING_TEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],

View File

@ -107,8 +107,6 @@ public:
// Tell the appshell to exit
mService->mAppShell->Exit();
// We're done "shutting down".
mService->mShuttingDown = false;
mService->mRunning = false;
return NS_OK;
}

View File

@ -4114,9 +4114,9 @@
"extended_statistics_ok": true,
"description": "BACKGROUND THUMBNAILS: Time the capture took once it started and successfully completed (ms)"
},
"FX_THUMBNAILS_BG_CAPTURE_DONE_REASON": {
"FX_THUMBNAILS_BG_CAPTURE_DONE_REASON_2": {
"kind": "enumerated",
"n_values": 4,
"n_values": 10,
"description": "BACKGROUND THUMBNAILS: Reason the capture completed (see TEL_CAPTURE_DONE_* constants in BackgroundPageThumbs.jsm)"
},
"FX_THUMBNAILS_BG_CAPTURE_PAGE_LOAD_TIME_MS": {

View File

@ -19,10 +19,11 @@ const FRAME_SCRIPT_URL = "chrome://global/content/backgroundPageThumbsContent.js
const TELEMETRY_HISTOGRAM_ID_PREFIX = "FX_THUMBNAILS_BG_";
// possible FX_THUMBNAILS_BG_CAPTURE_DONE_REASON telemetry values
// possible FX_THUMBNAILS_BG_CAPTURE_DONE_REASON_2 telemetry values
const TEL_CAPTURE_DONE_OK = 0;
const TEL_CAPTURE_DONE_TIMEOUT = 1;
// 2 and 3 were used when we had special handling for private-browsing.
const TEL_CAPTURE_DONE_CRASHED = 4;
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const HTML_NS = "http://www.w3.org/1999/xhtml";
@ -201,7 +202,7 @@ const BackgroundPageThumbs = {
// "resetting" the capture requires more work - so for now, we just
// discard it.
if (curCapture && curCapture.pending) {
curCapture._done(null);
curCapture._done(null, TEL_CAPTURE_DONE_CRASHED);
// _done automatically continues queue processing.
}
// else: we must have been idle and not currently doing a capture (eg,
@ -331,31 +332,35 @@ Capture.prototype = {
delete this._msgMan;
}
delete this.captureCallback;
Services.ww.unregisterNotification(this);
delete this.doneCallbacks;
delete this.options;
},
// Called when the didCapture message is received.
receiveMessage: function (msg) {
tel("CAPTURE_DONE_REASON", TEL_CAPTURE_DONE_OK);
tel("CAPTURE_SERVICE_TIME_MS", new Date() - this.startDate);
// A different timed-out capture may have finally successfully completed, so
// discard messages that aren't meant for this capture.
if (msg.json.id == this.id)
this._done(msg.json);
this._done(msg.json, TEL_CAPTURE_DONE_OK);
},
// Called when the timeout timer fires.
notify: function () {
tel("CAPTURE_DONE_REASON", TEL_CAPTURE_DONE_TIMEOUT);
this._done(null);
this._done(null, TEL_CAPTURE_DONE_TIMEOUT);
},
_done: function (data) {
_done: function (data, reason) {
// Note that _done will be called only once, by either receiveMessage or
// notify, since it calls destroy, which cancels the timeout timer and
// notify, since it calls destroy here, which cancels the timeout timer and
// removes the didCapture message listener.
let { captureCallback, doneCallbacks, options } = this;
this.destroy();
if (typeof(reason) != "number")
throw new Error("A done reason must be given.");
tel("CAPTURE_DONE_REASON_2", reason);
if (data && data.telemetry) {
// Telemetry is currently disabled in the content process (bug 680508).
for (let id in data.telemetry) {
@ -364,11 +369,10 @@ Capture.prototype = {
}
let done = () => {
this.captureCallback(this);
this.destroy();
for (let callback of this.doneCallbacks) {
captureCallback(this);
for (let callback of doneCallbacks) {
try {
callback.call(this.options, this.url);
callback.call(options, this.url);
}
catch (err) {
Cu.reportError(err);

View File

@ -69,9 +69,11 @@
<li><a href="about:license#bspatch">bspatch License</a></li>
<li><a href="about:license#cairo">Cairo Component Licenses</a></li>
<li><a href="about:license#chromium">Chromium License</a></li>
<li><a href="about:license#codemirror">CodeMirror License</a></li>
<li><a href="about:license#dtoa">dtoa License</a></li>
<li><a href="about:license#hunspell-nl">Dutch Spellchecking Dictionary License</a></li>
<li><a href="about:license#edl">Eclipse Distribution License</a></li>
<li><a href="about:license#escodegen">Escodegen License</a></li>
<li><a href="about:license#hunspell-ee">Estonian Spellchecking Dictionary License</a></li>
<li><a href="about:license#expat">Expat License</a></li>
<li><a href="about:license#firebug">Firebug License</a></li>
@ -125,8 +127,6 @@
<li><a href="about:license#vtune">VTune License</a></li>
<li><a href="about:license#webrtc">WebRTC License</a></li>
<li><a href="about:license#xiph">Xiph.org Foundation License</a></li>
<li><a href="about:license#codemirror">CodeMirror License</a></li>
<li><a href="about:license#escodegen">Escodegen License</a></li>
</ul>
<br>
@ -1674,6 +1674,49 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="codemirror"></a>CodeMirror License</h1>
<p>This license applies to all files in
<span class="path">browser/devtools/sourceeditor/codemirror</span> and
to specified files in the <span class="path">browser/devtools/sourceeditor/test/</span>:
</p>
<ul>
<li><span class="path">cm_comment_test.js</span></li>
<li><span class="path">cm_driver.js</span></li>
<li><span class="path">cm_mode_javascript_test.js</span></li>
<li><span class="path">cm_mode_test.css</span></li>
<li><span class="path">cm_mode_test.js</span></li>
<li><span class="path">cm_test.js</span></li>
</ul>
<pre>
Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Please note that some subdirectories of the CodeMirror distribution
include their own LICENSE files, and are released under different
licences.
</pre>
<hr>
<h1><a id="dtoa"></a>dtoa License</h1>
@ -1780,6 +1823,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="escodegen"></a>Escodegen License</h1>
<p>This license applies to all files in
<span class="path">toolkit/devtools/escodegen</span>.
</p>
<pre>
Copyright (C) 2012 Yusuke Suzuki (twitter: @Constellation) and other contributors.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
</pre>
<hr>
@ -4058,81 +4133,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="codemirror"></a>CodeMirror License</h1>
<p>This license applies to all files in
<span class="path">browser/devtools/sourceeditor/codemirror</span> and
to specified files in the <span class="path">browser/devtools/sourceeditor/test/</span>:
</p>
<ul>
<li><span class="path">cm_comment_test.js</span></li>
<li><span class="path">cm_driver.js</span></li>
<li><span class="path">cm_mode_javascript_test.js</span></li>
<li><span class="path">cm_mode_test.css</span></li>
<li><span class="path">cm_mode_test.js</span></li>
<li><span class="path">cm_test.js</span></li>
</ul>
<pre>
Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Please note that some subdirectories of the CodeMirror distribution
include their own LICENSE files, and are released under different
licences.
</pre>
<hr>
<h1><a id="escodegen"></a>Escodegen License</h1>
<p>This license applies to all files in
<span class="path">toolkit/devtools/escodegen</span>.
</p>
<pre>
Copyright (C) 2012 Yusuke Suzuki (twitter: @Constellation) and other contributors.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
</pre>
<hr>

View File

@ -564,6 +564,14 @@ var StyleSheetActor = protocol.ActorClass({
return this.actorID;
}
let href;
if (this.rawSheet.ownerNode) {
if (this.rawSheet.ownerNode instanceof Ci.nsIDOMHTMLDocument)
href = this.rawSheet.ownerNode.location.href;
if (this.rawSheet.ownerNode.ownerDocument)
href = this.rawSheet.ownerNode.ownerDocument.location.href;
}
return {
actor: this.actorID,
@ -572,7 +580,7 @@ var StyleSheetActor = protocol.ActorClass({
// nodeHref stores the URI of the document that
// included the sheet.
nodeHref: this.rawSheet.ownerNode ? this.rawSheet.ownerNode.ownerDocument.location.href : undefined,
nodeHref: href,
system: !CssLogic.isContentStylesheet(this.rawSheet),
disabled: this.rawSheet.disabled ? true : undefined
@ -720,7 +728,11 @@ var StyleRuleActor = protocol.ActorClass({
if (this.rawNode) {
document = this.rawNode.ownerDocument;
} else {
document = this.rawRule.parentStyleSheet.ownerNode.ownerDocument;
if (this.rawRule.parentStyleSheet.ownerNode instanceof Ci.nsIDOMHTMLDocument) {
document = this.rawRule.parentStyleSheet.ownerNode;
} else {
document = this.rawRule.parentStyleSheet.ownerNode.ownerDocument;
}
}
let tempElement = document.createElement("div");

View File

@ -27,5 +27,6 @@ support-files =
[test_styles-computed.html]
[test_styles-matched.html]
[test_styles-modify.html]
[test_styles-svg.html]
[test_unsafeDereference.html]
[test_evalInGlobal-outerized_this.html]
[test_evalInGlobal-outerized_this.html]

View File

@ -16,6 +16,9 @@
background-color: #f06;
}
}
#svgcontent rect {
fill: rgb(1,2,3);
}
</style>
<link type="text/css" rel="stylesheet" href="inspector-styles-data.css"></link>
<body>
@ -51,5 +54,9 @@
Screen mediaqueried.
</div>
<div id="svgcontent">
<svg><rect></rect></svg>
</div>
</body>
</html>

View File

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=921191
Bug 921191 - allow inspection/editing of SVG elements' CSS properties
-->
<head>
<meta charset="utf-8">
<title>Test for Bug </title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
<script type="application/javascript;version=1.8">
Components.utils.import("resource://gre/modules/devtools/Loader.jsm");
const promise = devtools.require("sdk/core/promise");
const inspector = devtools.require("devtools/server/actors/inspector");
window.onload = function() {
SimpleTest.waitForExplicitFinish();
runNextTest();
}
var gWalker = null;
var gStyles = null;
var gClient = null;
addTest(function setup() {
let url = document.getElementById("inspectorContent").href;
attachURL(url, function(err, client, tab, doc) {
gInspectee = doc;
let {InspectorFront} = devtools.require("devtools/server/actors/inspector");
let inspector = InspectorFront(client, tab);
promiseDone(inspector.getWalker().then(walker => {
ok(walker, "getWalker() should return an actor.");
gClient = client;
gWalker = walker;
return inspector.getPageStyle();
}).then(styles => {
gStyles = styles;
}).then(runNextTest));
});
});
addTest(function inheritedUserStyles() {
let node = node;
promiseDone(gWalker.querySelector(gWalker.rootNode, "#svgcontent rect").then(node => {
return gStyles.getApplied(node, { inherited: true, filter: "user" });
}).then(applied => {
is(applied.length, 3, "Should have 3 rules");
is(applied[1].rule.cssText, "fill: rgb(1, 2, 3);", "cssText is right");
}).then(runNextTest));
});
addTest(function cleanup() {
delete gStyles;
delete gWalker;
delete gClient;
runNextTest();
});
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=921191">Mozilla Bug 921191</a>
<a id="inspectorContent" target="_blank" href="inspector-styles-data.html">Test Document</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -62,7 +62,7 @@ ContentPermission.prototype = {
}
// Display a prompt at the top level
let {name} = WebappRT.config.app.manifest;
let {name} = WebappRT.localeManifest;
let requestingWindow = request.window.top;
let chromeWin = this._getChromeWindow(requestingWindow);
let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");

View File

@ -20,11 +20,14 @@ Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
Cu.import('resource://gre/modules/Payment.jsm');
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
// Initialize window-independent handling of webapps- notifications.
Cu.import("resource://webapprt/modules/WebappsHandler.jsm");
Cu.import("resource://webapprt/modules/WebappRT.jsm");
const PROFILE_DIR = OS.Constants.Path.profileDir;
function isFirstRunOrUpdate() {
let savedBuildID = null;
try {
@ -41,6 +44,38 @@ function isFirstRunOrUpdate() {
return false;
}
function writeFile(aPath, aData) {
return Task.spawn(function() {
let data = TextEncoder().encode(aData);
yield OS.File.writeAtomic(aPath, data, { tmpPath: aPath + ".tmp" });
});
}
function createBrandingFiles() {
return Task.spawn(function() {
let manifest = WebappRT.localeManifest;
let name = WebappRT.localeManifest.name;
let developer = " ";
if (WebappRT.localeManifest.developer) {
developer = WebappRT.localeManifest.developer.name;
}
let brandDTDContent = '<!ENTITY brandShortName "' + name + '">\n\
<!ENTITY brandFullName "' + name + '">\n\
<!ENTITY vendorShortName "' + developer + '">\n\
<!ENTITY trademarkInfo.part1 " ">';
yield writeFile(OS.Path.join(PROFILE_DIR, "brand.dtd"), brandDTDContent);
let brandPropertiesContent = 'brandShortName=' + name + '\n\
brandFullName=' + name + '\n\
vendorShortName=' + developer;
yield writeFile(OS.Path.join(PROFILE_DIR, "brand.properties"),
brandPropertiesContent);
});
}
// Observes all the events needed to actually launch an application.
// It waits for XUL window and webapps registry loading.
this.startup = function(window) {
@ -79,9 +114,21 @@ this.startup = function(window) {
// TODO: Update the permissions when the application is updated.
if (isFirstRunOrUpdate(Services.prefs)) {
PermissionsInstaller.installPermissions(WebappRT.config.app, true);
yield createBrandingFiles();
}
}
// Branding substitution
let aliasFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Ci.nsIFile);
aliasFile.initWithPath(PROFILE_DIR);
let aliasURI = Services.io.newFileURI(aliasFile);
Services.io.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler)
.setSubstitution("webappbranding", aliasURI);
// Wait for XUL window loading
yield deferredWindowLoad.promise;

View File

@ -46,8 +46,12 @@ this.WebappRT = {
},
get launchURI() {
let manifest = new ManifestHelper(this.config.app.manifest,
this.config.app.origin);
let manifest = this.localeManifest;
return manifest.fullLaunchPath();
}
},
get localeManifest() {
return new ManifestHelper(this.config.app.manifest,
this.config.app.origin);
},
};

View File

@ -7,3 +7,5 @@
% locale webapprt @AB_CD@ %locale/webapprt/
locale/webapprt/webapp.dtd (%webapprt/webapp.dtd)
locale/webapprt/webapp.properties (%webapprt/webapp.properties)
% locale branding @AB_CD@ resource://webappbranding/

View File

@ -12,7 +12,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
DIRS += ['gtk2']
DIRS += ['locales']
TEST_DIRS += ['test']
EXTRA_COMPONENTS += [
'CommandLineHandler.js',
@ -28,3 +27,7 @@ EXTRA_JS_MODULES += [
'WebappRT.jsm',
'WebappsHandler.jsm',
]
MOCHITEST_WEBAPPRT_CHROME_MANIFESTS += ['test/chrome/webapprt.ini']
MOCHITEST_MANIFESTS += ['test/content/mochitest.ini']

View File

@ -1,40 +0,0 @@
# 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/.
MOCHITEST_WEBAPPRT_CHROME_FILES = \
head.js \
browser_sample.js \
sample.webapp \
sample.webapp^headers^ \
sample.html \
browser_window-title.js \
window-title.webapp \
window-title.webapp^headers^ \
window-title.html \
browser_webperm.js \
webperm.webapp \
webperm.webapp^headers^ \
webperm.html \
browser_noperm.js \
noperm.webapp \
noperm.webapp^headers^ \
noperm.html \
browser_geolocation-prompt-perm.js \
browser_geolocation-prompt-noperm.js \
geolocation-prompt-perm.webapp \
geolocation-prompt-perm.webapp^headers^ \
geolocation-prompt-noperm.webapp \
geolocation-prompt-noperm.webapp^headers^ \
geolocation-prompt-perm.html \
geolocation-prompt-noperm.html \
browser_debugger.js \
debugger.webapp \
debugger.webapp^headers^ \
debugger.html \
browser_mozpay.js \
mozpay.webapp \
mozpay.webapp^headers^ \
mozpay.html \
mozpay-success.html \
$(NULL)

View File

@ -1,6 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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

@ -0,0 +1,38 @@
[DEFAULT]
support-files =
head.js
sample.webapp
sample.webapp^headers^
sample.html
window-title.webapp
window-title.webapp^headers^
window-title.html
webperm.webapp
webperm.webapp^headers^
webperm.html
noperm.webapp
noperm.webapp^headers^
noperm.html
geolocation-prompt-perm.webapp
geolocation-prompt-perm.webapp^headers^
geolocation-prompt-noperm.webapp
geolocation-prompt-noperm.webapp^headers^
geolocation-prompt-perm.html
geolocation-prompt-noperm.html
debugger.webapp
debugger.webapp^headers^
debugger.html
mozpay.webapp
mozpay.webapp^headers^
mozpay.html
mozpay-success.html
[browser_sample.js]
[browser_window-title.js]
[browser_webperm.js]
[browser_noperm.js]
[browser_geolocation-prompt-perm.js]
[browser_geolocation-prompt-noperm.js]
[browser_debugger.js]
[browser_mozpay.js]

View File

@ -1,10 +0,0 @@
# 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/.
MOCHITEST_FILES = \
test.webapp \
test.webapp^headers^ \
webapprt_sample.html \
webapprt_indexeddb.html \
$(NULL)

View File

@ -0,0 +1,7 @@
[DEFAULT]
support-files =
test.webapp
test.webapp^headers^
[webapprt_sample.html]
[webapprt_indexeddb.html]

View File

@ -1,6 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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,7 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DIRS += ['chrome', 'content']

View File

@ -445,45 +445,114 @@ HwcComposer2D::TryHwComposition()
{
FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface());
if (!(fbsurface && fbsurface->lastHandle)) {
LOGD("H/W Composition failed. FBSurface not initialized.");
return false;
}
// Add FB layer
int idx = mList->numHwLayers++;
if (idx >= mMaxLayerCount) {
if (!ReallocLayerList() || idx >= mMaxLayerCount) {
LOGE("TryHwComposition failed! Could not add FB layer");
return false;
}
}
Prepare(fbsurface->lastHandle, -1);
for (int j = 0; j < idx; j++) {
if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER) {
LOGD("GPU or Partial HWC Composition");
return false;
}
}
// Full HWC Composition
Commit();
// No composition on FB layer, so closing releaseFenceFd
close(mList->hwLayers[idx].releaseFenceFd);
mList->hwLayers[idx].releaseFenceFd = -1;
mList->numHwLayers = 0;
return true;
}
bool
HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
{
if (!mList) {
// After boot, HWC list hasn't been created yet
return GetGonkDisplay()->SwapBuffers(dpy, sur);
}
GetGonkDisplay()->UpdateFBSurface(dpy, sur);
FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface());
if (!fbsurface) {
LOGE("H/W Composition failed. FBSurface not initialized.");
return false;
}
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = {NULL};
if (mList->numHwLayers != 0) {
// No mHwc prepare, if already prepared in current draw cycle
mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle;
mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->lastFenceFD;
} else {
mList->numHwLayers = 2;
mList->hwLayers[0].hints = 0;
mList->hwLayers[0].compositionType = HWC_BACKGROUND;
mList->hwLayers[0].flags = HWC_SKIP_LAYER;
mList->hwLayers[0].backgroundColor = {0};
mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height};
Prepare(fbsurface->lastHandle, fbsurface->lastFenceFD);
}
// GPU or partial HWC Composition
Commit();
GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
mList->numHwLayers = 0;
return true;
}
void
HwcComposer2D::Prepare(buffer_handle_t fbHandle, int fence)
{
int idx = mList->numHwLayers - 1;
const hwc_rect_t r = {0, 0, mScreenRect.width, mScreenRect.height};
int idx = mList->numHwLayers;
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
displays[HWC_DISPLAY_PRIMARY] = mList;
mList->flags = HWC_GEOMETRY_CHANGED;
mList->outbufAcquireFenceFd = -1;
mList->outbuf = nullptr;
mList->retireFenceFd = -1;
mList->hwLayers[idx].hints = 0;
mList->hwLayers[idx].flags = 0;
mList->hwLayers[idx].transform = 0;
mList->hwLayers[idx].handle = fbsurface->lastHandle;
mList->hwLayers[idx].handle = fbHandle;
mList->hwLayers[idx].blending = HWC_BLENDING_PREMULT;
mList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET;
mList->hwLayers[idx].sourceCrop = r;
mList->hwLayers[idx].displayFrame = r;
mList->hwLayers[idx].visibleRegionScreen.numRects = 1;
mList->hwLayers[idx].visibleRegionScreen.rects = &mList->hwLayers[idx].sourceCrop;
mList->hwLayers[idx].acquireFenceFd = -1;
mList->hwLayers[idx].acquireFenceFd = fence;
mList->hwLayers[idx].releaseFenceFd = -1;
mList->hwLayers[idx].planeAlpha = 0xFF;
mList->numHwLayers++;
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
}
for (int j = 0; j < idx; j++) {
if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER) {
LOGD("GPU or Partial MDP Composition");
return false;
}
}
bool
HwcComposer2D::Commit()
{
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
displays[HWC_DISPLAY_PRIMARY] = mList;
// Full MDP Composition
mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
for (int i = 0; i <= MAX_HWC_LAYERS; i++) {
if (mPrevRelFd[i] <= 0) {
@ -504,18 +573,15 @@ HwcComposer2D::TryHwComposition()
}
mPrevRelFd[0] = mList->retireFenceFd;
for (uint32_t j = 0; j < idx; j++) {
for (uint32_t j = 0; j < (mList->numHwLayers - 1); j++) {
if (mList->hwLayers[j].compositionType == HWC_OVERLAY) {
mPrevRelFd[j + 1] = mList->hwLayers[j].releaseFenceFd;
mList->hwLayers[j].releaseFenceFd = -1;
}
}
close(mList->hwLayers[idx].releaseFenceFd);
mList->hwLayers[idx].releaseFenceFd = -1;
mList->retireFenceFd = -1;
mList->numHwLayers = 0;
return true;
return !err;
}
#else
bool
@ -523,6 +589,12 @@ HwcComposer2D::TryHwComposition()
{
return !mHwc->set(mHwc, mDpy, mSur, mList);
}
bool
HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
{
return GetGonkDisplay()->SwapBuffers(dpy, sur);
}
#endif
bool
@ -549,13 +621,15 @@ HwcComposer2D::TryRender(Layer* aRoot,
aGLWorldTransform))
{
LOGD("Render aborted. Nothing was drawn to the screen");
if (mList) {
mList->numHwLayers = 0;
}
return false;
}
if (!TryHwComposition()) {
// Full MDP Composition
LOGE("H/W Composition failed");
return false;
LOGD("H/W Composition failed");
return false;
}
LOGD("Frame rendered");

View File

@ -62,7 +62,11 @@ public:
// by this composer so nothing was rendered at all
bool TryRender(layers::Layer* aRoot, const gfxMatrix& aGLWorldTransform) MOZ_OVERRIDE;
bool Render(EGLDisplay dpy, EGLSurface sur);
private:
void Prepare(buffer_handle_t fbHandle, int fence);
bool Commit();
bool TryHwComposition();
bool ReallocLayerList();
bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,

View File

@ -43,6 +43,10 @@ public:
virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur) = 0;
virtual void SetFBReleaseFd(int fd) = 0;
float xdpi;
uint32_t surfaceformat;
};

View File

@ -196,6 +196,17 @@ GonkDisplayICS::QueueBuffer(ANativeWindowBuffer *buf)
return !window->queueBuffer(window, buf);
}
void
GonkDisplayICS::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur)
{
eglSwapBuffers(dpy, sur);
}
void
GonkDisplayICS::SetFBReleaseFd(int fd)
{
}
__attribute__ ((visibility ("default")))
GonkDisplay*
GetGonkDisplay()

View File

@ -46,6 +46,10 @@ public:
virtual bool QueueBuffer(ANativeWindowBuffer* handle);
virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur);
virtual void SetFBReleaseFd(int fd);
private:
hw_module_t const* mModule;
hwc_composer_device_t* mHwc;

View File

@ -272,6 +272,20 @@ GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf)
return success;
}
void
GonkDisplayJB::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur)
{
StopBootAnimation();
mBootAnimBuffer = nullptr;
eglSwapBuffers(dpy, sur);
}
void
GonkDisplayJB::SetFBReleaseFd(int fd)
{
mFBSurface->setReleaseFenceFd(fd);
}
__attribute__ ((visibility ("default")))
GonkDisplay*
GetGonkDisplay()

View File

@ -45,6 +45,10 @@ public:
virtual bool QueueBuffer(ANativeWindowBuffer* buf);
virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur);
virtual void SetFBReleaseFd(int fd);
bool Post(buffer_handle_t buf, int fence);
private: