Merge m-c to m-i.

This commit is contained in:
Ms2ger 2012-07-25 16:51:37 +02:00
commit 52fc40391f
266 changed files with 5405 additions and 2026 deletions

View File

@ -258,7 +258,7 @@ DocAccessibleWrap::DoInitialUpdate()
a11y::RootAccessible* rootDocument = RootAccessible();
mozilla::WindowsHandle nativeData = nsnull;
mozilla::WindowsHandle nativeData = NULL;
if (tabChild)
tabChild->SendGetWidgetNativeData(&nativeData);
else

View File

@ -122,11 +122,14 @@ var shell = {
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
.createInstance(Ci.nsISHistory);
['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) {
window.addEventListener(type, this, false, true);
window.addEventListener(type, this, true, true);
}).bind(this));
// Capture all key events so we can filter out hardware buttons
// And send them to Gaia via mozChromeEvents.
// Ideally, hardware buttons wouldn't generate key events at all, or
// if they did, they would use keycodes that conform to DOM 3 Events.
// See discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=762362
window.addEventListener('keydown', this, true);
window.addEventListener('keypress', this, true);
window.addEventListener('keyup', this, true);
window.addEventListener('MozApplicationManifest', this);
window.addEventListener('mozfullscreenchange', this);
window.addEventListener('sizemodechange', this);
@ -165,11 +168,9 @@ var shell = {
},
stop: function shell_stop() {
['keydown', 'keypress', 'keyup'].forEach((function unlistenKey(type) {
window.removeEventListener(type, this, false, true);
window.removeEventListener(type, this, true, true);
}).bind(this));
window.removeEventListener('keydown', this, true);
window.removeEventListener('keypress', this, true);
window.removeEventListener('keyup', this, true);
window.removeEventListener('MozApplicationManifest', this);
window.removeEventListener('mozfullscreenchange', this);
window.removeEventListener('sizemodechange', this);
@ -180,15 +181,66 @@ var shell = {
#endif
},
forwardKeyToContent: function shell_forwardKeyToContent(evt) {
let content = shell.contentBrowser.contentWindow;
let generatedEvent = content.document.createEvent('KeyboardEvent');
generatedEvent.initKeyEvent(evt.type, true, true, evt.view, evt.ctrlKey,
evt.altKey, evt.shiftKey, evt.metaKey,
evt.keyCode, evt.charCode);
// If this key event actually represents a hardware button, filter it here
// and send a mozChromeEvent with detail.type set to xxx-button-press or
// xxx-button-release instead.
filterHardwareKeys: function shell_filterHardwareKeys(evt) {
var type;
switch (evt.keyCode) {
case evt.DOM_VK_HOME: // Home button
type = 'home-button';
break;
case evt.DOM_VK_SLEEP: // Sleep button
type = 'sleep-button';
break;
case evt.DOM_VK_PAGE_UP: // Volume up button
type = 'volume-up-button';
break;
case evt.DOM_VK_PAGE_DOWN: // Volume down button
type = 'volume-down-button';
break;
case evt.DOM_VK_ESCAPE: // Back button (should be disabled)
type = 'back-button';
break;
case evt.DOM_VK_CONTEXT_MENU: // Menu button
type = 'menu-button';
break;
default: // Anything else is a real key
return; // Don't filter it at all; let it propagate to Gaia
}
content.document.documentElement.dispatchEvent(generatedEvent);
// If we didn't return, then the key event represents a hardware key
// and we need to prevent it from propagating to Gaia
evt.stopImmediatePropagation();
evt.preventDefault(); // Prevent keypress events (when #501496 is fixed).
// If it is a key down or key up event, we send a chrome event to Gaia.
// If it is a keypress event we just ignore it.
switch (evt.type) {
case 'keydown':
type = type + '-press';
break;
case 'keyup':
type = type + '-release';
break;
case 'keypress':
return;
}
// On my device, the physical hardware buttons (sleep and volume)
// send multiple events (press press release release), but the
// soft home button just sends one. This hack is to manually
// "debounce" the keys. If the type of this event is the same as
// the type of the last one, then don't send it. We'll never send
// two presses or two releases in a row.
// FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=761067
if (type !== this.lastHardwareButtonEventType) {
this.lastHardwareButtonEventType = type;
this.sendChromeEvent({type: type});
}
},
lastHardwareButtonEventType: null, // property for the hack above
handleEvent: function shell_handleEvent(evt) {
let content = this.contentBrowser.contentWindow;
@ -196,17 +248,8 @@ var shell = {
case 'keydown':
case 'keyup':
case 'keypress':
// Redirect the HOME key to System app and stop the applications from
// handling it.
let rootContentEvt = (evt.target.ownerDocument.defaultView == content);
if (!rootContentEvt && evt.eventPhase == evt.CAPTURING_PHASE &&
evt.keyCode == evt.DOM_VK_HOME) {
this.forwardKeyToContent(evt);
evt.preventDefault();
evt.stopImmediatePropagation();
}
this.filterHardwareKeys(evt);
break;
case 'mozfullscreenchange':
// When the screen goes fullscreen make sure to set the focus to the
// main window so noboby can prevent the ESC key to get out fullscreen
@ -272,6 +315,9 @@ var shell = {
let event = content.document.createEvent('CustomEvent');
event.initCustomEvent(type, true, true, details ? details : {});
content.dispatchEvent(event);
},
sendChromeEvent: function shell_sendChromeEvent(details) {
this.sendEvent(getContentWindow(), "mozChromeEvent", details);
}
};
@ -310,7 +356,7 @@ nsBrowserAccess.prototype = {
Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
let msg = JSON.parse(data);
let origin = Services.io.newURI(msg.manifest, null, null).prePath;
shell.sendEvent(shell.contentBrowser.contentWindow, 'mozChromeEvent', {
shell.sendChromeEvent({
type: 'open-app',
url: msg.uri,
origin: origin,
@ -415,12 +461,22 @@ var AlertsHelper = {
return id;
},
showAlertNotification: function alert_showAlertNotification(imageUrl, title, text, textClickable,
cookie, alertListener, name) {
showAlertNotification: function alert_showAlertNotification(imageUrl,
title,
text,
textClickable,
cookie,
alertListener,
name)
{
let id = this.registerListener(cookie, alertListener);
let content = shell.contentBrowser.contentWindow;
shell.sendEvent(content, "mozChromeEvent", { type: "desktop-notification", id: id, icon: imageUrl,
title: title, text: text } );
shell.sendChromeEvent({
type: "desktop-notification",
id: id,
icon: imageUrl,
title: title,
text: text
});
}
}
@ -456,7 +512,6 @@ var WebappsHelper = {
},
observe: function webapps_observe(subject, topic, data) {
let content = shell.contentBrowser.contentWindow;
let json = JSON.parse(data);
switch(topic) {
case "webapps-launch":
@ -465,7 +520,7 @@ var WebappsHelper = {
return;
let manifest = new DOMApplicationManifest(aManifest, json.origin);
shell.sendEvent(content, "mozChromeEvent", {
shell.sendChromeEvent({
"type": "webapps-launch",
"url": manifest.fullLaunchPath(json.startPoint),
"origin": json.origin
@ -474,7 +529,11 @@ var WebappsHelper = {
break;
case "webapps-ask-install":
let id = this.registerInstaller(json);
shell.sendEvent(content, "mozChromeEvent", { type: "webapps-ask-install", id: id, app: json.app } );
shell.sendChromeEvent({
type: "webapps-ask-install",
id: id,
app: json.app
});
break;
}
}
@ -529,16 +588,28 @@ window.addEventListener('ContentStart', function ss_onContentStart() {
context.drawWindow(window, 0, 0, width, height,
'rgb(255,255,255)', flags);
shell.sendEvent(content, 'mozChromeEvent', {
type: 'take-screenshot-success',
file: canvas.mozGetAsFile('screenshot', 'image/png')
shell.sendChromeEvent({
type: 'take-screenshot-success',
file: canvas.mozGetAsFile('screenshot', 'image/png')
});
} catch (e) {
dump('exception while creating screenshot: ' + e + '\n');
shell.sendEvent(content, 'mozChromeEvent', {
shell.sendChromeEvent({
type: 'take-screenshot-error',
error: String(e)
});
}
});
});
Services.obs.addObserver(function ContentHandler(subject, topic, data) {
let handler = JSON.parse(data);
new MozActivity({
name: 'view',
data: {
type: handler.type,
url: handler.url
}
});
}, 'content-handler', false);

View File

@ -38,3 +38,8 @@ contract @mozilla.org/dom/activities/ui-glue;1 {70a83123-7467-4389-a309-3e81c74a
component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
# ContentHandler.js
component {d18d0216-d50c-11e1-ba54-efb18d0ef0ac} ContentHandler.js
contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {d18d0216-d50c-11e1-ba54-efb18d0ef0ac}

View File

@ -0,0 +1,48 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const PDF_CONTENT_TYPE = "application/pdf";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function log(aMsg) {
let msg = "ContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
.logStringMessage(msg);
dump(msg + "\n");
}
const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
function ContentHandler() {
}
ContentHandler.prototype = {
handleContent: function handleContent(aMimetype, aContext, aRequest) {
if (aMimetype != PDF_CONTENT_TYPE)
throw NS_ERROR_WONT_HANDLE_CONTENT;
if (!(aRequest instanceof Ci.nsIChannel))
throw NS_ERROR_WONT_HANDLE_CONTENT;
let detail = {
"type": aMimetype,
"url": aRequest.URI.spec
};
Services.obs.notifyObservers(this, "content-handler", JSON.stringify(detail));
aRequest.cancel(Cr.NS_BINDING_ABORTED);
},
classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler])
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentHandler]);

View File

@ -22,7 +22,7 @@ DirectoryProvider.prototype = {
getFile: function dp_getFile(prop, persistent) {
#ifdef MOZ_WIDGET_GONK
let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir"];
let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir", "permissionDBPDir"];
if (localProps.indexOf(prop) != -1) {
prop.persistent = true;
let file = Cc["@mozilla.org/file/local;1"]

View File

@ -17,14 +17,15 @@ XPIDLSRCS = \
$(NULL)
EXTRA_PP_COMPONENTS = \
ActivitiesGlue.js \
AlertsService.js \
B2GComponents.manifest \
CameraContent.js \
ContentHandler.js \
ContentPermissionPrompt.js \
DirectoryProvider.js \
MozKeyboard.js \
ProcessGlobal.js \
ActivitiesGlue.js \
$(NULL)
ifdef MOZ_UPDATER

View File

@ -684,3 +684,4 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/components/DirectoryProvider.js
@BINPATH@/components/ActivitiesGlue.js
@BINPATH@/components/ProcessGlobal.js
@BINPATH@/components/ContentHandler.js

View File

@ -43,12 +43,26 @@ static void Output(const char *fmt, ... )
va_list ap;
va_start(ap, fmt);
#if defined(XP_WIN) && !MOZ_WINCONSOLE
PRUnichar msg[2048];
_vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
#else
#ifndef XP_WIN
vfprintf(stderr, fmt, ap);
#else
char msg[2048];
vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap);
wchar_t wide_msg[2048];
MultiByteToWideChar(CP_UTF8,
0,
msg,
-1,
wide_msg,
_countof(wide_msg));
#if MOZ_WINCONSOLE
fwprintf_s(stderr, wide_msg);
#else
MessageBoxW(NULL, wide_msg, L"Firefox", MB_OK
| MB_ICONERROR
| MB_SETFOREGROUND);
#endif
#endif
va_end(ap);

View File

@ -1186,3 +1186,5 @@ pref("image.mem.max_decoded_image_kb", 256000);
// Example social provider
pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\",\"sidebarURL\":\"https://motown-dev.mozillalabs.com/social/sidebar\"}");
pref("social.sidebar.open", true);
pref("browser.social.whitelist", "");
pref("social.active", false);

View File

@ -332,6 +332,10 @@
label="&preferencesCmd2.label;"
#endif
oncommand="openPreferences();">
<menuitem id="appmenu_socialToggle"
type="checkbox"
autocheck="false"
command="Social:Toggle"/>
<menupopup id="appmenu_customizeMenu"
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleToolbarsSeparator'));">
<menuitem id="appmenu_preferences"

View File

@ -496,6 +496,10 @@
accesskey="&addons.accesskey;"
key="key_openAddons"
command="Tools:Addons"/>
<menuitem id="menu_socialToggle"
type="checkbox"
autocheck="false"
command="Social:Toggle"/>
#ifdef MOZ_SERVICES_SYNC
<!-- only one of sync-setup or sync-menu will be showing at once -->
<menuitem id="sync-setup"

View File

@ -108,6 +108,7 @@
<command id="Social:SharePage" oncommand="SocialShareButton.sharePage();"/>
<command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
<command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
<command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
</commandset>
<commandset id="placesCommands">

View File

@ -11,6 +11,8 @@ let SocialUI = {
Services.prefs.addObserver("social.sidebar.open", this, false);
gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler, true, true);
Social.init(this._providerReady.bind(this));
},
@ -31,6 +33,7 @@ let SocialUI = {
observe: function SocialUI_observe(subject, topic, data) {
switch (topic) {
case "social:pref-changed":
this.updateToggleCommand();
SocialShareButton.updateButtonHiddenState();
SocialToolbar.updateButtonHiddenState();
SocialSidebar.updateSidebar();
@ -46,11 +49,103 @@ let SocialUI = {
}
},
get toggleCommand() {
return document.getElementById("Social:Toggle");
},
// Called once Social.jsm's provider has been set
_providerReady: function SocialUI_providerReady() {
// If we couldn't find a provider, nothing to do here.
if (!Social.provider)
return;
this.updateToggleCommand();
let toggleCommand = this.toggleCommand;
let label = gNavigatorBundle.getFormattedString("social.enable.label",
[Social.provider.name]);
let accesskey = gNavigatorBundle.getString("social.enable.accesskey");
toggleCommand.setAttribute("label", label);
toggleCommand.setAttribute("accesskey", accesskey);
SocialToolbar.init();
SocialShareButton.init();
SocialSidebar.init();
},
updateToggleCommand: function SocialUI_updateToggleCommand() {
let toggleCommand = this.toggleCommand;
toggleCommand.setAttribute("checked", Social.enabled);
// FIXME: bug 772808: menu items don't inherit the "hidden" state properly,
// need to update them manually.
// This should just be: toggleCommand.hidden = !Social.active;
for (let id of ["appmenu_socialToggle", "menu_socialToggle"]) {
let el = document.getElementById(id);
if (!el)
continue;
if (Social.active)
el.removeAttribute("hidden");
else
el.setAttribute("hidden", "true");
}
},
// This handles "ActivateSocialFeature" events fired against content documents
// in this window.
_activationEventHandler: function SocialUI_activationHandler(e) {
// Nothing to do if Social is already active, or we don't have a provider
// to enable yet.
if (Social.active || !Social.provider)
return;
let targetDoc = e.target;
// Event must be fired against the document
if (!(targetDoc instanceof HTMLDocument))
return;
// Ignore events fired in background tabs
if (targetDoc.defaultView.top != content)
return;
// Check that the associated document's origin is in our whitelist
let prePath = targetDoc.documentURIObject.prePath;
let whitelist = Services.prefs.getCharPref("browser.social.whitelist");
if (whitelist.split(",").indexOf(prePath) == -1)
return;
// If the last event was received < 1s ago, ignore this one
let now = Date.now();
if (now - Social.lastEventReceived < 1000)
return;
Social.lastEventReceived = now;
// Enable the social functionality, and indicate that it was activated
Social.active = true;
// Show a warning, allow undoing the activation
let description = document.getElementById("social-activation-message");
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
let message = gNavigatorBundle.getFormattedString("social.activated.message",
[Social.provider.name, brandShortName]);
description.value = message;
SocialUI.notificationPanel.hidden = false;
setTimeout(function () {
SocialUI.notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
}.bind(this), 0);
},
get notificationPanel() {
return document.getElementById("socialActivatedNotification")
},
undoActivation: function SocialUI_undoActivation() {
Social.active = false;
this.notificationPanel.hidePopup();
}
}
@ -153,22 +248,33 @@ var SocialToolbar = {
// Called once, after window load, when the Social.provider object is initialized
init: function SocialToolbar_init() {
document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
// handle button state
document.getElementById("social-statusarea-popup").addEventListener("popupshowing", function(e) {
document.getElementById("social-toolbar-button").setAttribute("open", "true");
}, false);
document.getElementById("social-statusarea-popup").addEventListener("popuphiding", function(e) {
document.getElementById("social-toolbar-button").removeAttribute("open");
}, false);
let removeItem = document.getElementById("social-remove-menuitem");
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
let label = gNavigatorBundle.getFormattedString("social.remove.label",
[brandShortName]);
let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
removeItem.setAttribute("label", label);
removeItem.setAttribute("accesskey", accesskey);
let statusAreaPopup = document.getElementById("social-statusarea-popup");
statusAreaPopup.addEventListener("popupshowing", function(e) {
this.button.setAttribute("open", "true");
}.bind(this));
statusAreaPopup.addEventListener("popuphidden", function(e) {
this.button.removeAttribute("open");
}.bind(this));
this.updateButton();
this.updateProfile();
},
get button() {
return document.getElementById("social-toolbar-button");
},
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
let toolbarbutton = document.getElementById("social-toolbar-button");
toolbarbutton.hidden = !Social.uiVisible;
this.button.hidden = !Social.uiVisible;
},
updateProfile: function SocialToolbar_updateProfile() {
@ -233,10 +339,10 @@ var SocialToolbar = {
panel.hidden = false;
function sizePanelToContent() {
// XXX Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
// XXX need to handle dynamic sizing
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
// Need to handle dynamic sizing
let doc = notifBrowser.contentDocument;
// XXX "notif" is an implementation detail that we should get rid of
// "notif" is an implementation detail that we should get rid of
// eventually
let body = doc.getElementById("notif") || doc.body.firstChild;
if (!body)
@ -254,13 +360,13 @@ var SocialToolbar = {
panel.addEventListener("popuphiding", function onpopuphiding() {
panel.removeEventListener("popuphiding", onpopuphiding);
// unload the panel
document.getElementById("social-toolbar-button").removeAttribute("open");
SocialToolbar.button.removeAttribute("open");
notifBrowser.setAttribute("src", "about:blank");
});
notifBrowser.setAttribute("origin", Social.provider.origin);
notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
document.getElementById("social-toolbar-button").setAttribute("open", "true");
this.button.setAttribute("open", "true");
panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
}
}

View File

@ -182,6 +182,44 @@
</hbox>
</panel>
<panel id="socialActivatedNotification"
type="arrow"
hidden="true"
consumeoutsideclicks="true"
align="start"
role="alert">
<hbox flex="1">
<image src="chrome://browser/content/social-icon.png" class="popup-notification-icon"/>
<vbox flex="1">
<description id="social-activation-message" class="popup-notification-description"/>
<spacer flex="1"/>
<hbox pack="end" align="center" class="popup-notification-button-container">
#ifdef XP_UNIX
<button id="social-undoactivation-button"
label="&social.activated.button.label;"
accesskey="&social.activated.button.accesskey;"
onclick="SocialUI.undoActivation();"/>
<button default="true"
autofocus="autofocus"
label="&social.ok.label;"
accesskey="&social.ok.accesskey;"
oncommand="SocialUI.notificationPanel.hidePopup();"/>
#else
<button default="true"
autofocus="autofocus"
label="&social.ok.label;"
accesskey="&social.ok.accesskey;"
oncommand="SocialUI.notificationPanel.hidePopup();"/>
<button id="social-undoactivation-button"
label="&social.activated.button.label;"
accesskey="&social.activated.button.accesskey;"
onclick="SocialUI.undoActivation();"/>
#endif
</hbox>
</vbox>
</hbox>
</panel>
<panel id="editSharePopup"
type="arrow"
orient="vertical"
@ -214,16 +252,16 @@
class="editSharePopupBottomButton"
default="true"
autofocus="autofocus"
label="&social.sharePopup.ok.label;"
accesskey="&social.sharePopup.ok.accesskey;"
label="&social.ok.label;"
accesskey="&social.ok.accesskey;"
oncommand="SocialShareButton.dismissSharePopup();"/>
#else
<button id="editSharePopupOkButton"
class="editSharePopupBottomButton"
default="true"
autofocus="autofocus"
label="&social.sharePopup.ok.label;"
accesskey="&social.sharePopup.ok.accesskey;"
label="&social.ok.label;"
accesskey="&social.ok.accesskey;"
oncommand="SocialShareButton.dismissSharePopup();"/>
<button id="editSharePopupUndoButton"
class="editSharePopupBottomButton"
@ -638,6 +676,8 @@
oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/>
</vbox>
</hbox>
<menuitem id="social-remove-menuitem"
oncommand="Social.active = false;"/>
<menuitem id="social-toggle-sidebar-menuitem"
type="checkbox"
autocheck="false"

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -258,6 +258,10 @@ _BROWSER_FILES = \
browser_bug734076.js \
browser_social_toolbar.js \
browser_social_sidebar.js \
browser_social_mozSocial_API.js \
social_panel.html \
social_sidebar.html \
social_worker.js \
$(NULL)
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))

View File

@ -0,0 +1,87 @@
/* 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/. */
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
function test() {
// XXX Bug 775779
if (Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).isDebugBuild) {
ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
return;
}
waitForExplicitFinish();
let manifest = { // normal provider
name: "provider 1",
origin: "http://example.com",
sidebarURL: "http://example.com/browser/browser/base/content/test/social_sidebar.html",
workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
iconURL: "chrome://branding/content/icon48.png"
};
runSocialTestWithProvider(manifest, doTest);
}
function doTest() {
let iconsReady = false;
let gotSidebarMessage = false;
function checkNext() {
if (iconsReady && gotSidebarMessage)
triggerIconPanel();
}
function triggerIconPanel() {
let statusIcons = document.getElementById("social-status-iconbox");
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
// Click the button to trigger its contentPanel
let panel = document.getElementById("social-notification-panel");
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
}
let port = Social.provider.port;
ok(port, "provider has a port");
port.postMessage({topic: "test-init"});
Social.provider.port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "got-panel-message":
ok(true, "got panel message");
// Wait for the panel to close before ending the test
let panel = document.getElementById("social-notification-panel");
panel.addEventListener("popuphidden", function hiddenListener() {
panel.removeEventListener("popuphidden", hiddenListener);
SocialService.removeProvider(Social.provider.origin, finish);
});
panel.hidePopup();
break;
case "got-sidebar-message":
// The sidebar message will always come first, since it loads by default
ok(true, "got sidebar message");
info(topic);
gotSidebarMessage = true;
checkNext();
break;
}
}
// Our worker sets up ambient notification at the same time as it responds to
// the workerAPI initialization. If it's already initialized, we can
// immediately check the icons, otherwise wait for initialization by
// observing the topic sent out by the social service.
if (Social.provider.workerAPI.initialized) {
iconsReady = true;
checkNext();
} else {
Services.obs.addObserver(function obs() {
Services.obs.removeObserver(obs, "social:ambient-notification-changed");
// Let the other observers (like the one that updates the UI) run before
// checking the icons.
executeSoon(function () {
iconsReady = true;
checkNext();
});
}, "social:ambient-notification-changed", false);
}
}

View File

@ -0,0 +1,14 @@
<html>
<head>
<meta charset="utf-8">
<script>
function pingWorker() {
var port = navigator.mozSocial.getWorker().port;
port.postMessage({topic: "panel-message", result: "ok"});
}
</script>
</head>
<body onload="pingWorker();">
<p>This is a test social panel.</p>
</body>
</html>

View File

@ -0,0 +1,14 @@
<html>
<head>
<meta charset="utf-8">
<script>
function pingWorker() {
var port = navigator.mozSocial.getWorker().port;
port.postMessage({topic: "sidebar-message", result: "ok"});
}
</script>
</head>
<body onload="pingWorker();">
<p>This is a test social sidebar.</p>
</body>
</html>

View File

@ -0,0 +1,40 @@
/* 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/. */
let testPort;
onconnect = function(e) {
let port = e.ports[0];
port.onmessage = function onMessage(event) {
let topic = event.data.topic;
switch (topic) {
case "test-init":
testPort = port;
break;
case "sidebar-message":
if (testPort && event.data.result == "ok")
testPort.postMessage({topic:"got-sidebar-message"});
break;
case "panel-message":
if (testPort && event.data.result == "ok")
testPort.postMessage({topic:"got-panel-message"});
break;
case "social.initialize":
// This is the workerAPI port, respond and set up a notification icon.
port.postMessage({topic: "social.initialize-response"});
let profile = {
userName: "foo"
};
port.postMessage({topic: "social.user-profile", data: profile});
let icon = {
name: "testIcon",
iconURL: "chrome://branding/content/icon48.png",
contentPanel: "http://example.com/browser/browser/base/content/test/social_panel.html",
counter: 1
};
port.postMessage({topic: "social.ambient-notification", data: icon});
break;
}
}
}

View File

@ -101,6 +101,7 @@ browser.jar:
#ifdef XP_WIN
* content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
#endif
content/browser/social-icon.png (content/social-icon.png)
# the following files are browser-specific overrides
* content/browser/license.html (/toolkit/content/license.html)
% override chrome://global/content/license.html chrome://browser/content/license.html

View File

@ -68,7 +68,7 @@ PlacesViewBase.prototype = {
if (val) {
this._resultNode = val.root;
this._rootElt._placesNode = this._resultNode;
this._domNodes = new WeakMap();
this._domNodes = new Map();
this._domNodes.set(this._resultNode, this._rootElt);
// This calls _rebuild through invalidateContainer.

View File

@ -80,7 +80,7 @@ function PlacesController(aView) {
return Services.dirsvc.get("ProfD", Ci.nsIFile).leafName;
});
this._cachedLivemarkInfoObjects = new WeakMap();
this._cachedLivemarkInfoObjects = new Map();
}
PlacesController.prototype = {

View File

@ -51,7 +51,7 @@ PlacesTreeView.prototype = {
// Bug 761494:
// ----------
// Some addons use methods from nsINavHistoryResultObserver and
// nsINavHistoryResultTreeViewer, without QIing to these intefaces first.
// nsINavHistoryResultTreeViewer, without QIing to these interfaces first.
// That's not a problem when the view is retrieved through the
// <tree>.view getter (which returns the wrappedJSObject of this object),
// it raises an issue when the view retrieved through the treeBoxObject.view
@ -153,12 +153,21 @@ PlacesTreeView.prototype = {
_getRowForNode:
function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) {
if (aNode == this._rootNode)
throw "The root node is never visible";
throw new Error("The root node is never visible");
let ancestors = PlacesUtils.nodeAncestors(aNode);
for (let ancestor in ancestors) {
// A node is removed form the view either if it has no parent or if its
// root-ancestor is not the root node (in which case that's the node
// for which nodeRemoved was called).
let ancestors = [x for each (x in PlacesUtils.nodeAncestors(aNode))];
if (ancestors.length == 0 ||
ancestors[ancestors.length - 1] != this._rootNode) {
throw new Error("Removed node passed to _getRowForNode");
}
// Ensure that the entire chain is open, otherwise that node is invisible.
for (let ancestor of ancestors) {
if (!ancestor.containerOpen)
throw "Invisible node passed to _getRowForNode";
throw new Error("Invisible node passed to _getRowForNode");
}
// Non-plain containers are initially built with their contents.
@ -1097,7 +1106,7 @@ PlacesTreeView.prototype = {
if (val) {
this._result = val;
this._rootNode = this._result.root;
this._cellProperties = new WeakMap();
this._cellProperties = new Map();
this._cuttingNodes = new Set();
}
else if (this._result) {

View File

@ -657,11 +657,21 @@ toolbar button -->
<!ENTITY socialToolbar.title "Social Toolbar Button">
<!ENTITY social.notLoggedIn.label "Not logged in">
<!-- LOCALIZATION NOTE (social.ok.label, social.ok.accesskey): this string is
used for the "OK" button for two different social panels. One appears when
the feature is activated (social.activated.* below), and the other when
the user clicks the "Share" button a second time (social.sharePopup.*
below). -->
<!ENTITY social.ok.label "OK">
<!ENTITY social.ok.accesskey "O">
<!ENTITY social.sharePopup.undo.label "Unshare">
<!ENTITY social.sharePopup.undo.accesskey "U">
<!ENTITY social.sharePopup.ok.label "OK">
<!ENTITY social.sharePopup.ok.accesskey "O">
<!ENTITY social.sharePopup.shared.label "You shared this page.">
<!ENTITY social.sharePopup.portrait.arialabel "User profile picture">
<!ENTITY social.toggleSidebar.label "Show sidebar">
<!ENTITY social.toggleSidebar.accesskey "s">
<!ENTITY social.activated.button.label "Oops, undo">
<!ENTITY social.activated.button.accesskey "u">

View File

@ -372,3 +372,14 @@ fullscreen.rememberDecision=Remember decision for %S
social.shareButton.tooltip=Share this
social.shareButton.sharedtooltip=You shared this
social.pageShared.label=Page shared
# LOCALIZATION NOTE (social.enable.label): %S = Social networking provider
social.enable.label=%S integration
social.enable.accesskey=n
# LOCALIZATION NOTE (social.remove.label): %S = brandShortName
social.remove.label=Remove from %S
social.remove.accesskey=R
# LOCALIZATION NOTE (social.enabled.message): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
social.activated.message=%1$S integration with %2$S has been activated.

View File

@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
"resource://gre/modules/SocialService.jsm");
let Social = {
lastEventReceived: 0,
provider: null,
init: function Social_init(callback) {
if (this.provider) {
@ -38,6 +39,25 @@ let Social = {
return this.provider && this.provider.enabled && this.provider.port;
},
set enabled(val) {
SocialService.enabled = val;
},
get enabled() {
return SocialService.enabled;
},
get active() {
return Services.prefs.getBoolPref("social.active");
},
set active(val) {
Services.prefs.setBoolPref("social.active", !!val);
this.enabled = !!val;
},
toggle: function Social_toggle() {
this.enabled = !this.enabled;
},
toggleSidebar: function SocialSidebar_toggle() {
let prefValue = Services.prefs.getBoolPref("social.sidebar.open");
Services.prefs.setBoolPref("social.sidebar.open", !prefValue);

View File

@ -6,4 +6,6 @@ setup.py:testing/mozbase/mozlog:develop
setup.py:testing/mozbase/mozprocess:develop
setup.py:testing/mozbase/mozprofile:develop
setup.py:testing/mozbase/mozrunner:develop
setup.py:build/pylib/blessings:develop
setup.py:python/blessings:develop
mozilla.pth:build
mozilla.pth:config

View File

@ -5,9 +5,11 @@
# This file contains code for populating the virtualenv environment for
# Mozilla's build system. It is typically called as part of configure.
from __future__ import with_statement
import os.path
import subprocess
import sys
import distutils.sysconfig
def populate_virtualenv(top_source_directory, manifest_filename):
"""Populate the virtualenv from the contents of a manifest.
@ -38,6 +40,11 @@ def populate_virtualenv(top_source_directory, manifest_filename):
call_setup(os.path.join(top_source_directory, package[1]),
package[2:])
if package[0].endswith('.pth'):
assert len(package) == 2
with open(os.path.join(distutils.sysconfig.get_python_lib(), package[0]), 'a') as f:
f.write("%s\n" % os.path.join(top_source_directory, package[1]))
def call_setup(directory, arguments):
"""Calls setup.py in a directory."""

View File

@ -161,6 +161,7 @@ PYUNITS := \
unit-buildlist.py \
unit-expandlibs.py \
unit-writemozinfo.py \
unit-mozunit.py \
$(NULL)
check-preqs = \

View File

@ -126,11 +126,13 @@ class Preprocessor:
'file': self.context['FILE'],
'le': self.LE})
self.writtenLines = ln
aLine = self.applyFilters(aLine)
filteredLine = self.applyFilters(aLine)
if filteredLine != aLine:
self.actionLevel = 2
# ensure our line ending. Only need to handle \n, as we're reading
# with universal line ending support, at least for files.
aLine = re.sub('\n', self.LE, aLine)
self.out.write(aLine)
filteredLine = re.sub('\n', self.LE, filteredLine)
self.out.write(filteredLine)
def handleCommandLine(self, args, defaultToStdin = False):
"""

View File

@ -3,7 +3,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
import unittest
import inspect
from StringIO import StringIO
import os
'''Helper to make python unit tests report the way that the Mozilla
unit test infrastructure expects tests to report.
@ -11,10 +14,10 @@ unit test infrastructure expects tests to report.
Usage:
import unittest
from mozunit import MozTestRunner
import mozunit
if __name__ == '__main__':
unittest.main(testRunner=MozTestRunner())
mozunit.main()
'''
class _MozTestResult(_TestResult):
@ -68,3 +71,69 @@ class MozTestRunner(_TestRunner):
test(result)
result.printErrorList()
return result
class MockedFile(StringIO):
def __init__(self, context, filename, content = ''):
self.context = context
self.name = filename
StringIO.__init__(self, content)
def close(self):
self.context.files[self.name] = self.getvalue()
StringIO.close(self)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
class MockedOpen(object):
'''
Context manager diverting the open builtin such that opening files
can open "virtual" file instances given when creating a MockedOpen.
with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
f = open('foo', 'r')
will thus open the virtual file instance for the file 'foo' to f.
MockedOpen also masks writes, so that creating or replacing files
doesn't touch the file system, while subsequently opening the file
will return the recorded content.
with MockedOpen():
f = open('foo', 'w')
f.write('foo')
self.assertRaises(Exception,f.open('foo', 'r'))
'''
def __init__(self, files = {}):
self.files = {}
for name, content in files.iteritems():
self.files[os.path.abspath(name)] = content
def __call__(self, name, mode = 'r'):
absname = os.path.abspath(name)
if 'w' in mode:
file = MockedFile(self, absname)
elif absname in self.files:
file = MockedFile(self, absname, self.files[absname])
elif 'a' in mode:
file = MockedFile(self, absname, self.open(name, 'r').read())
else:
file = self.open(name, mode)
if 'a' in mode:
file.seek(0, os.SEEK_END)
return file
def __enter__(self):
import __builtin__
self.open = __builtin__.open
__builtin__.open = self
def __exit__(self, type, value, traceback):
import __builtin__
__builtin__.open = self.open
def main(*args):
unittest.main(testRunner=MozTestRunner(),*args)

View File

@ -291,11 +291,9 @@ endif
ifndef MOZ_AUTO_DEPS
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
ifndef NO_GEN_XPT
MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
endif
endif
endif
ALL_TRASH = \
$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
@ -1298,7 +1296,6 @@ $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
@if test -n "$(findstring $*.h, $(EXPORTS))"; \
then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
@ -1323,8 +1320,6 @@ ifndef NO_INTERFACES_MANIFEST
endif
endif
endif # NO_GEN_XPT
GARBAGE_DIRS += $(XPIDL_GEN_DIR)
endif #} XPIDLSRCS

View File

@ -2,7 +2,7 @@ import unittest
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import mozunit
from Expression import Expression, Context
@ -60,4 +60,4 @@ class TestExpression(unittest.TestCase):
self.assert_(Expression('FAIL != 1').evaluate(self.c))
if __name__ == '__main__':
unittest.main()
mozunit.main()

View File

@ -5,9 +5,7 @@ from filecmp import dircmp
from tempfile import mkdtemp
from shutil import rmtree, copy2
from zipfile import ZipFile
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from mozunit import MozTestRunner
import mozunit
from JarMaker import JarMaker
if sys.platform == "win32":
@ -280,4 +278,4 @@ class TestJarMaker(unittest.TestCase):
self.assertTrue(not difference, difference)
if __name__ == '__main__':
unittest.main(testRunner=MozTestRunner())
mozunit.main()

View File

@ -4,7 +4,7 @@ from StringIO import StringIO
import os
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import mozunit
from Preprocessor import Preprocessor
@ -43,4 +43,4 @@ class TestLineEndings(unittest.TestCase):
self.assertEquals(self.pp.out.getvalue(), 'a\nb\nc\n')
if __name__ == '__main__':
unittest.main()
mozunit.main()

View File

@ -5,41 +5,14 @@ from StringIO import StringIO
import os
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from mozunit import main, MockedOpen
from Preprocessor import Preprocessor
class NamedIO(StringIO):
def __init__(self, name, content):
self.name = name
StringIO.__init__(self, content)
class MockedOpen(object):
"""
Context manager diverting the open builtin such that opening files
can open NamedIO instances given when creating a MockedOpen.
with MockedOpen(NamedIO('foo', 'foo'), NamedIO('bar', 'bar')):
f = open('foo', 'r')
will thus assign the NamedIO instance for the file 'foo' to f.
"""
def __init__(self, *files):
self.files = {}
for f in files:
self.files[os.path.abspath(f.name)] = f
def __call__(self, name, args):
absname = os.path.abspath(name)
if absname in self.files:
return self.files[absname]
return self.open(name, args)
def __enter__(self):
import __builtin__
self.open = __builtin__.open
__builtin__.open = self
def __exit__(self, type, value, traceback):
import __builtin__
__builtin__.open = self.open
def NamedIO(name, content):
with open(name, 'w') as f:
f.write(content)
return name
class TestPreprocessor(unittest.TestCase):
"""
@ -539,13 +512,13 @@ octal value is not equal
self.fail("Expected a Preprocessor.Error")
def test_include(self):
with MockedOpen(NamedIO("foo/test", """#define foo foobarbaz
with MockedOpen({"foo/test": """#define foo foobarbaz
#include @inc@
@bar@
"""),
NamedIO("bar", """#define bar barfoobaz
""",
"bar": """#define bar barfoobaz
@foo@
""")):
"""}):
f = NamedIO("include.in", """#filter substitution
#define inc ../bar
#include foo/test""")
@ -575,7 +548,7 @@ barfoobaz
self.fail("Expected a Preprocessor.Error")
def test_include_literal_at(self):
with MockedOpen(NamedIO("@foo@", "#define foo foobarbaz")):
with MockedOpen({"@foo@": "#define foo foobarbaz"}):
f = NamedIO("include_literal_at.in", """#include @foo@
#filter substitution
@foo@
@ -585,11 +558,11 @@ barfoobaz
""")
def test_command_line_literal_at(self):
with MockedOpen(NamedIO("@foo@.in", """@foo@
""")):
with MockedOpen({"@foo@.in": """@foo@
"""}):
self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo@.in'])
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
""")
if __name__ == '__main__':
unittest.main()
main()

View File

@ -3,7 +3,7 @@ import unittest
import os, sys, os.path, time
from tempfile import mkdtemp
from shutil import rmtree
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import mozunit
from buildlist import addEntriesToListFile
@ -77,4 +77,4 @@ class TestBuildList(unittest.TestCase):
self.assertFileContains(testfile, ["a","b","c"])
if __name__ == '__main__':
unittest.main()
mozunit.main()

View File

@ -6,8 +6,7 @@ import os
import imp
from tempfile import mkdtemp
from shutil import rmtree
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from mozunit import MozTestRunner
import mozunit
from UserString import UserString
# Create a controlled configuration for use by expandlibs
@ -385,4 +384,4 @@ class TestSymbolOrder(unittest.TestCase):
if __name__ == '__main__':
unittest.main(testRunner=MozTestRunner())
mozunit.main()

View File

@ -0,0 +1,75 @@
# 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/.
from __future__ import with_statement
import sys
import os
from mozunit import main, MockedOpen
import unittest
from tempfile import mkstemp
class TestMozUnit(unittest.TestCase):
def test_mocked_open(self):
# Create a temporary file on the file system.
(fd, path) = mkstemp()
with os.fdopen(fd, 'w') as file:
file.write('foobar');
with MockedOpen({'file1': 'content1',
'file2': 'content2'}):
# Check the contents of the files given at MockedOpen creation.
self.assertEqual(open('file1', 'r').read(), 'content1')
self.assertEqual(open('file2', 'r').read(), 'content2')
# Check that overwriting these files alters their content.
with open('file1', 'w') as file:
file.write('foo')
self.assertEqual(open('file1', 'r').read(), 'foo')
# ... but not until the file is closed.
file = open('file2', 'w')
file.write('bar')
self.assertEqual(open('file2', 'r').read(), 'content2')
file.close()
self.assertEqual(open('file2', 'r').read(), 'bar')
# Check that appending to a file does append
with open('file1', 'a') as file:
file.write('bar')
self.assertEqual(open('file1', 'r').read(), 'foobar')
# Opening a non-existing file ought to fail.
self.assertRaises(IOError, open, 'file3', 'r')
# Check that writing a new file does create the file.
with open('file3', 'w') as file:
file.write('baz')
self.assertEqual(open('file3', 'r').read(), 'baz')
# Check the content of the file created outside MockedOpen.
self.assertEqual(open(path, 'r').read(), 'foobar')
# Check that overwriting a file existing on the file system
# does modify its content.
with open(path, 'w') as file:
file.write('bazqux')
self.assertEqual(open(path, 'r').read(), 'bazqux')
with MockedOpen():
# Check that appending to a file existing on the file system
# does modify its content.
with open(path, 'a') as file:
file.write('bazqux')
self.assertEqual(open(path, 'r').read(), 'foobarbazqux')
# Check that the file was not actually modified on the file system.
self.assertEqual(open(path, 'r').read(), 'foobar')
os.remove(path)
# Check that the file created inside MockedOpen wasn't actually
# created.
self.assertRaises(IOError, open, 'file3', 'r')
if __name__ == "__main__":
main()

View File

@ -3,7 +3,7 @@ import unittest
import os, sys, os.path, time
from tempfile import mkdtemp
from shutil import rmtree
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import mozunit
from mozprocess import processhandler
from nsinstall import nsinstall
@ -170,4 +170,4 @@ class TestNsinstall(unittest.TestCase):
#TODO: implement -R, -l, -L and test them!
if __name__ == '__main__':
unittest.main()
mozunit.main()

View File

@ -2,7 +2,7 @@ import unittest
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import mozunit
from printprereleasesuffix import get_prerelease_suffix
@ -77,4 +77,4 @@ class TestGetPreReleaseSuffix(unittest.TestCase):
self.assertEqual(self.c, '')
if __name__ == '__main__':
unittest.main()
mozunit.main()

View File

@ -3,8 +3,7 @@ from __future__ import with_statement
import unittest
import os, sys, time, tempfile
from StringIO import StringIO
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import mozunit
from writemozinfo import build_dict, write_json, JsonValue, jsonify
@ -239,5 +238,4 @@ class TestWriteJson(unittest.TestCase):
self.assertEqual(32, d['bits'])
if __name__ == '__main__':
unittest.main()
mozunit.main()

View File

@ -363,6 +363,10 @@ else
fi
fi
if test -n "$MOZ_WINCONSOLE"; then
AC_DEFINE(MOZ_WINCONSOLE)
fi
MOZ_TOOL_VARIABLES
dnl ========================================================
@ -746,6 +750,9 @@ if test -n "$_WIN32_MSVC"; then
AC_DEFINE(HAVE_IO_H)
AC_DEFINE(HAVE_SETBUF)
AC_DEFINE(HAVE_ISATTY)
if test $_MSC_VER -ge 1600; then
AC_DEFINE(HAVE_NULLPTR)
fi
fi
fi # COMPILE_ENVIRONMENT
@ -4206,6 +4213,7 @@ MOZ_ANDROID_HISTORY=
MOZ_WEBSMS_BACKEND=
MOZ_GRAPHITE=1
ACCESSIBILITY=1
MOZ_SYS_MSG=
case "$target_os" in
mingw*)
@ -7313,7 +7321,7 @@ MOZ_ARG_ENABLE_BOOL(b2g-ril,
MOZ_B2G_RIL=1,
MOZ_B2G_RIL= )
if test -n "$MOZ_B2G_RIL"; then
AC_DEFINE(MOZ_B2G_RIL)
AC_DEFINE(MOZ_B2G_RIL)
fi
AC_SUBST(MOZ_B2G_RIL)
@ -7325,14 +7333,16 @@ MOZ_ARG_ENABLE_BOOL(b2g-bt,
MOZ_B2G_BT=1,
MOZ_B2G_BT= )
if test -n "$MOZ_B2G_BT"; then
AC_DEFINE(MOZ_B2G_BT)
AC_DEFINE(MOZ_B2G_BT)
fi
AC_SUBST(MOZ_B2G_BT)
dnl ========================================================
dnl = Enable Support for System Messages API
dnl ========================================================
if test -n "$MOZ_SYS_MSG"; then
AC_DEFINE(MOZ_SYS_MSG)
fi
AC_SUBST(MOZ_SYS_MSG)
dnl ========================================================

View File

@ -11,6 +11,7 @@
#include "nsChangeHint.h"
#include "nsINode.h"
#include "nsIDocument.h" // for IsInHTMLDocument
#include "nsCSSProperty.h"
// Forward declarations
class nsIAtom;

View File

@ -1291,6 +1291,8 @@ private:
NodeMayHaveDOMMutationObserver,
// Set if node is Content
NodeIsContent,
// Set if the node has animations or transitions
ElementHasAnimations,
// Guard value
BooleanFlagCount
};
@ -1356,6 +1358,8 @@ public:
bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetInDocument() { SetBoolFlag(IsInDocument); }

View File

@ -178,8 +178,6 @@ MOCHITEST_FILES_A = \
file_bug426646-1.html \
file_bug426646-2.html \
test_bug429157.html \
test_header.html \
header.sjs \
test_XHR.html \
file_XHR_pass1.xml \
file_XHR_pass2.txt \

View File

@ -1,8 +0,0 @@
function handleRequest(request, response) {
response.setHeader("Content-Type", "text/plain", false);
response.setHeader("Cache-Control", "no-cache", false);
var value = request.hasHeader("SomeHeader") ? request.getHeader("SomeHeader")
: "";
response.write("SomeHeader: " + value);
}

View File

@ -1,31 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for XHR header preservation</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 421622 **/
const SJS_URL = "http://mochi.test:8888/tests/content/base/test/header.sjs";
const VALUE = "http://www.mozilla.org/";
var req = new XMLHttpRequest();
req.open("GET", SJS_URL, false);
req.setRequestHeader("SomeHeader", VALUE);
req.send(null);
is(req.responseText,
"SomeHeader: " + VALUE,
"Header received by server does not match what was set");
</script>
</pre>
</body>
</html>

View File

@ -26,6 +26,11 @@ public:
Init(aX1, aY1, aX2, aY2);
}
double X1() const { return mX1; }
double Y1() const { return mY1; }
double X2() const { return mX2; }
double Y2() const { return mY2; }
void Init(double aX1, double aY1,
double aX2, double aY2);

View File

@ -4901,6 +4901,13 @@ nsDocShell::SetParentNativeWindow(nativeWindow parentNativeWindow)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocShell::GetNativeHandle(nsAString& aNativeHandle)
{
// the nativeHandle should be accessed from nsIXULWindow
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocShell::GetVisibility(bool * aVisibility)
{

View File

@ -228,8 +228,8 @@ let AlarmService = {
if (this._currentAlarm) {
debug("Fire system intent: " + JSON.stringify(this._currentAlarm));
if (this._currentAlarm.manifestURL)
messenger.sendMessage("alarm", this._currentAlarm, this._currentAlarm.manifestURL);
let manifestURI = Services.io.newURI(this._currentAlarm.manifestURL, null, null);
messenger.sendMessage("alarm", this._currentAlarm, manifestURI);
this._currentAlarm = null;
}
@ -244,8 +244,8 @@ let AlarmService = {
// fire system intent for it instead of setting it
if (nextAlarmTime <= nowTime) {
debug("Fire system intent: " + JSON.stringify(nextAlarm));
if (nextAlarm.manifestURL)
messenger.sendMessage("alarm", nextAlarm, nextAlarm.manifestURL);
let manifestURI = Services.io.newURI(nextAlarm.manifestURL, null, null);
messenger.sendMessage("alarm", nextAlarm, manifestURI);
} else {
this._currentAlarm = nextAlarm;
break;

View File

@ -45,6 +45,11 @@ AlarmsManager.prototype = {
add: function add(aDate, aRespectTimezone, aData) {
debug("add()");
if (!this._manifestURL) {
debug("Cannot add alarms for non-installed apps.");
throw Components.results.NS_ERROR_FAILURE;
}
let isIgnoreTimezone = true;
switch (aRespectTimezone) {
case "honorTimezone":
@ -150,8 +155,7 @@ AlarmsManager.prototype = {
// Get the manifest URL if this is an installed app
this._manifestURL = null;
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let app = utils.getApp();
if (app)
this._manifestURL = app.manifestURL;

View File

@ -1298,7 +1298,7 @@ Navigator::GetMozBluetooth(nsIDOMBluetoothManager** aBluetooth)
// nsNavigator::nsIDOMNavigatorSystemMessages
//*****************************************************************************
#ifdef MOZ_SYS_MSG
NS_IMETHODIMP
nsresult
Navigator::EnsureMessagesManager()
{
if (mMessagesManager) {

View File

@ -5973,6 +5973,9 @@ DefineIDBInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
else if (aIID->Equals(NS_GET_IID(nsIIDBTransaction))) {
interface = IDBConstant::IDBTransaction;
}
else {
MOZ_NOT_REACHED("unexpected IID");
}
for (int8_t i = 0; i < (int8_t)mozilla::ArrayLength(sIDBConstants); ++i) {
const IDBConstant& c = sIDBConstants[i];

View File

@ -9400,9 +9400,7 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
nsRefPtr<nsTimeout> copy = timeout;
rv = timeout->mTimer->InitWithFuncCallback(TimerCallback, timeout,
realInterval,
nsITimer::TYPE_ONE_SHOT);
rv = timeout->InitTimer(TimerCallback, realInterval);
if (NS_FAILED(rv)) {
return rv;
}
@ -9637,10 +9635,7 @@ nsGlobalWindow::RescheduleTimeout(nsTimeout* aTimeout, const TimeStamp& now,
// platforms whether delay is positive or negative (which we
// know is always positive here, but cast anyways for
// consistency).
nsresult rv = aTimeout->mTimer->
InitWithFuncCallback(TimerCallback, aTimeout,
delay.ToMilliseconds(),
nsITimer::TYPE_ONE_SHOT);
nsresult rv = aTimeout->InitTimer(TimerCallback, delay.ToMilliseconds());
if (NS_FAILED(rv)) {
NS_ERROR("Error initializing timer for DOM timeout!");
@ -9982,11 +9977,7 @@ nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
timeout->mFiringDepth = firingDepth;
timeout->Release();
nsresult rv =
timeout->mTimer->InitWithFuncCallback(TimerCallback,
timeout,
delay.ToMilliseconds(),
nsITimer::TYPE_ONE_SHOT);
nsresult rv = timeout->InitTimer(TimerCallback, delay.ToMilliseconds());
if (NS_FAILED(rv)) {
NS_WARNING("Error resetting non background timer for DOM timeout!");
@ -10499,8 +10490,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
t->mTimer = do_CreateInstance("@mozilla.org/timer;1");
NS_ENSURE_TRUE(t->mTimer, NS_ERROR_OUT_OF_MEMORY);
rv = t->mTimer->InitWithFuncCallback(TimerCallback, t, delay,
nsITimer::TYPE_ONE_SHOT);
rv = t->InitTimer(TimerCallback, delay);
if (NS_FAILED(rv)) {
t->mTimer = nsnull;
return rv;

View File

@ -153,6 +153,11 @@ struct nsTimeout : PRCList
return static_cast<nsTimeout*>(PR_PREV_LINK(this));
}
nsresult InitTimer(nsTimerCallbackFunc aFunc, PRUint64 delay) {
return mTimer->InitWithFuncCallback(aFunc, this, delay,
nsITimer::TYPE_ONE_SHOT);
}
// Window for which this timeout fires
nsRefPtr<nsGlobalWindow> mWindow;

View File

@ -80,8 +80,9 @@ template<>
struct PrimitiveConversionTraits<bool> {
typedef JSBool jstype;
typedef bool intermediateType;
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
return JS_ValueToBoolean(cx, v, retval);
static inline bool converter(JSContext* /* unused */, JS::Value v, jstype* retval) {
*retval = JS::ToBoolean(v);
return true;
}
};

View File

@ -403,8 +403,10 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
DBusMessageIter iter;
NS_ASSERTION(dbus_message_iter_init(aMsg, &iter),
"Can't create message iterator!");
if (!dbus_message_iter_init(aMsg, &iter)) {
NS_WARNING("Can't create iterator!");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
InfallibleTArray<BluetoothNamedValue> value;
const char* addr;

View File

@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<body onunload="unload()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
<p id="display"></p>
<div id="content" style="display: none">
@ -22,11 +22,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test">
<script class="testbody" type="text/javascript">
function unload() {
delete gDataBlob;
gDataBlob = null;
delete gFileReader;
gFileReader = null;
}
devicestorage_setup();
var gFileName = "devicestorage/hi";
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies."
var gDataBlob = new Blob([gData], {type: 'text/plain'});
var gFileReader = new FileReader();
function getAfterDeleteSuccess(e) {
ok(false, "file was deleted not successfully");
@ -63,9 +73,8 @@ function getSuccess(e) {
var name = e.target.result.name;
var reader = new FileReader();
reader.readAsArrayBuffer(gDataBlob);
reader.onload = function(e) {
gFileReader.readAsArrayBuffer(gDataBlob);
gFileReader.onload = function(e) {
readerCallback(e);
request = storage[0].delete(name)

View File

@ -17,7 +17,7 @@ namespace dom {
void
CrashReporterParent::ActorDestroy(ActorDestroyReason why)
{
#if defined(__ANDROID__) && defined(MOZ_CRASHREPORTER)
#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
CrashReporter::RemoveLibraryMappingsForChild(ProcessId(OtherProcess()));
#endif
}
@ -25,7 +25,7 @@ CrashReporterParent::ActorDestroy(ActorDestroyReason why)
bool
CrashReporterParent::RecvAddLibraryMappings(const InfallibleTArray<Mapping>& mappings)
{
#if defined(__ANDROID__) && defined(MOZ_CRASHREPORTER)
#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
for (PRUint32 i = 0; i < mappings.Length(); i++) {
const Mapping& m = mappings[i];
CrashReporter::AddLibraryMappingForChild(ProcessId(OtherProcess()),

View File

@ -1947,6 +1947,68 @@ nsPluginHost::IsLiveTag(nsIPluginTag* aPluginTag)
return false;
}
nsPluginTag*
nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag)
{
for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
if (tag->HasSameNameAndMimes(aPluginTag)) {
return tag;
}
}
return nsnull;
}
nsPluginTag*
nsPluginHost::FirstPluginWithPath(const nsCString& path)
{
for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
if (tag->mFullPath.Equals(path)) {
return tag;
}
}
return nsnull;
}
namespace {
PRInt64 GetPluginLastModifiedTime(const nsCOMPtr<nsIFile>& localfile)
{
PRInt64 fileModTime = LL_ZERO;
#if defined(XP_MACOSX)
// On OS X the date of a bundle's "contents" (i.e. of its Info.plist file)
// is a much better guide to when it was last modified than the date of
// its package directory. See bug 313700.
nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(localfile);
if (localFileMac) {
localFileMac->GetBundleContentsLastModifiedTime(&fileModTime);
} else {
localfile->GetLastModifiedTime(&fileModTime);
}
#else
localfile->GetLastModifiedTime(&fileModTime);
#endif
return fileModTime;
}
struct CompareFilesByTime
{
bool
LessThan(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
{
return LL_CMP(GetPluginLastModifiedTime(a), <, GetPluginLastModifiedTime(b));
}
bool
Equals(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
{
return LL_EQ(GetPluginLastModifiedTime(a), GetPluginLastModifiedTime(b));
}
};
} // anonymous namespace
typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
@ -1991,9 +2053,11 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
}
}
pluginFiles.Sort(CompareFilesByTime());
bool warnOutdated = false;
for (PRUint32 i = 0; i < pluginFiles.Length(); i++) {
for (PRInt32 i = (pluginFiles.Length() - 1); i >= 0; i--) {
nsCOMPtr<nsIFile>& localfile = pluginFiles[i];
nsString utf16FilePath;
@ -2001,21 +2065,8 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
if (NS_FAILED(rv))
continue;
PRInt64 fileModTime = LL_ZERO;
#if defined(XP_MACOSX)
// On OS X the date of a bundle's "contents" (i.e. of its Info.plist file)
// is a much better guide to when it was last modified than the date of
// its package directory. See bug 313700.
nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(localfile);
if (localFileMac) {
localFileMac->GetBundleContentsLastModifiedTime(&fileModTime);
} else {
localfile->GetLastModifiedTime(&fileModTime);
}
#else
localfile->GetLastModifiedTime(&fileModTime);
#endif
PRInt64 fileModTime = GetPluginLastModifiedTime(localfile);
// Look for it in our cache
NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
nsRefPtr<nsPluginTag> pluginTag;
@ -2146,6 +2197,21 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
// We have a valid new plugin so report that plugins have changed.
*aPluginsChanged = true;
}
// Avoid adding different versions of the same plugin if they are running
// in-process, otherwise we risk undefined behaviour.
if (!nsNPAPIPlugin::RunPluginOOP(pluginTag)) {
if (nsPluginTag *duplicate = HaveSamePlugin(pluginTag)) {
continue;
}
}
// Don't add the same plugin again if it hasn't changed
if (nsPluginTag* duplicate = FirstPluginWithPath(pluginTag->mFullPath)) {
if (LL_EQ(pluginTag->mLastModifiedTime, duplicate->mLastModifiedTime)) {
continue;
}
}
// If we're not creating a plugin list, simply looking for changes,
// then we're done.

View File

@ -267,6 +267,12 @@ private:
// Checks to see if a tag object is in our list of live tags.
bool IsLiveTag(nsIPluginTag* tag);
// Checks our list of live tags for an equivalent tag.
nsPluginTag* HaveSamePlugin(const nsPluginTag * aPluginTag);
// Returns the first plugin at |path|
nsPluginTag* FirstPluginWithPath(const nsCString& path);
nsresult EnsurePrivateDirServiceProvider();

View File

@ -379,6 +379,25 @@ bool nsPluginTag::IsEnabled()
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
}
bool
nsPluginTag::HasSameNameAndMimes(const nsPluginTag *aPluginTag) const
{
NS_ENSURE_TRUE(aPluginTag, false);
if ((!mName.Equals(aPluginTag->mName)) ||
(mMimeTypes.Length() != aPluginTag->mMimeTypes.Length())) {
return false;
}
for (PRUint32 i = 0; i < mMimeTypes.Length(); i++) {
if (!mMimeTypes[i].Equals(aPluginTag->mMimeTypes[i])) {
return false;
}
}
return true;
}
void nsPluginTag::TryUnloadPlugin(bool inShutdown)
{
// We never want to send NPP_Shutdown to an in-process plugin unless

View File

@ -58,6 +58,7 @@ public:
void UnMark(PRUint32 mask);
bool HasFlag(PRUint32 flag);
PRUint32 Flags();
bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
bool IsEnabled();
nsRefPtr<nsPluginTag> mNext;

View File

@ -1922,7 +1922,7 @@ bool
PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
NPRemoteWindow& aRemoteWindow)
{
aRemoteWindow.window = nsnull;
aRemoteWindow.window = 0;
aRemoteWindow.x = aWindow->x;
aRemoteWindow.y = aWindow->y;
aRemoteWindow.width = aWindow->width;

View File

@ -140,17 +140,17 @@ function RILContentHelper() {
this.initMessageListener(RIL_IPC_MSG_NAMES);
Services.obs.addObserver(this, "xpcom-shutdown", false);
// Request initial state.
let radioState = cpmm.QueryInterface(Ci.nsISyncMessageSender)
.sendSyncMessage("RIL:GetRadioState")[0];
// Request initial context.
let rilContext = cpmm.QueryInterface(Ci.nsISyncMessageSender)
.sendSyncMessage("RIL:GetRilContext")[0];
if (!radioState) {
debug("Received null radioState from chrome process.");
if (!rilContext) {
debug("Received null rilContext from chrome process.");
return;
}
this.cardState = radioState.cardState;
this.updateConnectionInfo(radioState.voice, this.voiceConnectionInfo);
this.updateConnectionInfo(radioState.data, this.dataConnectionInfo);
this.cardState = rilContext.cardState;
this.updateConnectionInfo(rilContext.voice, this.voiceConnectionInfo);
this.updateConnectionInfo(rilContext.data, this.dataConnectionInfo);
}
RILContentHelper.prototype = {

View File

@ -60,6 +60,7 @@ let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
let RILQUIRKS_V5_LEGACY = true;
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false;
let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false;
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false;
/**
* This object contains helpers buffering incoming data & deconstructing it
@ -727,6 +728,10 @@ let RIL = {
case "Qualcomm RIL 1.0":
let product_model = libcutils.property_get("ro.product.model");
if (DEBUG) debug("Detected product model " + product_model);
if (product_model == "otoro1") {
if (DEBUG) debug("Enabling RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS.");
RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = true;
}
if (DEBUG) {
debug("Detected Qualcomm RIL 1.0, " +
"disabling RILQUIRKS_V5_LEGACY and " +
@ -2825,6 +2830,12 @@ RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
pin1: Buf.readUint32(),
pin2: Buf.readUint32()
});
if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
Buf.readUint32();
Buf.readUint32();
Buf.readUint32();
Buf.readUint32();
}
}
if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));

View File

@ -7,7 +7,9 @@
#include "nsEditor.h"
#include "IMETextTxn.h"
#include "nsGkAtoms.h"
#include "nsISelection.h"
#include "mozilla/Selection.h"
using namespace mozilla;
PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(),
mAbsorb(true),
@ -42,7 +44,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
NS_IMPL_RELEASE_INHERITED(PlaceholderTxn, EditAggregateTxn)
NS_IMETHODIMP PlaceholderTxn::Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)
NS_IMETHODIMP
PlaceholderTxn::Init(nsIAtom* aName, nsSelectionState* aSelState,
nsEditor* aEditor)
{
NS_ENSURE_TRUE(aEditor && aSelState, NS_ERROR_NULL_POINTER);
@ -256,10 +260,9 @@ NS_IMETHODIMP PlaceholderTxn::Commit()
NS_IMETHODIMP PlaceholderTxn::RememberEndingSelection()
{
nsCOMPtr<nsISelection> selection;
nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = mEditor->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
return mEndSel.SaveSelection(selection);
mEndSel.SaveSelection(selection);
return NS_OK;
}

View File

@ -44,7 +44,8 @@ public:
// ------------ nsIAbsorbingTransaction -----------------------
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor);
NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
nsEditor* aEditor);
NS_IMETHOD GetTxnName(nsIAtom **aName);
@ -72,7 +73,7 @@ protected:
// selection properly.
nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist
nsSelectionState mEndSel;
nsIEditor* mEditor; /** the editor for this transaction */
nsEditor* mEditor; /** the editor for this transaction */
};

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html contenteditable="true">
<head>
<script>
function boom()
{
document.execCommand("inserthtml", false, "b");
var myrange = document.createRange();
myrange.selectNodeContents(document.getElementsByTagName("img")[0]);
window.getSelection().addRange(myrange);
document.execCommand("strikethrough", false, null);
}
</script>
</head>
<body onload="boom();"><img></body>
</html>

View File

@ -17,3 +17,4 @@ load 766845.xhtml
load 768765.html
needs-focus load 771749.html
load 772282.html
load 776323.html

View File

@ -904,9 +904,8 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
BeginUpdateViewBatch();
mPlaceHolderTxn = nsnull;
mPlaceHolderName = aName;
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(res)) {
nsRefPtr<Selection> selection = GetSelection();
if (selection) {
mSelState = new nsSelectionState();
mSelState->SaveSelection(selection);
}
@ -1979,7 +1978,7 @@ nsEditor::ArePreservingSelection()
}
void
nsEditor::PreserveSelectionAcrossActions(nsISelection *aSel)
nsEditor::PreserveSelectionAcrossActions(Selection* aSel)
{
mSavedSel.SaveSelection(aSel);
mRangeUpdater.RegisterSelectionState(mSavedSel);

View File

@ -425,7 +425,7 @@ public:
/** routines for managing the preservation of selection across
* various editor actions */
bool ArePreservingSelection();
void PreserveSelectionAcrossActions(nsISelection *aSel);
void PreserveSelectionAcrossActions(mozilla::Selection* aSel);
nsresult RestorePreservedSelection(nsISelection *aSel);
void StopPreservingSelection();

View File

@ -3,7 +3,7 @@
* 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 "mozilla/Selection.h"
#include "nsCOMArray.h"
#include "nsComponentManagerUtils.h"
#include "nsEditorUtils.h"
@ -18,24 +18,23 @@
#include "nsIDocument.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsINode.h"
#include "nsISelection.h"
#include "nsISimpleEnumerator.h"
class nsIDOMRange;
class nsISupports;
using namespace mozilla;
/******************************************************************************
* nsAutoSelectionReset
*****************************************************************************/
nsAutoSelectionReset::nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd) :
mSel(nsnull)
,mEd(nsnull)
nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd)
: mSel(nsnull), mEd(nsnull)
{
if (!aSel || !aEd) return; // not much we can do, bail.
if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
mSel = do_QueryInterface(aSel);
mSel = aSel;
mEd = aEd;
if (mSel)
{

View File

@ -57,12 +57,12 @@ class NS_STACK_CLASS nsAutoSelectionReset
{
private:
/** ref-counted reference to the selection that we are supposed to restore */
nsCOMPtr<nsISelection> mSel;
nsRefPtr<mozilla::Selection> mSel;
nsEditor *mEd; // non-owning ref to nsEditor
public:
/** constructor responsible for remembering all state needed to restore aSel */
nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd);
nsAutoSelectionReset(mozilla::Selection* aSel, nsEditor* aEd);
/** destructor restores mSel to its former state */
~nsAutoSelectionReset();

View File

@ -32,7 +32,8 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID)
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)=0;
NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
nsEditor* aEditor) = 0;
NS_IMETHOD EndPlaceHolderBatch()=0;

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Selection.h" // for Selection
#include "nsAString.h" // for nsAString_internal::Length
#include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc
#include "nsCycleCollectionParticipant.h"
@ -19,6 +20,7 @@
#include "nsRange.h" // for nsRange
#include "nsSelectionState.h"
using namespace mozilla;
/***************************************************************************
* class for recording selection info. stores selection as collection of
@ -47,43 +49,30 @@ nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
}
}
nsresult
nsSelectionState::SaveSelection(nsISelection *aSel)
void
nsSelectionState::SaveSelection(Selection* aSel)
{
NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
PRInt32 i,rangeCount, arrayCount = mArray.Length();
aSel->GetRangeCount(&rangeCount);
MOZ_ASSERT(aSel);
PRInt32 arrayCount = mArray.Length();
PRInt32 rangeCount = aSel->GetRangeCount();
// if we need more items in the array, new them
if (arrayCount<rangeCount)
{
PRInt32 count = rangeCount-arrayCount;
for (i=0; i<count; i++)
{
if (arrayCount < rangeCount) {
for (PRInt32 i = arrayCount; i < rangeCount; i++) {
mArray.AppendElement();
mArray[i] = new nsRangeStore();
}
}
// else if we have too many, delete them
else if (arrayCount>rangeCount)
{
for (i = arrayCount-1; i >= rangeCount; i--)
{
} else if (arrayCount > rangeCount) {
// else if we have too many, delete them
for (PRInt32 i = arrayCount - 1; i >= rangeCount; i--) {
mArray.RemoveElementAt(i);
}
}
// now store the selection ranges
nsresult res = NS_OK;
for (i=0; i<rangeCount; i++)
{
nsCOMPtr<nsIDOMRange> range;
res = aSel->GetRangeAt(i, getter_AddRefs(range));
mArray[i]->StoreRange(range);
for (PRInt32 i = 0; i < rangeCount; i++) {
mArray[i]->StoreRange(aSel->GetRangeAt(i));
}
return res;
}
nsresult

View File

@ -18,6 +18,9 @@ class nsIDOMCharacterData;
class nsIDOMRange;
class nsISelection;
class nsRange;
namespace mozilla {
class Selection;
}
/***************************************************************************
* class for recording selection info. stores selection as collection of
@ -52,7 +55,7 @@ class nsSelectionState
void DoTraverse(nsCycleCollectionTraversalCallback &cb);
void DoUnlink() { MakeEmpty(); }
nsresult SaveSelection(nsISelection *aSel);
void SaveSelection(mozilla::Selection *aSel);
nsresult RestoreSelection(nsISelection *aSel);
bool IsCollapsed();
bool IsEqual(nsSelectionState *aSelState);

View File

@ -2869,7 +2869,7 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection,
}
nsresult
nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
nsHTMLEditRules::WillMakeList(Selection* aSelection,
const nsAString* aListType,
bool aEntireList,
const nsAString* aBulletType,
@ -3159,7 +3159,7 @@ nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
nsresult
nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
nsHTMLEditRules::WillRemoveList(Selection* aSelection,
bool aOrdered,
bool *aCancel,
bool *aHandled)
@ -3226,7 +3226,7 @@ nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
nsresult
nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection,
nsHTMLEditRules::WillMakeDefListItem(Selection* aSelection,
const nsAString *aItemType,
bool aEntireList,
bool *aCancel,
@ -3238,7 +3238,7 @@ nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection,
}
nsresult
nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection,
nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
const nsAString *aBlockType,
bool *aCancel,
bool *aHandled)
@ -3395,7 +3395,8 @@ nsHTMLEditRules::DidMakeBasicBlock(nsISelection *aSelection,
}
nsresult
nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
nsHTMLEditRules::WillIndent(Selection* aSelection,
bool* aCancel, bool* aHandled)
{
nsresult res;
if (mHTMLEditor->IsCSSEnabled()) {
@ -3408,7 +3409,8 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHan
}
nsresult
nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
nsHTMLEditRules::WillCSSIndent(Selection* aSelection,
bool* aCancel, bool* aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
@ -3614,7 +3616,8 @@ nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * a
}
nsresult
nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
nsHTMLEditRules::WillHTMLIndent(Selection* aSelection,
bool* aCancel, bool* aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
@ -3842,7 +3845,8 @@ nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *
nsresult
nsHTMLEditRules::WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled)
nsHTMLEditRules::WillOutdent(Selection* aSelection,
bool* aCancel, bool* aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
@ -4412,7 +4416,7 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
nsresult
nsHTMLEditRules::WillAlign(nsISelection *aSelection,
nsHTMLEditRules::WillAlign(Selection* aSelection,
const nsAString *alignType,
bool *aCancel,
bool *aHandled)
@ -8570,7 +8574,8 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt
//
nsresult
nsHTMLEditRules::WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
nsHTMLEditRules::WillAbsolutePosition(Selection* aSelection,
bool* aCancel, bool* aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
@ -8786,8 +8791,8 @@ nsHTMLEditRules::DidAbsolutePosition()
}
nsresult
nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
{
nsHTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
bool* aCancel, bool* aHandled) {
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
NS_ENSURE_SUCCESS(res, res);
@ -8808,7 +8813,7 @@ nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCan
}
nsresult
nsHTMLEditRules::WillRelativeChangeZIndex(nsISelection *aSelection,
nsHTMLEditRules::WillRelativeChangeZIndex(Selection* aSelection,
PRInt32 aChange,
bool *aCancel,
bool * aHandled)

View File

@ -156,18 +156,38 @@ protected:
nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
nsresult DeleteNonTableElements(nsINode* aNode);
nsresult WillMakeList(nsISelection *aSelection, const nsAString *aListType, bool aEntireList, const nsAString *aBulletType, bool *aCancel, bool *aHandled, const nsAString *aItemType=nsnull);
nsresult WillRemoveList(nsISelection *aSelection, bool aOrderd, bool *aCancel, bool *aHandled);
nsresult WillIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
nsresult WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
nsresult WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
nsresult WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
nsresult WillAlign(nsISelection *aSelection, const nsAString *alignType, bool *aCancel, bool *aHandled);
nsresult WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
nsresult WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
nsresult WillRelativeChangeZIndex(nsISelection *aSelection, PRInt32 aChange, bool *aCancel, bool * aHandled);
nsresult WillMakeDefListItem(nsISelection *aSelection, const nsAString *aBlockType, bool aEntireList, bool *aCancel, bool *aHandled);
nsresult WillMakeBasicBlock(nsISelection *aSelection, const nsAString *aBlockType, bool *aCancel, bool *aHandled);
nsresult WillMakeList(mozilla::Selection* aSelection,
const nsAString* aListType,
bool aEntireList,
const nsAString* aBulletType,
bool* aCancel, bool* aHandled,
const nsAString* aItemType = nsnull);
nsresult WillRemoveList(mozilla::Selection* aSelection,
bool aOrdered, bool* aCancel, bool* aHandled);
nsresult WillIndent(mozilla::Selection* aSelection,
bool* aCancel, bool* aHandled);
nsresult WillCSSIndent(mozilla::Selection* aSelection,
bool* aCancel, bool* aHandled);
nsresult WillHTMLIndent(mozilla::Selection* aSelection,
bool* aCancel, bool* aHandled);
nsresult WillOutdent(mozilla::Selection* aSelection,
bool* aCancel, bool* aHandled);
nsresult WillAlign(mozilla::Selection* aSelection,
const nsAString* alignType,
bool* aCancel, bool* aHandled);
nsresult WillAbsolutePosition(mozilla::Selection* aSelection,
bool* aCancel, bool* aHandled);
nsresult WillRemoveAbsolutePosition(mozilla::Selection* aSelection,
bool* aCancel, bool* aHandled);
nsresult WillRelativeChangeZIndex(mozilla::Selection* aSelection,
PRInt32 aChange,
bool* aCancel, bool* aHandled);
nsresult WillMakeDefListItem(mozilla::Selection* aSelection,
const nsAString* aBlockType, bool aEntireList,
bool* aCancel, bool* aHandled);
nsresult WillMakeBasicBlock(mozilla::Selection* aSelection,
const nsAString* aBlockType,
bool* aCancel, bool* aHandled);
nsresult DidMakeBasicBlock(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
nsresult DidAbsolutePosition();
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType);

View File

@ -3379,15 +3379,13 @@ SetSelectionAroundHeadChildren(nsISelection* aSelection,
NS_IMETHODIMP
nsHTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
{
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// Save current selection
nsAutoSelectionReset selectionResetter(selection, this);
res = SetSelectionAroundHeadChildren(selection, mDocWeak);
nsresult res = SetSelectionAroundHeadChildren(selection, mDocWeak);
NS_ENSURE_SUCCESS(res, res);
res = OutputToString(NS_LITERAL_STRING("text/html"),

View File

@ -1535,11 +1535,8 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
ForceCompositionEnd();
// Get the selection
nsCOMPtr<nsISelection>selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
// Is the selection collapsed?
// if it's collapsed set typing state
if (selection->Collapsed()) {
@ -1554,7 +1551,7 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
NS_ENSURE_TRUE(selectedNode, NS_OK);
if (IsTextNode(selectedNode)) {
nsCOMPtr<nsIDOMNode> parent;
res = selectedNode->GetParentNode(getter_AddRefs(parent));
nsresult res = selectedNode->GetParentNode(getter_AddRefs(parent));
NS_ENSURE_SUCCESS(res, res);
selectedNode = parent;
}
@ -1575,7 +1572,7 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
// get selection range enumerator
nsCOMPtr<nsIEnumerator> enumerator;
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
nsresult res = selection->GetEnumerator(getter_AddRefs(enumerator));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);

View File

@ -6,6 +6,7 @@
#include <stdio.h>
#include "mozilla/Assertions.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Element.h"
#include "nsAString.h"
#include "nsAlgorithm.h"
@ -28,8 +29,6 @@
#include "nsIHTMLEditor.h"
#include "nsINode.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsISelectionPrivate.h" // For nsISelectionPrivate::TABLESELECTION_ defines
#include "nsISupportsUtils.h"
#include "nsITableCellLayout.h" // For efficient access to table cell
#include "nsITableEditor.h"
@ -1953,9 +1952,7 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
// Save current selection to restore when done
// This is needed so ReplaceContainer can monitor selection
// when replacing nodes
nsCOMPtr<nsISelection>selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
nsAutoSelectionReset selectionResetter(selection, this);
@ -1965,7 +1962,8 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
// This creates new node, moves children, copies attributes (true)
// and manages the selection!
res = ReplaceContainer(aSourceCell, address_of(newNode), newCellType, nsnull, nsnull, true);
nsresult res = ReplaceContainer(aSourceCell, address_of(newNode),
newCellType, nsnull, nsnull, true);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
@ -2491,13 +2489,12 @@ nsHTMLEditor::FixBadColSpan(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32& a
NS_IMETHODIMP
nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
{
nsCOMPtr<nsISelection>selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"),
aTable, getter_AddRefs(table));
NS_ENSURE_SUCCESS(res, res);
// Don't fail if we didn't find a table
NS_ENSURE_TRUE(table, NS_OK);

View File

@ -583,6 +583,13 @@ nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
{
// the nativeHandle should be accessed from nsIXULWindow
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetVisibility(bool* aVisibility)
{

View File

@ -1378,6 +1378,12 @@ NS_IMETHODIMP nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWind
return NS_OK;
}
NS_IMETHODIMP nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle)
{
// the nativeHandle should be accessed from nsIXULWindow
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsWebBrowser::GetVisibility(bool* visibility)
{
NS_ENSURE_ARG_POINTER(visibility);

View File

@ -303,11 +303,13 @@ nsresult
nsPermissionManager::InitDB(bool aRemoveFile)
{
nsCOMPtr<nsIFile> permissionsFile;
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
if (!permissionsFile)
return NS_ERROR_UNEXPECTED;
nsresult rv = NS_GetSpecialDirectory(NS_APP_PERMISSION_PARENT_DIR, getter_AddRefs(permissionsFile));
if (NS_FAILED(rv)) {
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
nsresult rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
NS_ENSURE_SUCCESS(rv, rv);
if (aRemoveFile) {

View File

@ -182,6 +182,8 @@ avoid-extend-none.patch: Avoid incorrectly using EXTEND_NONE (bug 751668)
win32-ExtCreatePen-zero-size.patch: Don't pass zero width or dash lengths to ExtCreatePen (bug 768348)
d2d-repeating-gradients.patch: Minimize number of gradient stops added to handle repeating with path fills (bug 768775)
==== pixman patches ====
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.

View File

@ -1416,7 +1416,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
// Find the corner furthest away from the gradient center in pattern space.
double largest = MAX(_cairo_d2d_point_dist(top_left, gradient_center), _cairo_d2d_point_dist(top_right, gradient_center));
@ -1536,6 +1536,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
static RefPtr<ID2D1Brush>
_cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
cairo_path_fixed_t *fill_path,
cairo_linear_pattern_t *source_pattern)
{
if (source_pattern->p1.x == source_pattern->p2.x &&
@ -1569,25 +1570,36 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
D2D1_GRADIENT_STOP *stops;
int num_stops = source_pattern->base.n_stops;
if (source_pattern->base.base.extend == CAIRO_EXTEND_REPEAT || source_pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
RefPtr<IDXGISurface> surf;
d2dsurf->surface->QueryInterface(&surf);
DXGI_SURFACE_DESC desc;
surf->GetDesc(&desc);
// Get this when the points are not transformed yet.
double gradient_length = _cairo_d2d_point_dist(p1, p2);
cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
if (fill_path) {
// Calculate the repeat count needed;
cairo_box_t fill_extents;
_cairo_path_fixed_extents (fill_path, &fill_extents);
top_left.x = bottom_left.x = _cairo_fixed_to_double (fill_extents.p1.x);
top_left.y = top_right.y = _cairo_fixed_to_double (fill_extents.p1.y);
top_right.x = bottom_right.x = _cairo_fixed_to_double (fill_extents.p2.x);
bottom_right.y = bottom_left.y = _cairo_fixed_to_double (fill_extents.p2.y);
} else {
RefPtr<IDXGISurface> surf;
d2dsurf->surface->QueryInterface(&surf);
DXGI_SURFACE_DESC desc;
surf->GetDesc(&desc);
top_left.x = bottom_left.x = 0;
top_left.y = top_right.y = 0;
top_right.x = bottom_right.x = desc.Width;
bottom_right.y = bottom_left.y = desc.Height;
}
// Calculate the repeat count needed;
cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
top_left.x = bottom_left.x = top_left.y = top_right.y = 0;
top_right.x = bottom_right.x = desc.Width;
bottom_right.y = bottom_left.y = desc.Height;
// Transform the corners of our surface to pattern space.
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
cairo_point_double_t u;
// Unit vector of the gradient direction.
@ -1706,7 +1718,8 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
* \return A brush object
*/
static RefPtr<ID2D1Brush>
_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
cairo_path_fixed_t *fill_path,
const cairo_pattern_t *pattern,
bool unique = false)
{
@ -1734,7 +1747,7 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
} else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
cairo_linear_pattern_t *source_pattern =
(cairo_linear_pattern_t*)pattern;
return _cairo_d2d_create_linear_gradient_brush(d2dsurf, source_pattern);
return _cairo_d2d_create_linear_gradient_brush(d2dsurf, fill_path, source_pattern);
} else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
cairo_radial_pattern_t *source_pattern =
(cairo_radial_pattern_t*)pattern;
@ -3233,7 +3246,7 @@ _cairo_d2d_paint(void *surface,
target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
source);
if (!brush) {
@ -3354,7 +3367,7 @@ _cairo_d2d_mask(void *surface,
}
}
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -3394,7 +3407,7 @@ _cairo_d2d_mask(void *surface,
return CAIRO_INT_STATUS_SUCCESS;
}
RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, mask, true);
RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, mask, true);
if (!opacityBrush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -3480,7 +3493,7 @@ _cairo_d2d_stroke(void *surface,
transformed = false;
}
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -3607,7 +3620,7 @@ _cairo_d2d_fill(void *surface,
float x2 = _cairo_fixed_to_float(box.p2.x);
float y2 = _cairo_fixed_to_float(box.p2.y);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
source);
path, source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -3621,7 +3634,7 @@ _cairo_d2d_fill(void *surface,
RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
source);
path, source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -4143,7 +4156,7 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
fontArea.height = bounds.bottom - bounds.top;
}
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst, NULL,
source);
if (!brush) {

View File

@ -0,0 +1,271 @@
From: Robert O'Callahan <robert@ocallahan.org>
Bug 768775. Improve the precision of the calculation of the number of stops that need to be added to handle 'repeat' and 'reflect', when we're filling a path. r=bas
diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -1411,17 +1411,17 @@ static RefPtr<ID2D1Brush>
gradient_center.x = _cairo_fixed_to_float(source_pattern->c1.x);
gradient_center.y = _cairo_fixed_to_float(source_pattern->c1.y);
// Transform surface corners into pattern coordinates.
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
- cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
+ cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
// Find the corner furthest away from the gradient center in pattern space.
double largest = MAX(_cairo_d2d_point_dist(top_left, gradient_center), _cairo_d2d_point_dist(top_right, gradient_center));
largest = MAX(largest, _cairo_d2d_point_dist(bottom_left, gradient_center));
largest = MAX(largest, _cairo_d2d_point_dist(bottom_right, gradient_center));
unsigned int minSize = (unsigned int)ceil(largest);
@@ -1531,16 +1531,17 @@ static RefPtr<ID2D1Brush>
stopCollection,
&brush);
delete [] stops;
return brush;
}
static RefPtr<ID2D1Brush>
_cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
+ cairo_path_fixed_t *fill_path,
cairo_linear_pattern_t *source_pattern)
{
if (source_pattern->p1.x == source_pattern->p2.x &&
source_pattern->p1.y == source_pattern->p2.y) {
// Cairo behavior in this situation is to draw a solid color the size of the last stop.
RefPtr<ID2D1SolidColorBrush> brush;
d2dsurf->rt->CreateSolidColorBrush(
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
@@ -1564,35 +1565,46 @@ static RefPtr<ID2D1Brush>
p1.x = _cairo_fixed_to_float(source_pattern->p1.x);
p1.y = _cairo_fixed_to_float(source_pattern->p1.y);
p2.x = _cairo_fixed_to_float(source_pattern->p2.x);
p2.y = _cairo_fixed_to_float(source_pattern->p2.y);
D2D1_GRADIENT_STOP *stops;
int num_stops = source_pattern->base.n_stops;
if (source_pattern->base.base.extend == CAIRO_EXTEND_REPEAT || source_pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
-
- RefPtr<IDXGISurface> surf;
- d2dsurf->surface->QueryInterface(&surf);
- DXGI_SURFACE_DESC desc;
- surf->GetDesc(&desc);
-
// Get this when the points are not transformed yet.
double gradient_length = _cairo_d2d_point_dist(p1, p2);
-
- // Calculate the repeat count needed;
- cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
- top_left.x = bottom_left.x = top_left.y = top_right.y = 0;
- top_right.x = bottom_right.x = desc.Width;
- bottom_right.y = bottom_left.y = desc.Height;
+ cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
+
+ if (fill_path) {
+ // Calculate the repeat count needed;
+ cairo_box_t fill_extents;
+ _cairo_path_fixed_extents (fill_path, &fill_extents);
+
+ top_left.x = bottom_left.x = _cairo_fixed_to_double (fill_extents.p1.x);
+ top_left.y = top_right.y = _cairo_fixed_to_double (fill_extents.p1.y);
+ top_right.x = bottom_right.x = _cairo_fixed_to_double (fill_extents.p2.x);
+ bottom_right.y = bottom_left.y = _cairo_fixed_to_double (fill_extents.p2.y);
+ } else {
+ RefPtr<IDXGISurface> surf;
+ d2dsurf->surface->QueryInterface(&surf);
+ DXGI_SURFACE_DESC desc;
+ surf->GetDesc(&desc);
+
+ top_left.x = bottom_left.x = 0;
+ top_left.y = top_right.y = 0;
+ top_right.x = bottom_right.x = desc.Width;
+ bottom_right.y = bottom_left.y = desc.Height;
+ }
+
// Transform the corners of our surface to pattern space.
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
- cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
+ cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
cairo_point_double_t u;
// Unit vector of the gradient direction.
u = _cairo_d2d_subtract_point(p2, p1);
_cairo_d2d_normalize_point(&u);
// (corner - p1) . u = |corner - p1| cos(a) where a is the angle between the two vectors.
// Coincidentally |corner - p1| cos(a) is actually also the distance our gradient needs to cover since
@@ -1701,17 +1713,18 @@ static RefPtr<ID2D1Brush>
* \param d2dsurf Surface to create a brush for
* \param pattern The pattern to create a brush for
* \param unique We cache the bitmap/color brush for speed. If this
* needs a brush that is unique (i.e. when more than one is needed),
* this will make the function return a seperate brush.
* \return A brush object
*/
static RefPtr<ID2D1Brush>
-_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
+_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
+ cairo_path_fixed_t *fill_path,
const cairo_pattern_t *pattern,
bool unique = false)
{
HRESULT hr;
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
cairo_solid_pattern_t *sourcePattern =
(cairo_solid_pattern_t*)pattern;
@@ -1729,17 +1742,17 @@ static RefPtr<ID2D1Brush>
d2dsurf->solidColorBrush->SetColor(color);
}
return d2dsurf->solidColorBrush;
}
} else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
cairo_linear_pattern_t *source_pattern =
(cairo_linear_pattern_t*)pattern;
- return _cairo_d2d_create_linear_gradient_brush(d2dsurf, source_pattern);
+ return _cairo_d2d_create_linear_gradient_brush(d2dsurf, fill_path, source_pattern);
} else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
cairo_radial_pattern_t *source_pattern =
(cairo_radial_pattern_t*)pattern;
return _cairo_d2d_create_radial_gradient_brush(d2dsurf, source_pattern);
} else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_matrix_t mat = pattern->matrix;
cairo_matrix_invert(&mat);
@@ -3228,17 +3241,17 @@ static cairo_int_status_t
if (unlikely(status))
return status;
}
#endif
target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
D2D1_SIZE_F size = target_rt->GetSize();
target_rt->FillRectangle(D2D1::RectF((FLOAT)0,
@@ -3349,17 +3362,17 @@ static cairo_int_status_t
source->filter,
solidAlphaValue);
if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
return rv;
}
}
}
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source);
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
RefPtr<ID2D1RenderTarget> target_rt = d2dsurf->rt;
#ifndef ALWAYS_MANUAL_COMPOSITE
if (op != CAIRO_OPERATOR_OVER) {
#endif
@@ -3389,17 +3402,17 @@ static cairo_int_status_t
brush->SetOpacity(1.0);
if (target_rt.get() != d2dsurf->rt.get()) {
return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip);
}
return CAIRO_INT_STATUS_SUCCESS;
}
- RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, mask, true);
+ RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, mask, true);
if (!opacityBrush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (!d2dsurf->maskLayer) {
d2dsurf->rt->CreateLayer(&d2dsurf->maskLayer);
}
target_rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(),
@@ -3475,17 +3488,17 @@ static cairo_int_status_t
D2D1_FIGURE_BEGIN_FILLED);
bool transformed = true;
if (_cairo_matrix_is_identity(ctm)) {
transformed = false;
}
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
D2D1::Matrix3x2F mat;
if (transformed) {
// If we are transformed we will draw the geometry multiplied by the
@@ -3602,31 +3615,31 @@ static cairo_int_status_t
}
if (is_box) {
float x1 = _cairo_fixed_to_float(box.p1.x);
float y1 = _cairo_fixed_to_float(box.p1.y);
float x2 = _cairo_fixed_to_float(box.p2.x);
float y2 = _cairo_fixed_to_float(box.p2.y);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
- source);
+ path, source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
target_rt->FillRectangle(D2D1::RectF(x1,
y1,
x2,
y2),
brush);
} else {
RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
- source);
+ path, source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
target_rt->FillGeometry(d2dpath, brush);
}
if (target_rt.get() != d2dsurf->rt.get()) {
double x1, y1, x2, y2;
@@ -4138,17 +4151,17 @@ static cairo_int_status_t
DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1,
&bounds);
fontArea.x = bounds.left;
fontArea.y = bounds.top;
fontArea.width = bounds.right - bounds.left;
fontArea.height = bounds.bottom - bounds.top;
}
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst, NULL,
source);
if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (transform) {
D2D1::Matrix3x2F mat_inverse = _cairo_d2d_matrix_from_matrix(&dwritesf->mat_inverse);

View File

@ -888,10 +888,10 @@ SharedTextureHandle
GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
{
if (aType != TextureImage::ThreadShared)
return nsnull;
return 0;
if (!mShareWithEGLImage)
return nsnull;
return 0;
MakeCurrent();
GLuint texture = 0;
@ -903,7 +903,7 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
if (!tex->CreateEGLImage()) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
ReleaseSharedHandle(aType, (SharedTextureHandle)tex);
return nsnull;
return 0;
}
// Raw pointer shared across threads
return (SharedTextureHandle)tex;
@ -917,35 +917,35 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType,
// Both EGLImage and SurfaceTexture only support ThreadShared currently, but
// it's possible to make SurfaceTexture work across processes. We should do that.
if (aType != TextureImage::ThreadShared)
return nsnull;
return 0;
switch (aBufferType) {
#ifdef MOZ_WIDGET_ANDROID
case SharedTextureBufferType::SurfaceTexture:
if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) {
NS_WARNING("Missing GL_OES_EGL_image_external");
return nsnull;
return 0;
}
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(aBuffer));
#endif
case SharedTextureBufferType::TextureID: {
if (!mShareWithEGLImage)
return nsnull;
return 0;
GLuint texture = (GLuint)aBuffer;
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture, false);
if (!tex->CreateEGLImage()) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
delete tex;
return nsnull;
return 0;
}
return (SharedTextureHandle)tex;
}
default:
NS_ERROR("Unknown shared texture buffer type");
return nsnull;
return 0;
}
}

View File

@ -17,6 +17,7 @@
#include "nsPrintfCString.h"
#include "mozilla/Util.h"
#include "LayerSorter.h"
#include "AnimationCommon.h"
using namespace mozilla::layers;
using namespace mozilla::gfx;
@ -220,6 +221,245 @@ LayerManager::CreateAsynchronousImageContainer()
//--------------------------------------------------
// Layer
Layer::Layer(LayerManager* aManager, void* aImplData) :
mManager(aManager),
mParent(nsnull),
mNextSibling(nsnull),
mPrevSibling(nsnull),
mImplData(aImplData),
mMaskLayer(nsnull),
mXScale(1.0f),
mYScale(1.0f),
mOpacity(1.0),
mContentFlags(0),
mUseClipRect(false),
mUseTileSourceRect(false),
mIsFixedPosition(false),
mDebugColorIndex(0)
{}
Layer::~Layer()
{}
void
Layer::AddAnimation(const Animation& aAnimation)
{
if (!AsShadowableLayer() || !AsShadowableLayer()->HasShadow())
return;
MOZ_ASSERT(aAnimation.segments().Length() >= 1);
mAnimations.AppendElement(aAnimation);
Mutated();
}
void
Layer::ClearAnimations()
{
mAnimations.Clear();
mAnimationData.Clear();
Mutated();
}
static nsCSSValueList*
CreateCSSValueList(const InfallibleTArray<TransformFunction>& aFunctions)
{
nsAutoPtr<nsCSSValueList> result;
nsCSSValueList** resultTail = getter_Transfers(result);
for (PRUint32 i = 0; i < aFunctions.Length(); i++) {
nsRefPtr<nsCSSValue::Array> arr;
switch (aFunctions[i].type()) {
case TransformFunction::TRotationX:
{
float theta = aFunctions[i].get_RotationX().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatex, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotationY:
{
float theta = aFunctions[i].get_RotationY().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatey, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotationZ:
{
float theta = aFunctions[i].get_RotationZ().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatez, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotation:
{
float theta = aFunctions[i].get_Rotation().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotation3D:
{
float x = aFunctions[i].get_Rotation3D().x();
float y = aFunctions[i].get_Rotation3D().y();
float z = aFunctions[i].get_Rotation3D().z();
float theta = aFunctions[i].get_Rotation3D().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate3d, resultTail);
arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
arr->Item(2).SetFloatValue(y, eCSSUnit_Number);
arr->Item(3).SetFloatValue(z, eCSSUnit_Number);
arr->Item(4).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TScale:
{
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_scale3d, resultTail);
arr->Item(1).SetFloatValue(aFunctions[i].get_Scale().x(), eCSSUnit_Number);
arr->Item(2).SetFloatValue(aFunctions[i].get_Scale().y(), eCSSUnit_Number);
arr->Item(3).SetFloatValue(aFunctions[i].get_Scale().z(), eCSSUnit_Number);
break;
}
case TransformFunction::TTranslation:
{
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_translate3d, resultTail);
arr->Item(1).SetFloatValue(aFunctions[i].get_Translation().x(), eCSSUnit_Pixel);
arr->Item(2).SetFloatValue(aFunctions[i].get_Translation().y(), eCSSUnit_Pixel);
arr->Item(3).SetFloatValue(aFunctions[i].get_Translation().z(), eCSSUnit_Pixel);
break;
}
case TransformFunction::TSkewX:
{
float x = aFunctions[i].get_SkewX().x();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewx, resultTail);
arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
break;
}
case TransformFunction::TSkewY:
{
float y = aFunctions[i].get_SkewY().y();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewy, resultTail);
arr->Item(1).SetFloatValue(y, eCSSUnit_Number);
break;
}
case TransformFunction::TTransformMatrix:
{
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_matrix3d, resultTail);
const gfx3DMatrix& matrix = aFunctions[i].get_TransformMatrix().value();
arr->Item(1).SetFloatValue(matrix._11, eCSSUnit_Number);
arr->Item(2).SetFloatValue(matrix._12, eCSSUnit_Number);
arr->Item(3).SetFloatValue(matrix._13, eCSSUnit_Number);
arr->Item(4).SetFloatValue(matrix._14, eCSSUnit_Number);
arr->Item(5).SetFloatValue(matrix._21, eCSSUnit_Number);
arr->Item(6).SetFloatValue(matrix._22, eCSSUnit_Number);
arr->Item(7).SetFloatValue(matrix._23, eCSSUnit_Number);
arr->Item(8).SetFloatValue(matrix._24, eCSSUnit_Number);
arr->Item(9).SetFloatValue(matrix._31, eCSSUnit_Number);
arr->Item(10).SetFloatValue(matrix._32, eCSSUnit_Number);
arr->Item(11).SetFloatValue(matrix._33, eCSSUnit_Number);
arr->Item(12).SetFloatValue(matrix._34, eCSSUnit_Number);
arr->Item(13).SetFloatValue(matrix._41, eCSSUnit_Number);
arr->Item(14).SetFloatValue(matrix._42, eCSSUnit_Number);
arr->Item(15).SetFloatValue(matrix._43, eCSSUnit_Number);
arr->Item(16).SetFloatValue(matrix._44, eCSSUnit_Number);
break;
}
case TransformFunction::TPerspective:
{
float perspective = aFunctions[i].get_Perspective().value();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_perspective, resultTail);
arr->Item(1).SetFloatValue(perspective, eCSSUnit_Pixel);
break;
}
default:
NS_ASSERTION(false, "All functions should be implemented?");
}
}
return result.forget();
}
void
Layer::SetAnimations(const AnimationArray& aAnimations)
{
mAnimations = aAnimations;
mAnimationData.Clear();
for (PRUint32 i = 0; i < mAnimations.Length(); i++) {
AnimData data;
InfallibleTArray<css::ComputedTimingFunction*>* functions =
&data.mFunctions;
nsTArray<AnimationSegment> segments = mAnimations.ElementAt(i).segments();
for (PRUint32 j = 0; j < segments.Length(); j++) {
TimingFunction tf = segments.ElementAt(j).sampleFn();
css::ComputedTimingFunction* ctf = new css::ComputedTimingFunction();
switch (tf.type()) {
case TimingFunction::TCubicBezierFunction: {
CubicBezierFunction cbf = tf.get_CubicBezierFunction();
ctf->Init(nsTimingFunction(cbf.x1(), cbf.y1(), cbf.x2(), cbf.y2()));
break;
}
default: {
NS_ASSERTION(tf.type() == TimingFunction::TStepFunction,
"Function must be bezier or step");
StepFunction sf = tf.get_StepFunction();
nsTimingFunction::Type type = sf.type() == 1 ? nsTimingFunction::StepStart
: nsTimingFunction::StepEnd;
ctf->Init(nsTimingFunction(type, sf.steps()));
break;
}
}
functions->AppendElement(ctf);
}
// Precompute the nsStyleAnimation::Values that we need if this is a transform
// animation.
InfallibleTArray<nsStyleAnimation::Value>* startValues =
&data.mStartValues;
InfallibleTArray<nsStyleAnimation::Value>* endValues =
&data.mEndValues;
for (PRUint32 j = 0; j < mAnimations[i].segments().Length(); j++) {
const AnimationSegment& segment = mAnimations[i].segments()[j];
if (segment.endState().type() == Animatable::TArrayOfTransformFunction) {
const InfallibleTArray<TransformFunction>& startFunctions =
segment.startState().get_ArrayOfTransformFunction();
nsStyleAnimation::Value startValue;
nsCSSValueList* startList;
if (startFunctions.Length() > 0) {
startList = CreateCSSValueList(startFunctions);
} else {
startList = new nsCSSValueList();
startList->mValue.SetNoneValue();
}
startValue.SetAndAdoptCSSValueListValue(startList, nsStyleAnimation::eUnit_Transform);
startValues->AppendElement(startValue);
const InfallibleTArray<TransformFunction>& endFunctions =
segment.endState().get_ArrayOfTransformFunction();
nsStyleAnimation::Value endValue;
nsCSSValueList* endList;
if (endFunctions.Length() > 0) {
endList = CreateCSSValueList(endFunctions);
} else {
endList = new nsCSSValueList();
endList->mValue.SetNoneValue();
}
endValue.SetAndAdoptCSSValueListValue(endList, nsStyleAnimation::eUnit_Transform);
endValues->AppendElement(endValue);
} else {
NS_ASSERTION(segment.endState().type() == Animatable::TOpacity,
"Unknown Animatable type");
nsStyleAnimation::Value startValue;
startValue.SetFloatValue(segment.startState().get_Opacity().value());
startValues->AppendElement(startValue);
nsStyleAnimation::Value endValue;
endValue.SetFloatValue(segment.endState().get_Opacity().value());
endValues->AppendElement(endValue);
}
}
mAnimationData.AppendElement(data);
}
Mutated();
}
bool
Layer::CanUseOpaqueSurface()
{
@ -304,7 +544,7 @@ Layer::SnapTransform(const gfx3DMatrix& aTransform,
return result;
}
nsIntRect
nsIntRect
Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
const gfxMatrix* aWorldTransform)
{
@ -361,21 +601,42 @@ Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
return currentClip.Intersect(scissor);
}
const gfx3DMatrix&
const gfx3DMatrix
Layer::GetTransform()
{
gfx3DMatrix transform = mTransform;
transform.Scale(mXScale, mYScale, 1);
return transform;
}
const gfx3DMatrix
Layer::GetLocalTransform()
{
gfx3DMatrix transform;
if (ShadowLayer* shadow = AsShadowLayer()) {
transform = shadow->GetShadowTransform();
} else {
transform = mTransform;
}
transform.Scale(mXScale, mYScale, 1);
return transform;
}
const float
Layer::GetLocalOpacity()
{
if (ShadowLayer* shadow = AsShadowLayer())
return shadow->GetShadowTransform();
return mTransform;
return shadow->GetShadowOpacity();
return mOpacity;
}
float
Layer::GetEffectiveOpacity()
{
float opacity = GetOpacity();
float opacity = GetLocalOpacity();
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
c = c->GetParent()) {
opacity *= c->GetOpacity();
opacity *= c->GetLocalOpacity();
}
return opacity;
}
@ -384,14 +645,15 @@ void
Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix& aTransformToSurface)
{
if (mMaskLayer) {
mMaskLayer->mEffectiveTransform = aTransformToSurface;
#ifdef DEBUG
gfxMatrix maskTranslation;
bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
#endif
mMaskLayer->mEffectiveTransform.PreMultiply(mMaskLayer->GetTransform());
mMaskLayer->mEffectiveTransform = aTransformToSurface;
#ifdef DEBUG
gfxMatrix maskTranslation;
bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
#endif
mMaskLayer->mEffectiveTransform.PreMultiply(mMaskLayer->GetTransform());
}
}
@ -790,7 +1052,7 @@ void
LayerManager::Dump(FILE* aFile, const char* aPrefix)
{
FILE* file = FILEOrDefault(aFile);
fprintf(file, "<ul><li><a ");
#ifdef MOZ_DUMP_PAINTING
WriteSnapshotLinkToDumpFile(this, file);
@ -807,7 +1069,7 @@ LayerManager::Dump(FILE* aFile, const char* aPrefix)
fprintf(file, "%s(null)</li></ul>", pfx.get());
return;
}
fprintf(file, "<ul>");
GetRoot()->Dump(file, pfx.get());
fprintf(file, "</ul></li></ul>");
@ -941,5 +1203,5 @@ LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix)
PRLogModuleInfo* LayerManager::sLog;
} // namespace layers
} // namespace layers
} // namespace mozilla

View File

@ -18,6 +18,7 @@
#include "gfxPattern.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "nsStyleAnimation.h"
#include "LayersBackend.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/TimeStamp.h"
@ -43,8 +44,14 @@ namespace gl {
class GLContext;
}
namespace css {
class ComputedTimingFunction;
}
namespace layers {
class Animation;
class CommonLayerAttributes;
class Layer;
class ThebesLayer;
class ContainerLayer;
@ -530,6 +537,13 @@ private:
};
class ThebesLayer;
typedef InfallibleTArray<Animation> AnimationArray;
struct AnimData {
InfallibleTArray<nsStyleAnimation::Value> mStartValues;
InfallibleTArray<nsStyleAnimation::Value> mEndValues;
InfallibleTArray<mozilla::css::ComputedTimingFunction*> mFunctions;
};
/**
* A Layer represents anything that can be rendered onto a destination
@ -551,7 +565,7 @@ public:
TYPE_THEBES
};
virtual ~Layer() {}
virtual ~Layer();
/**
* Returns the LayerManager this Layer belongs to. Note that the layer
@ -702,12 +716,19 @@ public:
* XXX Currently only transformations corresponding to 2D affine transforms
* are supported.
*/
void SetTransform(const gfx3DMatrix& aMatrix)
void SetBaseTransform(const gfx3DMatrix& aMatrix)
{
mTransform = aMatrix;
Mutated();
}
void SetScale(float aXScale, float aYScale)
{
mXScale = aXScale;
mYScale = aYScale;
Mutated();
}
/**
* CONSTRUCTION PHASE ONLY
* A layer is "fixed position" when it draws content from a content
@ -716,6 +737,14 @@ public:
*/
void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; }
// Call AddAnimation to add an animation to this layer from layout code.
void AddAnimation(const Animation& aAnimation);
// ClearAnimations clears animations on this layer.
void ClearAnimations();
// This is only called when the layer tree is updated. Do not call this from
// layout code. To add an animation to this layer, use AddAnimation.
void SetAnimations(const AnimationArray& aAnimations);
/**
* CONSTRUCTION PHASE ONLY
* If a layer is "fixed position", this determines which point on the layer
@ -735,11 +764,15 @@ public:
Layer* GetPrevSibling() { return mPrevSibling; }
virtual Layer* GetFirstChild() { return nsnull; }
virtual Layer* GetLastChild() { return nsnull; }
const gfx3DMatrix& GetTransform() { return mTransform; }
const gfx3DMatrix GetTransform();
const gfx3DMatrix& GetBaseTransform() { return mTransform; }
float GetXScale() { return mXScale; }
float GetYScale() { return mYScale; }
bool GetIsFixedPosition() { return mIsFixedPosition; }
gfxPoint GetFixedPositionAnchor() { return mAnchor; }
Layer* GetMaskLayer() { return mMaskLayer; }
AnimationArray& GetAnimations() { return mAnimations; }
InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
/**
* DRAWING PHASE ONLY
*
@ -940,20 +973,7 @@ public:
#endif
protected:
Layer(LayerManager* aManager, void* aImplData) :
mManager(aManager),
mParent(nsnull),
mNextSibling(nsnull),
mPrevSibling(nsnull),
mImplData(aImplData),
mMaskLayer(nsnull),
mOpacity(1.0),
mContentFlags(0),
mUseClipRect(false),
mUseTileSourceRect(false),
mIsFixedPosition(false),
mDebugColorIndex(0)
{}
Layer(LayerManager* aManager, void* aImplData);
void Mutated() { mManager->Mutated(this); }
@ -968,7 +988,13 @@ protected:
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowTransform()
*/
const gfx3DMatrix& GetLocalTransform();
const gfx3DMatrix GetLocalTransform();
/**
* Returns the local opacity for this layer: either mOpacity or,
* for shadow layers, GetShadowOpacity()
*/
const float GetLocalOpacity();
/**
* Computes a tweaked version of aTransform that snaps a point or a rectangle
@ -994,7 +1020,11 @@ protected:
gfx::UserData mUserData;
nsIntRegion mVisibleRegion;
gfx3DMatrix mTransform;
float mXScale;
float mYScale;
gfx3DMatrix mEffectiveTransform;
AnimationArray mAnimations;
InfallibleTArray<AnimData> mAnimationData;
float mOpacity;
nsIntRect mClipRect;
nsIntRect mTileSourceRect;

View File

@ -31,16 +31,18 @@ EXPORTS = \
BasicLayers.h \
BasicTiledThebesLayer.h \
BasicImplData.h \
CompositorParent.h \
ImageLayers.h \
Layers.h \
LayersBackend.h \
LayerManagerOGLShaders.h \
LayerManagerOGL.h \
LayerManagerOGLProgram.h \
ReadbackLayer.h \
LayerSorter.h \
TexturePoolOGL.h \
ReadbackLayer.h \
ShadowLayersManager.h \
SharedTextureImage.h \
TexturePoolOGL.h \
$(NULL)
CPPSRCS = \

View File

@ -22,6 +22,7 @@
#include "BasicThebesLayer.h"
#include "BasicContainerLayer.h"
#include "mozilla/Preferences.h"
#include "nsIWidget.h"
using namespace mozilla::gfx;
@ -132,7 +133,8 @@ BasicLayerManager::~BasicLayerManager()
void
BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
BufferMode aDoubleBuffering)
BufferMode aDoubleBuffering,
ScreenRotation aRotation)
{
NS_ASSERTION(!InTransaction(),
"Must set default target outside transaction");
@ -922,7 +924,7 @@ BasicLayerManager::CreateReadbackLayer()
}
BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
BasicLayerManager(aWidget)
BasicLayerManager(aWidget), mTargetRotation(ROTATION_0)
{
MOZ_COUNT_CTOR(BasicShadowLayerManager);
}
@ -942,6 +944,18 @@ BasicShadowLayerManager::GetMaxTextureSize() const
return PR_INT32_MAX;
}
void
BasicShadowLayerManager::SetDefaultTarget(gfxContext* aContext,
BufferMode aDoubleBuffering,
ScreenRotation aRotation)
{
BasicLayerManager::SetDefaultTarget(aContext, aDoubleBuffering, aRotation);
mTargetRotation = aRotation;
if (mWidget) {
mTargetBounds = mWidget->GetNaturalBounds();
}
}
void
BasicShadowLayerManager::SetRoot(Layer* aLayer)
{
@ -981,7 +995,7 @@ BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
if (HasShadowManager()) {
ShadowLayerForwarder::BeginTransaction();
ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation);
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.

View File

@ -10,11 +10,11 @@
#include "gfxContext.h"
#include "gfxCachedTempSurface.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/WidgetUtils.h"
#include "nsAutoRef.h"
#include "nsThreadUtils.h"
#include "mozilla/layers/ShadowLayers.h"
class nsIWidget;
namespace mozilla {
@ -80,7 +80,8 @@ public:
BUFFER_NONE,
BUFFER_BUFFERED
};
void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
ScreenRotation aRotation);
gfxContext* GetDefaultTarget() { return mDefaultTarget; }
nsIWidget* GetRetainerWidget() { return mWidget; }
@ -221,6 +222,8 @@ public:
virtual PRInt32 GetMaxTextureSize() const;
virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
ScreenRotation aRotation) MOZ_OVERRIDE;
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
virtual bool EndEmptyTransaction();
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
@ -261,11 +264,20 @@ private:
*/
void ForwardTransaction();
// The bounds of |mTarget| in device pixels.
nsIntRect mTargetBounds;
LayerRefArray mKeepAlive;
// Sometimes we draw to targets that don't natively support
// landscape/portrait orientation. When we need to implement that
// ourselves, |mTargetRotation| describes the induced transform we
// need to apply when compositing content to our target.
ScreenRotation mTargetRotation;
// Used to repeat the transaction right away (to avoid rebuilding
// a display list) to support progressive drawing.
bool mRepeatTransaction;
LayerRefArray mKeepAlive;
};
class BasicShadowableThebesLayer;

View File

@ -20,6 +20,7 @@
#include "ReadbackLayerD3D10.h"
#include "ImageLayerD3D10.h"
#include "mozilla/layers/PLayerChild.h"
#include "mozilla/WidgetUtils.h"
#include "../d3d9/Nv3DVUtils.h"
@ -448,7 +449,6 @@ LayerManagerD3D10::CreateOptimalSurface(const gfxIntSize &aSize,
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(texture));
@ -729,7 +729,8 @@ LayerManagerD3D10::Render()
if (mTarget) {
PaintToTarget();
} else if (mBackBuffer) {
ShadowLayerForwarder::BeginTransaction();
ShadowLayerForwarder::BeginTransaction(mWidget->GetNaturalBounds(),
ROTATION_0);
nsIntRect contentRect = nsIntRect(0, 0, rect.width, rect.height);
if (!mRootForShadowTree) {

View File

@ -470,7 +470,6 @@ ThebesLayerD3D10::CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode)
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
HRESULT hr;
if (!mTexture) {

View File

@ -21,6 +21,15 @@
#include "nsIWidget.h"
#include "RenderTrace.h"
#include "ShadowLayersParent.h"
#include "BasicLayers.h"
#include "LayerManagerOGL.h"
#include "nsIWidget.h"
#include "nsGkAtoms.h"
#include "RenderTrace.h"
#include "nsStyleAnimation.h"
#include "nsDisplayList.h"
#include "AnimationCommon.h"
#include "nsAnimationManager.h"
using namespace base;
using namespace mozilla::ipc;
@ -412,16 +421,23 @@ CompositorParent::Composite()
return;
}
Layer* aLayer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(aLayer);
Layer* layer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(layer);
bool requestNextFrame = TransformShadowTree(mLastCompose);
if (requestNextFrame) {
ScheduleComposition();
}
RenderTraceLayers(aLayer, "0000");
RenderTraceLayers(layer, "0000");
if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
!mTargetConfig.naturalBounds().IsEmpty()) {
LayerManagerOGL* lm = static_cast<LayerManagerOGL*>(mLayerManager.get());
lm->SetWorldTransform(
ComputeGLTransformForRotation(mTargetConfig.naturalBounds(),
mTargetConfig.rotation()));
}
mLayerManager->EndEmptyTransaction();
#ifdef COMPOSITOR_PERFORMANCE_WARNING
@ -510,9 +526,10 @@ SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowTransform(aLayer->GetTransform());
shadow->SetShadowTransform(aLayer->GetBaseTransform());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowClipRect(aLayer->GetClipRect());
shadow->SetShadowOpacity(aLayer->GetOpacity());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
@ -520,6 +537,114 @@ SetShadowProperties(Layer* aLayer)
}
}
// SampleValue should eventually take the CSS property as an argument. This
// will be needed if we ever animate two values with the same type but different
// interpolation rules.
static void
SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
nsStyleAnimation::Value& aEnd, Animatable* aValue)
{
nsStyleAnimation::Value interpolatedValue;
NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
if (aStart.GetUnit() == nsStyleAnimation::eUnit_Transform ||
aEnd.GetUnit() == nsStyleAnimation::eUnit_Transform) {
nsStyleAnimation::Interpolate(eCSSProperty_transform, aStart, aEnd,
aPortion, interpolatedValue);
nsCSSValueList* interpolatedList = interpolatedValue.GetCSSValueListValue();
TransformData& data = aAnimation.data().get_TransformData();
gfx3DMatrix transform =
nsDisplayTransform::GetResultingTransformMatrix(nsnull, data.origin(), nsDeviceContext::AppUnitsPerCSSPixel(),
&data.bounds(), interpolatedList, &data.mozOrigin(),
&data.perspectiveOrigin(), &data.perspective());
InfallibleTArray<TransformFunction>* functions = new InfallibleTArray<TransformFunction>();
functions->AppendElement(TransformMatrix(transform));
*aValue = *functions;
return;
}
NS_ASSERTION(aStart.GetUnit() == nsStyleAnimation::eUnit_Float, "Should be opacity");
nsStyleAnimation::Interpolate(eCSSProperty_opacity, aStart, aEnd,
aPortion, interpolatedValue);
*aValue = interpolatedValue.GetFloatValue();
}
static bool
SampleAnimations(Layer* aLayer, TimeStamp aPoint)
{
AnimationArray& animations = aLayer->GetAnimations();
InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();
bool activeAnimations = false;
for (PRUint32 i = animations.Length(); i-- !=0; ) {
Animation& animation = animations[i];
AnimData& animData = animationData[i];
double numIterations = animation.numIterations() != -1 ?
animation.numIterations() : NS_IEEEPositiveInfinity();
double positionInIteration =
ElementAnimations::GetPositionInIteration(animation.startTime(),
aPoint,
animation.duration(),
numIterations,
animation.direction());
if (positionInIteration == -1) {
animations.RemoveElementAt(i);
animationData.RemoveElementAt(i);
continue;
}
NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
positionInIteration <= 1.0,
"position should be in [0-1]");
int segmentIndex = 0;
AnimationSegment* segment = animation.segments().Elements();
while (segment->endPortion() < positionInIteration) {
++segment;
++segmentIndex;
}
double positionInSegment = (positionInIteration - segment->startPortion()) /
(segment->endPortion() - segment->startPortion());
double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment);
activeAnimations = true;
// interpolate the property
Animatable interpolatedValue;
SampleValue(portion, animation, animData.mStartValues[segmentIndex],
animData.mEndValues[segmentIndex], &interpolatedValue);
ShadowLayer* shadow = aLayer->AsShadowLayer();
switch (interpolatedValue.type()) {
case Animatable::TOpacity:
shadow->SetShadowOpacity(interpolatedValue.get_Opacity().value());
break;
case Animatable::TArrayOfTransformFunction: {
gfx3DMatrix matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
shadow->SetShadowTransform(matrix);
break;
}
default:
NS_WARNING("Unhandled animated property");
}
}
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
activeAnimations |= SampleAnimations(child, aPoint);
}
return activeAnimations;
}
bool
CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
Layer *aLayer,
@ -565,9 +690,13 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
ContainerLayer* container = layer->AsContainerLayer();
Layer* root = mLayerManager->GetRoot();
// NB: we must sample animations *before* sampling pan/zoom
// transforms.
wantNextFrame |= SampleAnimations(layer, mLastCompose);
const FrameMetrics& metrics = container->GetFrameMetrics();
const gfx3DMatrix& rootTransform = root->GetTransform();
const gfx3DMatrix& currentTransform = layer->GetTransform();
const gfx3DMatrix& currentTransform = layer->GetBaseTransform();
// FIXME/bug 775437: unify this interface with the ~native-fennec
// derived code
@ -660,7 +789,6 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
shadow->SetShadowTransform(treeTransform * currentTransform);
TransformFixedLayers(layer, offset, scaleDiff);
}
return wantNextFrame;
}
@ -694,8 +822,10 @@ CompositorParent::SyncViewportInfo(const nsIntRect& aDisplayPort,
void
CompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint)
{
mTargetConfig = aTargetConfig;
mIsFirstPaint = mIsFirstPaint || isFirstPaint;
mLayersUpdated = true;
Layer* root = aLayerTree->GetRoot();
@ -898,6 +1028,7 @@ public:
virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint) MOZ_OVERRIDE;
private:
@ -997,8 +1128,10 @@ CrossProcessCompositorParent::DeallocPLayers(PLayersParent* aLayers)
}
void
CrossProcessCompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
bool isFirstPaint)
CrossProcessCompositorParent::ShadowLayersUpdated(
ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint)
{
uint64_t id = aLayerTree->GetId();
MOZ_ASSERT(id != 0);

View File

@ -70,6 +70,7 @@ public:
virtual bool RecvResume() MOZ_OVERRIDE;
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint) MOZ_OVERRIDE;
void Destroy();
@ -227,6 +228,7 @@ private:
nsRefPtr<LayerManager> mLayerManager;
nsIWidget* mWidget;
TargetConfig mTargetConfig;
CancelableTask *mCurrentCompositeTask;
TimeStamp mLastCompose;
#ifdef COMPOSITOR_PERFORMANCE_WARNING

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