Merge m-c to m-i.

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

View File

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

View File

@ -122,11 +122,14 @@ var shell = {
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"] .sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
.createInstance(Ci.nsISHistory); .createInstance(Ci.nsISHistory);
['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) { // Capture all key events so we can filter out hardware buttons
window.addEventListener(type, this, false, true); // And send them to Gaia via mozChromeEvents.
window.addEventListener(type, this, true, true); // Ideally, hardware buttons wouldn't generate key events at all, or
}).bind(this)); // 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('MozApplicationManifest', this);
window.addEventListener('mozfullscreenchange', this); window.addEventListener('mozfullscreenchange', this);
window.addEventListener('sizemodechange', this); window.addEventListener('sizemodechange', this);
@ -165,11 +168,9 @@ var shell = {
}, },
stop: function shell_stop() { stop: function shell_stop() {
['keydown', 'keypress', 'keyup'].forEach((function unlistenKey(type) { window.removeEventListener('keydown', this, true);
window.removeEventListener(type, this, false, true); window.removeEventListener('keypress', this, true);
window.removeEventListener(type, this, true, true); window.removeEventListener('keyup', this, true);
}).bind(this));
window.removeEventListener('MozApplicationManifest', this); window.removeEventListener('MozApplicationManifest', this);
window.removeEventListener('mozfullscreenchange', this); window.removeEventListener('mozfullscreenchange', this);
window.removeEventListener('sizemodechange', this); window.removeEventListener('sizemodechange', this);
@ -180,33 +181,75 @@ var shell = {
#endif #endif
}, },
forwardKeyToContent: function shell_forwardKeyToContent(evt) { // If this key event actually represents a hardware button, filter it here
let content = shell.contentBrowser.contentWindow; // and send a mozChromeEvent with detail.type set to xxx-button-press or
let generatedEvent = content.document.createEvent('KeyboardEvent'); // xxx-button-release instead.
generatedEvent.initKeyEvent(evt.type, true, true, evt.view, evt.ctrlKey, filterHardwareKeys: function shell_filterHardwareKeys(evt) {
evt.altKey, evt.shiftKey, evt.metaKey, var type;
evt.keyCode, evt.charCode); 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) { handleEvent: function shell_handleEvent(evt) {
let content = this.contentBrowser.contentWindow; let content = this.contentBrowser.contentWindow;
switch (evt.type) { switch (evt.type) {
case 'keydown': case 'keydown':
case 'keyup': case 'keyup':
case 'keypress': case 'keypress':
// Redirect the HOME key to System app and stop the applications from this.filterHardwareKeys(evt);
// 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();
}
break; break;
case 'mozfullscreenchange': case 'mozfullscreenchange':
// When the screen goes fullscreen make sure to set the focus to the // 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 // 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'); let event = content.document.createEvent('CustomEvent');
event.initCustomEvent(type, true, true, details ? details : {}); event.initCustomEvent(type, true, true, details ? details : {});
content.dispatchEvent(event); 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) { Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
let msg = JSON.parse(data); let msg = JSON.parse(data);
let origin = Services.io.newURI(msg.manifest, null, null).prePath; let origin = Services.io.newURI(msg.manifest, null, null).prePath;
shell.sendEvent(shell.contentBrowser.contentWindow, 'mozChromeEvent', { shell.sendChromeEvent({
type: 'open-app', type: 'open-app',
url: msg.uri, url: msg.uri,
origin: origin, origin: origin,
@ -415,12 +461,22 @@ var AlertsHelper = {
return id; return id;
}, },
showAlertNotification: function alert_showAlertNotification(imageUrl, title, text, textClickable, showAlertNotification: function alert_showAlertNotification(imageUrl,
cookie, alertListener, name) { title,
text,
textClickable,
cookie,
alertListener,
name)
{
let id = this.registerListener(cookie, alertListener); let id = this.registerListener(cookie, alertListener);
let content = shell.contentBrowser.contentWindow; shell.sendChromeEvent({
shell.sendEvent(content, "mozChromeEvent", { type: "desktop-notification", id: id, icon: imageUrl, type: "desktop-notification",
title: title, text: text } ); id: id,
icon: imageUrl,
title: title,
text: text
});
} }
} }
@ -456,7 +512,6 @@ var WebappsHelper = {
}, },
observe: function webapps_observe(subject, topic, data) { observe: function webapps_observe(subject, topic, data) {
let content = shell.contentBrowser.contentWindow;
let json = JSON.parse(data); let json = JSON.parse(data);
switch(topic) { switch(topic) {
case "webapps-launch": case "webapps-launch":
@ -465,7 +520,7 @@ var WebappsHelper = {
return; return;
let manifest = new DOMApplicationManifest(aManifest, json.origin); let manifest = new DOMApplicationManifest(aManifest, json.origin);
shell.sendEvent(content, "mozChromeEvent", { shell.sendChromeEvent({
"type": "webapps-launch", "type": "webapps-launch",
"url": manifest.fullLaunchPath(json.startPoint), "url": manifest.fullLaunchPath(json.startPoint),
"origin": json.origin "origin": json.origin
@ -474,7 +529,11 @@ var WebappsHelper = {
break; break;
case "webapps-ask-install": case "webapps-ask-install":
let id = this.registerInstaller(json); 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; break;
} }
} }
@ -529,16 +588,28 @@ window.addEventListener('ContentStart', function ss_onContentStart() {
context.drawWindow(window, 0, 0, width, height, context.drawWindow(window, 0, 0, width, height,
'rgb(255,255,255)', flags); 'rgb(255,255,255)', flags);
shell.sendEvent(content, 'mozChromeEvent', { shell.sendChromeEvent({
type: 'take-screenshot-success', type: 'take-screenshot-success',
file: canvas.mozGetAsFile('screenshot', 'image/png') file: canvas.mozGetAsFile('screenshot', 'image/png')
}); });
} catch (e) { } catch (e) {
dump('exception while creating screenshot: ' + e + '\n'); dump('exception while creating screenshot: ' + e + '\n');
shell.sendEvent(content, 'mozChromeEvent', { shell.sendChromeEvent({
type: 'take-screenshot-error', type: 'take-screenshot-error',
error: String(e) 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 component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28} contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1 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) { getFile: function dp_getFile(prop, persistent) {
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir"]; let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir", "permissionDBPDir"];
if (localProps.indexOf(prop) != -1) { if (localProps.indexOf(prop) != -1) {
prop.persistent = true; prop.persistent = true;
let file = Cc["@mozilla.org/file/local;1"] let file = Cc["@mozilla.org/file/local;1"]

View File

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

View File

@ -684,3 +684,4 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/components/DirectoryProvider.js @BINPATH@/components/DirectoryProvider.js
@BINPATH@/components/ActivitiesGlue.js @BINPATH@/components/ActivitiesGlue.js
@BINPATH@/components/ProcessGlobal.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_list ap;
va_start(ap, fmt); va_start(ap, fmt);
#if defined(XP_WIN) && !MOZ_WINCONSOLE #ifndef XP_WIN
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
vfprintf(stderr, fmt, ap); 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 #endif
va_end(ap); va_end(ap);

View File

@ -1186,3 +1186,5 @@ pref("image.mem.max_decoded_image_kb", 256000);
// Example social provider // 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.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("social.sidebar.open", true);
pref("browser.social.whitelist", "");
pref("social.active", false);

View File

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

View File

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

View File

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

View File

@ -11,6 +11,8 @@ let SocialUI = {
Services.prefs.addObserver("social.sidebar.open", this, false); Services.prefs.addObserver("social.sidebar.open", this, false);
gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler, true, true);
Social.init(this._providerReady.bind(this)); Social.init(this._providerReady.bind(this));
}, },
@ -31,6 +33,7 @@ let SocialUI = {
observe: function SocialUI_observe(subject, topic, data) { observe: function SocialUI_observe(subject, topic, data) {
switch (topic) { switch (topic) {
case "social:pref-changed": case "social:pref-changed":
this.updateToggleCommand();
SocialShareButton.updateButtonHiddenState(); SocialShareButton.updateButtonHiddenState();
SocialToolbar.updateButtonHiddenState(); SocialToolbar.updateButtonHiddenState();
SocialSidebar.updateSidebar(); SocialSidebar.updateSidebar();
@ -46,11 +49,103 @@ let SocialUI = {
} }
}, },
get toggleCommand() {
return document.getElementById("Social:Toggle");
},
// Called once Social.jsm's provider has been set // Called once Social.jsm's provider has been set
_providerReady: function SocialUI_providerReady() { _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(); SocialToolbar.init();
SocialShareButton.init(); SocialShareButton.init();
SocialSidebar.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();
} }
} }
@ -154,21 +249,32 @@ var SocialToolbar = {
init: function SocialToolbar_init() { init: function SocialToolbar_init() {
document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL); document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
// handle button state let removeItem = document.getElementById("social-remove-menuitem");
document.getElementById("social-statusarea-popup").addEventListener("popupshowing", function(e) { let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
document.getElementById("social-toolbar-button").setAttribute("open", "true"); let label = gNavigatorBundle.getFormattedString("social.remove.label",
}, false); [brandShortName]);
document.getElementById("social-statusarea-popup").addEventListener("popuphiding", function(e) { let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
document.getElementById("social-toolbar-button").removeAttribute("open"); removeItem.setAttribute("label", label);
}, false); 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.updateButton();
this.updateProfile(); this.updateProfile();
}, },
get button() {
return document.getElementById("social-toolbar-button");
},
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() { updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
let toolbarbutton = document.getElementById("social-toolbar-button"); this.button.hidden = !Social.uiVisible;
toolbarbutton.hidden = !Social.uiVisible;
}, },
updateProfile: function SocialToolbar_updateProfile() { updateProfile: function SocialToolbar_updateProfile() {
@ -233,10 +339,10 @@ var SocialToolbar = {
panel.hidden = false; panel.hidden = false;
function sizePanelToContent() { function sizePanelToContent() {
// XXX Maybe we can use nsIDOMWindowUtils.getRootBounds() here? // FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
// XXX need to handle dynamic sizing // Need to handle dynamic sizing
let doc = notifBrowser.contentDocument; 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 // eventually
let body = doc.getElementById("notif") || doc.body.firstChild; let body = doc.getElementById("notif") || doc.body.firstChild;
if (!body) if (!body)
@ -254,13 +360,13 @@ var SocialToolbar = {
panel.addEventListener("popuphiding", function onpopuphiding() { panel.addEventListener("popuphiding", function onpopuphiding() {
panel.removeEventListener("popuphiding", onpopuphiding); panel.removeEventListener("popuphiding", onpopuphiding);
// unload the panel // unload the panel
document.getElementById("social-toolbar-button").removeAttribute("open"); SocialToolbar.button.removeAttribute("open");
notifBrowser.setAttribute("src", "about:blank"); notifBrowser.setAttribute("src", "about:blank");
}); });
notifBrowser.setAttribute("origin", Social.provider.origin); notifBrowser.setAttribute("origin", Social.provider.origin);
notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel")); 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); panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
} }
} }

View File

@ -182,6 +182,44 @@
</hbox> </hbox>
</panel> </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" <panel id="editSharePopup"
type="arrow" type="arrow"
orient="vertical" orient="vertical"
@ -214,16 +252,16 @@
class="editSharePopupBottomButton" class="editSharePopupBottomButton"
default="true" default="true"
autofocus="autofocus" autofocus="autofocus"
label="&social.sharePopup.ok.label;" label="&social.ok.label;"
accesskey="&social.sharePopup.ok.accesskey;" accesskey="&social.ok.accesskey;"
oncommand="SocialShareButton.dismissSharePopup();"/> oncommand="SocialShareButton.dismissSharePopup();"/>
#else #else
<button id="editSharePopupOkButton" <button id="editSharePopupOkButton"
class="editSharePopupBottomButton" class="editSharePopupBottomButton"
default="true" default="true"
autofocus="autofocus" autofocus="autofocus"
label="&social.sharePopup.ok.label;" label="&social.ok.label;"
accesskey="&social.sharePopup.ok.accesskey;" accesskey="&social.ok.accesskey;"
oncommand="SocialShareButton.dismissSharePopup();"/> oncommand="SocialShareButton.dismissSharePopup();"/>
<button id="editSharePopupUndoButton" <button id="editSharePopupUndoButton"
class="editSharePopupBottomButton" class="editSharePopupBottomButton"
@ -638,6 +676,8 @@
oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/> oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/>
</vbox> </vbox>
</hbox> </hbox>
<menuitem id="social-remove-menuitem"
oncommand="Social.active = false;"/>
<menuitem id="social-toggle-sidebar-menuitem" <menuitem id="social-toggle-sidebar-menuitem"
type="checkbox" type="checkbox"
autocheck="false" 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_bug734076.js \
browser_social_toolbar.js \ browser_social_toolbar.js \
browser_social_sidebar.js \ browser_social_sidebar.js \
browser_social_mozSocial_API.js \
social_panel.html \
social_sidebar.html \
social_worker.js \
$(NULL) $(NULL)
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT)) 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 #ifdef XP_WIN
* content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul) * content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
#endif #endif
content/browser/social-icon.png (content/social-icon.png)
# the following files are browser-specific overrides # the following files are browser-specific overrides
* content/browser/license.html (/toolkit/content/license.html) * content/browser/license.html (/toolkit/content/license.html)
% override chrome://global/content/license.html chrome://browser/content/license.html % override chrome://global/content/license.html chrome://browser/content/license.html

View File

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

View File

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

View File

@ -51,7 +51,7 @@ PlacesTreeView.prototype = {
// Bug 761494: // Bug 761494:
// ---------- // ----------
// Some addons use methods from nsINavHistoryResultObserver and // 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 // That's not a problem when the view is retrieved through the
// <tree>.view getter (which returns the wrappedJSObject of this object), // <tree>.view getter (which returns the wrappedJSObject of this object),
// it raises an issue when the view retrieved through the treeBoxObject.view // it raises an issue when the view retrieved through the treeBoxObject.view
@ -153,12 +153,21 @@ PlacesTreeView.prototype = {
_getRowForNode: _getRowForNode:
function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) { function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) {
if (aNode == this._rootNode) 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); // A node is removed form the view either if it has no parent or if its
for (let ancestor in ancestors) { // 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) 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. // Non-plain containers are initially built with their contents.
@ -1097,7 +1106,7 @@ PlacesTreeView.prototype = {
if (val) { if (val) {
this._result = val; this._result = val;
this._rootNode = this._result.root; this._rootNode = this._result.root;
this._cellProperties = new WeakMap(); this._cellProperties = new Map();
this._cuttingNodes = new Set(); this._cuttingNodes = new Set();
} }
else if (this._result) { else if (this._result) {

View File

@ -657,11 +657,21 @@ toolbar button -->
<!ENTITY socialToolbar.title "Social Toolbar Button"> <!ENTITY socialToolbar.title "Social Toolbar Button">
<!ENTITY social.notLoggedIn.label "Not logged in"> <!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.label "Unshare">
<!ENTITY social.sharePopup.undo.accesskey "U"> <!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.shared.label "You shared this page.">
<!ENTITY social.sharePopup.portrait.arialabel "User profile picture"> <!ENTITY social.sharePopup.portrait.arialabel "User profile picture">
<!ENTITY social.toggleSidebar.label "Show sidebar"> <!ENTITY social.toggleSidebar.label "Show sidebar">
<!ENTITY social.toggleSidebar.accesskey "s"> <!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.tooltip=Share this
social.shareButton.sharedtooltip=You shared this social.shareButton.sharedtooltip=You shared this
social.pageShared.label=Page shared 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"); "resource://gre/modules/SocialService.jsm");
let Social = { let Social = {
lastEventReceived: 0,
provider: null, provider: null,
init: function Social_init(callback) { init: function Social_init(callback) {
if (this.provider) { if (this.provider) {
@ -38,6 +39,25 @@ let Social = {
return this.provider && this.provider.enabled && this.provider.port; 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() { toggleSidebar: function SocialSidebar_toggle() {
let prefValue = Services.prefs.getBoolPref("social.sidebar.open"); let prefValue = Services.prefs.getBoolPref("social.sidebar.open");
Services.prefs.setBoolPref("social.sidebar.open", !prefValue); 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/mozprocess:develop
setup.py:testing/mozbase/mozprofile:develop setup.py:testing/mozbase/mozprofile:develop
setup.py:testing/mozbase/mozrunner: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 # This file contains code for populating the virtualenv environment for
# Mozilla's build system. It is typically called as part of configure. # Mozilla's build system. It is typically called as part of configure.
from __future__ import with_statement
import os.path import os.path
import subprocess import subprocess
import sys import sys
import distutils.sysconfig
def populate_virtualenv(top_source_directory, manifest_filename): def populate_virtualenv(top_source_directory, manifest_filename):
"""Populate the virtualenv from the contents of a manifest. """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]), call_setup(os.path.join(top_source_directory, package[1]),
package[2:]) 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): def call_setup(directory, arguments):
"""Calls setup.py in a directory.""" """Calls setup.py in a directory."""

View File

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

View File

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

View File

@ -3,7 +3,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
import unittest
import inspect import inspect
from StringIO import StringIO
import os
'''Helper to make python unit tests report the way that the Mozilla '''Helper to make python unit tests report the way that the Mozilla
unit test infrastructure expects tests to report. unit test infrastructure expects tests to report.
@ -11,10 +14,10 @@ unit test infrastructure expects tests to report.
Usage: Usage:
import unittest import unittest
from mozunit import MozTestRunner import mozunit
if __name__ == '__main__': if __name__ == '__main__':
unittest.main(testRunner=MozTestRunner()) mozunit.main()
''' '''
class _MozTestResult(_TestResult): class _MozTestResult(_TestResult):
@ -68,3 +71,69 @@ class MozTestRunner(_TestRunner):
test(result) test(result)
result.printErrorList() result.printErrorList()
return result 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 ifndef MOZ_AUTO_DEPS
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp)) MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
ifndef NO_GEN_XPT
MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp)) MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
endif endif
endif endif
endif
ALL_TRASH = \ ALL_TRASH = \
$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \ $(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))"; \ @if test -n "$(findstring $*.h, $(EXPORTS))"; \
then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi 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 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components. # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs) $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
@ -1323,8 +1320,6 @@ ifndef NO_INTERFACES_MANIFEST
endif endif
endif endif
endif # NO_GEN_XPT
GARBAGE_DIRS += $(XPIDL_GEN_DIR) GARBAGE_DIRS += $(XPIDL_GEN_DIR)
endif #} XPIDLSRCS endif #} XPIDLSRCS

View File

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

View File

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

View File

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

View File

@ -5,41 +5,14 @@ from StringIO import StringIO
import os import os
import sys import sys
import os.path import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from mozunit import main, MockedOpen
from Preprocessor import Preprocessor from Preprocessor import Preprocessor
class NamedIO(StringIO): def NamedIO(name, content):
def __init__(self, name, content): with open(name, 'w') as f:
self.name = name f.write(content)
StringIO.__init__(self, content) return name
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
class TestPreprocessor(unittest.TestCase): class TestPreprocessor(unittest.TestCase):
""" """
@ -539,13 +512,13 @@ octal value is not equal
self.fail("Expected a Preprocessor.Error") self.fail("Expected a Preprocessor.Error")
def test_include(self): def test_include(self):
with MockedOpen(NamedIO("foo/test", """#define foo foobarbaz with MockedOpen({"foo/test": """#define foo foobarbaz
#include @inc@ #include @inc@
@bar@ @bar@
"""), """,
NamedIO("bar", """#define bar barfoobaz "bar": """#define bar barfoobaz
@foo@ @foo@
""")): """}):
f = NamedIO("include.in", """#filter substitution f = NamedIO("include.in", """#filter substitution
#define inc ../bar #define inc ../bar
#include foo/test""") #include foo/test""")
@ -575,7 +548,7 @@ barfoobaz
self.fail("Expected a Preprocessor.Error") self.fail("Expected a Preprocessor.Error")
def test_include_literal_at(self): 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@ f = NamedIO("include_literal_at.in", """#include @foo@
#filter substitution #filter substitution
@foo@ @foo@
@ -585,11 +558,11 @@ barfoobaz
""") """)
def test_command_line_literal_at(self): 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.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo@.in'])
self.assertEqual(self.pp.out.getvalue(), """foobarbaz self.assertEqual(self.pp.out.getvalue(), """foobarbaz
""") """)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() main()

View File

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

View File

@ -6,8 +6,7 @@ import os
import imp import imp
from tempfile import mkdtemp from tempfile import mkdtemp
from shutil import rmtree from shutil import rmtree
sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import mozunit
from mozunit import MozTestRunner
from UserString import UserString from UserString import UserString
# Create a controlled configuration for use by expandlibs # Create a controlled configuration for use by expandlibs
@ -385,4 +384,4 @@ class TestSymbolOrder(unittest.TestCase):
if __name__ == '__main__': 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 import os, sys, os.path, time
from tempfile import mkdtemp from tempfile import mkdtemp
from shutil import rmtree from shutil import rmtree
sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import mozunit
from mozprocess import processhandler from mozprocess import processhandler
from nsinstall import nsinstall from nsinstall import nsinstall
@ -170,4 +170,4 @@ class TestNsinstall(unittest.TestCase):
#TODO: implement -R, -l, -L and test them! #TODO: implement -R, -l, -L and test them!
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() mozunit.main()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -178,8 +178,6 @@ MOCHITEST_FILES_A = \
file_bug426646-1.html \ file_bug426646-1.html \
file_bug426646-2.html \ file_bug426646-2.html \
test_bug429157.html \ test_bug429157.html \
test_header.html \
header.sjs \
test_XHR.html \ test_XHR.html \
file_XHR_pass1.xml \ file_XHR_pass1.xml \
file_XHR_pass2.txt \ 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); 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, void Init(double aX1, double aY1,
double aX2, double aY2); double aX2, double aY2);

View File

@ -4901,6 +4901,13 @@ nsDocShell::SetParentNativeWindow(nativeWindow parentNativeWindow)
return NS_ERROR_NOT_IMPLEMENTED; 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 NS_IMETHODIMP
nsDocShell::GetVisibility(bool * aVisibility) nsDocShell::GetVisibility(bool * aVisibility)
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -153,6 +153,11 @@ struct nsTimeout : PRCList
return static_cast<nsTimeout*>(PR_PREV_LINK(this)); 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 // Window for which this timeout fires
nsRefPtr<nsGlobalWindow> mWindow; nsRefPtr<nsGlobalWindow> mWindow;

View File

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

View File

@ -403,8 +403,10 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
DBusMessageIter iter; DBusMessageIter iter;
NS_ASSERTION(dbus_message_iter_init(aMsg, &iter), if (!dbus_message_iter_init(aMsg, &iter)) {
"Can't create message iterator!"); NS_WARNING("Can't create iterator!");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
InfallibleTArray<BluetoothNamedValue> value; InfallibleTArray<BluetoothNamedValue> value;
const char* addr; 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" /> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head> </head>
<body> <body onunload="unload()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
<p id="display"></p> <p id="display"></p>
<div id="content" style="display: none"> <div id="content" style="display: none">
@ -22,11 +22,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
function unload() {
delete gDataBlob;
gDataBlob = null;
delete gFileReader;
gFileReader = null;
}
devicestorage_setup(); devicestorage_setup();
var gFileName = "devicestorage/hi"; var gFileName = "devicestorage/hi";
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies." 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 gDataBlob = new Blob([gData], {type: 'text/plain'});
var gFileReader = new FileReader();
function getAfterDeleteSuccess(e) { function getAfterDeleteSuccess(e) {
ok(false, "file was deleted not successfully"); ok(false, "file was deleted not successfully");
@ -63,9 +73,8 @@ function getSuccess(e) {
var name = e.target.result.name; var name = e.target.result.name;
var reader = new FileReader(); gFileReader.readAsArrayBuffer(gDataBlob);
reader.readAsArrayBuffer(gDataBlob); gFileReader.onload = function(e) {
reader.onload = function(e) {
readerCallback(e); readerCallback(e);
request = storage[0].delete(name) request = storage[0].delete(name)

View File

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

View File

@ -1947,6 +1947,68 @@ nsPluginHost::IsLiveTag(nsIPluginTag* aPluginTag)
return false; 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); typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
@ -1991,9 +2053,11 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
} }
} }
pluginFiles.Sort(CompareFilesByTime());
bool warnOutdated = false; 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]; nsCOMPtr<nsIFile>& localfile = pluginFiles[i];
nsString utf16FilePath; nsString utf16FilePath;
@ -2001,20 +2065,7 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
if (NS_FAILED(rv)) if (NS_FAILED(rv))
continue; continue;
PRInt64 fileModTime = LL_ZERO; PRInt64 fileModTime = GetPluginLastModifiedTime(localfile);
#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
// Look for it in our cache // Look for it in our cache
NS_ConvertUTF16toUTF8 filePath(utf16FilePath); NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
@ -2147,6 +2198,21 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
*aPluginsChanged = true; *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, // If we're not creating a plugin list, simply looking for changes,
// then we're done. // then we're done.
if (!aCreatePluginList) { if (!aCreatePluginList) {

View File

@ -268,6 +268,12 @@ private:
// Checks to see if a tag object is in our list of live tags. // Checks to see if a tag object is in our list of live tags.
bool IsLiveTag(nsIPluginTag* tag); 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(); nsresult EnsurePrivateDirServiceProvider();
void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag); void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag);

View File

@ -379,6 +379,25 @@ bool nsPluginTag::IsEnabled()
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED); 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) void nsPluginTag::TryUnloadPlugin(bool inShutdown)
{ {
// We never want to send NPP_Shutdown to an in-process plugin unless // We never want to send NPP_Shutdown to an in-process plugin unless

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,9 @@
#include "nsEditor.h" #include "nsEditor.h"
#include "IMETextTxn.h" #include "IMETextTxn.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsISelection.h" #include "mozilla/Selection.h"
using namespace mozilla;
PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(), PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(),
mAbsorb(true), mAbsorb(true),
@ -42,7 +44,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn) NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
NS_IMPL_RELEASE_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); NS_ENSURE_TRUE(aEditor && aSelState, NS_ERROR_NULL_POINTER);
@ -256,10 +260,9 @@ NS_IMETHODIMP PlaceholderTxn::Commit()
NS_IMETHODIMP PlaceholderTxn::RememberEndingSelection() NS_IMETHODIMP PlaceholderTxn::RememberEndingSelection()
{ {
nsCOMPtr<nsISelection> selection; nsRefPtr<Selection> selection = mEditor->GetSelection();
nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); 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 ----------------------- // ------------ nsIAbsorbingTransaction -----------------------
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor); NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
nsEditor* aEditor);
NS_IMETHOD GetTxnName(nsIAtom **aName); NS_IMETHOD GetTxnName(nsIAtom **aName);
@ -72,7 +73,7 @@ protected:
// selection properly. // selection properly.
nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist
nsSelectionState mEndSel; 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 load 768765.html
needs-focus load 771749.html needs-focus load 771749.html
load 772282.html load 772282.html
load 776323.html

View File

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

View File

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

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Selection.h"
#include "nsCOMArray.h" #include "nsCOMArray.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsEditorUtils.h" #include "nsEditorUtils.h"
@ -18,24 +18,23 @@
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
#include "nsINode.h" #include "nsINode.h"
#include "nsISelection.h"
#include "nsISimpleEnumerator.h" #include "nsISimpleEnumerator.h"
class nsIDOMRange; class nsIDOMRange;
class nsISupports; class nsISupports;
using namespace mozilla;
/****************************************************************************** /******************************************************************************
* nsAutoSelectionReset * nsAutoSelectionReset
*****************************************************************************/ *****************************************************************************/
nsAutoSelectionReset::nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd) : nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd)
mSel(nsnull) : mSel(nsnull), mEd(nsnull)
,mEd(nsnull)
{ {
if (!aSel || !aEd) return; // not much we can do, bail. 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. if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
mSel = do_QueryInterface(aSel); mSel = aSel;
mEd = aEd; mEd = aEd;
if (mSel) if (mSel)
{ {

View File

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

View File

@ -32,7 +32,8 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID) 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; NS_IMETHOD EndPlaceHolderBatch()=0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -583,6 +583,13 @@ nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
return NS_ERROR_NULL_POINTER; 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 NS_IMETHODIMP
nsDocShellTreeOwner::GetVisibility(bool* aVisibility) nsDocShellTreeOwner::GetVisibility(bool* aVisibility)
{ {

View File

@ -1378,6 +1378,12 @@ NS_IMETHODIMP nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWind
return NS_OK; 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_IMETHODIMP nsWebBrowser::GetVisibility(bool* visibility)
{ {
NS_ENSURE_ARG_POINTER(visibility); NS_ENSURE_ARG_POINTER(visibility);

View File

@ -303,11 +303,13 @@ nsresult
nsPermissionManager::InitDB(bool aRemoveFile) nsPermissionManager::InitDB(bool aRemoveFile)
{ {
nsCOMPtr<nsIFile> permissionsFile; nsCOMPtr<nsIFile> permissionsFile;
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile)); nsresult rv = NS_GetSpecialDirectory(NS_APP_PERMISSION_PARENT_DIR, getter_AddRefs(permissionsFile));
if (!permissionsFile) if (NS_FAILED(rv)) {
return NS_ERROR_UNEXPECTED; 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); NS_ENSURE_SUCCESS(rv, rv);
if (aRemoveFile) { 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) 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 patches ====
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv. 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_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, &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_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. // 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)); 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> static RefPtr<ID2D1Brush>
_cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf, _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
cairo_path_fixed_t *fill_path,
cairo_linear_pattern_t *source_pattern) cairo_linear_pattern_t *source_pattern)
{ {
if (source_pattern->p1.x == source_pattern->p2.x && 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; D2D1_GRADIENT_STOP *stops;
int num_stops = source_pattern->base.n_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) { if (source_pattern->base.base.extend == CAIRO_EXTEND_REPEAT || source_pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
// 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; RefPtr<IDXGISurface> surf;
d2dsurf->surface->QueryInterface(&surf); d2dsurf->surface->QueryInterface(&surf);
DXGI_SURFACE_DESC desc; DXGI_SURFACE_DESC desc;
surf->GetDesc(&desc); surf->GetDesc(&desc);
// Get this when the points are not transformed yet. top_left.x = bottom_left.x = 0;
double gradient_length = _cairo_d2d_point_dist(p1, p2); top_left.y = top_right.y = 0;
// 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; top_right.x = bottom_right.x = desc.Width;
bottom_right.y = bottom_left.y = desc.Height; bottom_right.y = bottom_left.y = desc.Height;
}
// Transform the corners of our surface to pattern space. // 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_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, &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_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; cairo_point_double_t u;
// Unit vector of the gradient direction. // Unit vector of the gradient direction.
@ -1707,6 +1719,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
*/ */
static RefPtr<ID2D1Brush> 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, const cairo_pattern_t *pattern,
bool unique = false) 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) { } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
cairo_linear_pattern_t *source_pattern = cairo_linear_pattern_t *source_pattern =
(cairo_linear_pattern_t*)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) { } else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
cairo_radial_pattern_t *source_pattern = cairo_radial_pattern_t *source_pattern =
(cairo_radial_pattern_t*)pattern; (cairo_radial_pattern_t*)pattern;
@ -3233,7 +3246,7 @@ _cairo_d2d_paint(void *surface,
target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); 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); source);
if (!brush) { 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) { if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_INT_STATUS_UNSUPPORTED;
} }
@ -3394,7 +3407,7 @@ _cairo_d2d_mask(void *surface,
return CAIRO_INT_STATUS_SUCCESS; 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) { if (!opacityBrush) {
return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_INT_STATUS_UNSUPPORTED;
} }
@ -3480,7 +3493,7 @@ _cairo_d2d_stroke(void *surface,
transformed = false; transformed = false;
} }
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
source); source);
if (!brush) { if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_INT_STATUS_UNSUPPORTED;
@ -3607,7 +3620,7 @@ _cairo_d2d_fill(void *surface,
float x2 = _cairo_fixed_to_float(box.p2.x); float x2 = _cairo_fixed_to_float(box.p2.x);
float y2 = _cairo_fixed_to_float(box.p2.y); float y2 = _cairo_fixed_to_float(box.p2.y);
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
source); path, source);
if (!brush) { if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED; 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<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, RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
source); path, source);
if (!brush) { if (!brush) {
return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_INT_STATUS_UNSUPPORTED;
} }
@ -4143,7 +4156,7 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
fontArea.height = bounds.bottom - bounds.top; 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); source);
if (!brush) { 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) GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
{ {
if (aType != TextureImage::ThreadShared) if (aType != TextureImage::ThreadShared)
return nsnull; return 0;
if (!mShareWithEGLImage) if (!mShareWithEGLImage)
return nsnull; return 0;
MakeCurrent(); MakeCurrent();
GLuint texture = 0; GLuint texture = 0;
@ -903,7 +903,7 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
if (!tex->CreateEGLImage()) { if (!tex->CreateEGLImage()) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed"); NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
ReleaseSharedHandle(aType, (SharedTextureHandle)tex); ReleaseSharedHandle(aType, (SharedTextureHandle)tex);
return nsnull; return 0;
} }
// Raw pointer shared across threads // Raw pointer shared across threads
return (SharedTextureHandle)tex; return (SharedTextureHandle)tex;
@ -917,35 +917,35 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType,
// Both EGLImage and SurfaceTexture only support ThreadShared currently, but // Both EGLImage and SurfaceTexture only support ThreadShared currently, but
// it's possible to make SurfaceTexture work across processes. We should do that. // it's possible to make SurfaceTexture work across processes. We should do that.
if (aType != TextureImage::ThreadShared) if (aType != TextureImage::ThreadShared)
return nsnull; return 0;
switch (aBufferType) { switch (aBufferType) {
#ifdef MOZ_WIDGET_ANDROID #ifdef MOZ_WIDGET_ANDROID
case SharedTextureBufferType::SurfaceTexture: case SharedTextureBufferType::SurfaceTexture:
if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) { if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) {
NS_WARNING("Missing GL_OES_EGL_image_external"); NS_WARNING("Missing GL_OES_EGL_image_external");
return nsnull; return 0;
} }
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(aBuffer)); return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(aBuffer));
#endif #endif
case SharedTextureBufferType::TextureID: { case SharedTextureBufferType::TextureID: {
if (!mShareWithEGLImage) if (!mShareWithEGLImage)
return nsnull; return 0;
GLuint texture = (GLuint)aBuffer; GLuint texture = (GLuint)aBuffer;
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture, false); EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture, false);
if (!tex->CreateEGLImage()) { if (!tex->CreateEGLImage()) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed"); NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
delete tex; delete tex;
return nsnull; return 0;
} }
return (SharedTextureHandle)tex; return (SharedTextureHandle)tex;
} }
default: default:
NS_ERROR("Unknown shared texture buffer type"); NS_ERROR("Unknown shared texture buffer type");
return nsnull; return 0;
} }
} }

View File

@ -17,6 +17,7 @@
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "mozilla/Util.h" #include "mozilla/Util.h"
#include "LayerSorter.h" #include "LayerSorter.h"
#include "AnimationCommon.h"
using namespace mozilla::layers; using namespace mozilla::layers;
using namespace mozilla::gfx; using namespace mozilla::gfx;
@ -220,6 +221,245 @@ LayerManager::CreateAsynchronousImageContainer()
//-------------------------------------------------- //--------------------------------------------------
// Layer // 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 bool
Layer::CanUseOpaqueSurface() Layer::CanUseOpaqueSurface()
{ {
@ -361,21 +601,42 @@ Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
return currentClip.Intersect(scissor); return currentClip.Intersect(scissor);
} }
const gfx3DMatrix& const gfx3DMatrix
Layer::GetTransform()
{
gfx3DMatrix transform = mTransform;
transform.Scale(mXScale, mYScale, 1);
return transform;
}
const gfx3DMatrix
Layer::GetLocalTransform() 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()) if (ShadowLayer* shadow = AsShadowLayer())
return shadow->GetShadowTransform(); return shadow->GetShadowOpacity();
return mTransform; return mOpacity;
} }
float float
Layer::GetEffectiveOpacity() Layer::GetEffectiveOpacity()
{ {
float opacity = GetOpacity(); float opacity = GetLocalOpacity();
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface(); for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
c = c->GetParent()) { c = c->GetParent()) {
opacity *= c->GetOpacity(); opacity *= c->GetLocalOpacity();
} }
return opacity; return opacity;
} }
@ -387,6 +648,7 @@ Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix& aTransformToSurf
mMaskLayer->mEffectiveTransform = aTransformToSurface; mMaskLayer->mEffectiveTransform = aTransformToSurface;
#ifdef DEBUG #ifdef DEBUG
gfxMatrix maskTranslation; gfxMatrix maskTranslation;
bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation); bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!"); NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");

View File

@ -18,6 +18,7 @@
#include "gfxPattern.h" #include "gfxPattern.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsStyleAnimation.h"
#include "LayersBackend.h" #include "LayersBackend.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
@ -43,8 +44,14 @@ namespace gl {
class GLContext; class GLContext;
} }
namespace css {
class ComputedTimingFunction;
}
namespace layers { namespace layers {
class Animation;
class CommonLayerAttributes;
class Layer; class Layer;
class ThebesLayer; class ThebesLayer;
class ContainerLayer; class ContainerLayer;
@ -530,6 +537,13 @@ private:
}; };
class ThebesLayer; 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 * A Layer represents anything that can be rendered onto a destination
@ -551,7 +565,7 @@ public:
TYPE_THEBES TYPE_THEBES
}; };
virtual ~Layer() {} virtual ~Layer();
/** /**
* Returns the LayerManager this Layer belongs to. Note that the 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 * XXX Currently only transformations corresponding to 2D affine transforms
* are supported. * are supported.
*/ */
void SetTransform(const gfx3DMatrix& aMatrix) void SetBaseTransform(const gfx3DMatrix& aMatrix)
{ {
mTransform = aMatrix; mTransform = aMatrix;
Mutated(); Mutated();
} }
void SetScale(float aXScale, float aYScale)
{
mXScale = aXScale;
mYScale = aYScale;
Mutated();
}
/** /**
* CONSTRUCTION PHASE ONLY * CONSTRUCTION PHASE ONLY
* A layer is "fixed position" when it draws content from a content * A layer is "fixed position" when it draws content from a content
@ -716,6 +737,14 @@ public:
*/ */
void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; } 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 * CONSTRUCTION PHASE ONLY
* If a layer is "fixed position", this determines which point on the layer * If a layer is "fixed position", this determines which point on the layer
@ -735,11 +764,15 @@ public:
Layer* GetPrevSibling() { return mPrevSibling; } Layer* GetPrevSibling() { return mPrevSibling; }
virtual Layer* GetFirstChild() { return nsnull; } virtual Layer* GetFirstChild() { return nsnull; }
virtual Layer* GetLastChild() { 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; } bool GetIsFixedPosition() { return mIsFixedPosition; }
gfxPoint GetFixedPositionAnchor() { return mAnchor; } gfxPoint GetFixedPositionAnchor() { return mAnchor; }
Layer* GetMaskLayer() { return mMaskLayer; } Layer* GetMaskLayer() { return mMaskLayer; }
AnimationArray& GetAnimations() { return mAnimations; }
InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
/** /**
* DRAWING PHASE ONLY * DRAWING PHASE ONLY
* *
@ -940,20 +973,7 @@ public:
#endif #endif
protected: protected:
Layer(LayerManager* aManager, void* aImplData) : 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)
{}
void Mutated() { mManager->Mutated(this); } void Mutated() { mManager->Mutated(this); }
@ -968,7 +988,13 @@ protected:
* Returns the local transform for this layer: either mTransform or, * Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowTransform() * 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 * Computes a tweaked version of aTransform that snaps a point or a rectangle
@ -994,7 +1020,11 @@ protected:
gfx::UserData mUserData; gfx::UserData mUserData;
nsIntRegion mVisibleRegion; nsIntRegion mVisibleRegion;
gfx3DMatrix mTransform; gfx3DMatrix mTransform;
float mXScale;
float mYScale;
gfx3DMatrix mEffectiveTransform; gfx3DMatrix mEffectiveTransform;
AnimationArray mAnimations;
InfallibleTArray<AnimData> mAnimationData;
float mOpacity; float mOpacity;
nsIntRect mClipRect; nsIntRect mClipRect;
nsIntRect mTileSourceRect; nsIntRect mTileSourceRect;

View File

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

View File

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

View File

@ -10,11 +10,11 @@
#include "gfxContext.h" #include "gfxContext.h"
#include "gfxCachedTempSurface.h" #include "gfxCachedTempSurface.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/WidgetUtils.h"
#include "nsAutoRef.h" #include "nsAutoRef.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "mozilla/layers/ShadowLayers.h"
class nsIWidget; class nsIWidget;
namespace mozilla { namespace mozilla {
@ -80,7 +80,8 @@ public:
BUFFER_NONE, BUFFER_NONE,
BUFFER_BUFFERED BUFFER_BUFFERED
}; };
void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering); virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
ScreenRotation aRotation);
gfxContext* GetDefaultTarget() { return mDefaultTarget; } gfxContext* GetDefaultTarget() { return mDefaultTarget; }
nsIWidget* GetRetainerWidget() { return mWidget; } nsIWidget* GetRetainerWidget() { return mWidget; }
@ -221,6 +222,8 @@ public:
virtual PRInt32 GetMaxTextureSize() const; virtual PRInt32 GetMaxTextureSize() const;
virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
ScreenRotation aRotation) MOZ_OVERRIDE;
virtual void BeginTransactionWithTarget(gfxContext* aTarget); virtual void BeginTransactionWithTarget(gfxContext* aTarget);
virtual bool EndEmptyTransaction(); virtual bool EndEmptyTransaction();
virtual void EndTransaction(DrawThebesLayerCallback aCallback, virtual void EndTransaction(DrawThebesLayerCallback aCallback,
@ -261,11 +264,20 @@ private:
*/ */
void ForwardTransaction(); 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 // Used to repeat the transaction right away (to avoid rebuilding
// a display list) to support progressive drawing. // a display list) to support progressive drawing.
bool mRepeatTransaction; bool mRepeatTransaction;
LayerRefArray mKeepAlive;
}; };
class BasicShadowableThebesLayer; class BasicShadowableThebesLayer;

View File

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

View File

@ -21,6 +21,15 @@
#include "nsIWidget.h" #include "nsIWidget.h"
#include "RenderTrace.h" #include "RenderTrace.h"
#include "ShadowLayersParent.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 base;
using namespace mozilla::ipc; using namespace mozilla::ipc;
@ -412,16 +421,23 @@ CompositorParent::Composite()
return; return;
} }
Layer* aLayer = mLayerManager->GetRoot(); Layer* layer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(aLayer); AutoResolveRefLayers resolve(layer);
bool requestNextFrame = TransformShadowTree(mLastCompose); bool requestNextFrame = TransformShadowTree(mLastCompose);
if (requestNextFrame) { if (requestNextFrame) {
ScheduleComposition(); 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(); mLayerManager->EndEmptyTransaction();
#ifdef COMPOSITOR_PERFORMANCE_WARNING #ifdef COMPOSITOR_PERFORMANCE_WARNING
@ -510,9 +526,10 @@ SetShadowProperties(Layer* aLayer)
{ {
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate. // FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
ShadowLayer* shadow = aLayer->AsShadowLayer(); ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowTransform(aLayer->GetTransform()); shadow->SetShadowTransform(aLayer->GetBaseTransform());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion()); shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowClipRect(aLayer->GetClipRect()); shadow->SetShadowClipRect(aLayer->GetClipRect());
shadow->SetShadowOpacity(aLayer->GetOpacity());
for (Layer* child = aLayer->GetFirstChild(); for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) { 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 bool
CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame, CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
Layer *aLayer, Layer *aLayer,
@ -565,9 +690,13 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
ContainerLayer* container = layer->AsContainerLayer(); ContainerLayer* container = layer->AsContainerLayer();
Layer* root = mLayerManager->GetRoot(); Layer* root = mLayerManager->GetRoot();
// NB: we must sample animations *before* sampling pan/zoom
// transforms.
wantNextFrame |= SampleAnimations(layer, mLastCompose);
const FrameMetrics& metrics = container->GetFrameMetrics(); const FrameMetrics& metrics = container->GetFrameMetrics();
const gfx3DMatrix& rootTransform = root->GetTransform(); 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 // FIXME/bug 775437: unify this interface with the ~native-fennec
// derived code // derived code
@ -660,7 +789,6 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
shadow->SetShadowTransform(treeTransform * currentTransform); shadow->SetShadowTransform(treeTransform * currentTransform);
TransformFixedLayers(layer, offset, scaleDiff); TransformFixedLayers(layer, offset, scaleDiff);
} }
return wantNextFrame; return wantNextFrame;
} }
@ -694,8 +822,10 @@ CompositorParent::SyncViewportInfo(const nsIntRect& aDisplayPort,
void void
CompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree, CompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint) bool isFirstPaint)
{ {
mTargetConfig = aTargetConfig;
mIsFirstPaint = mIsFirstPaint || isFirstPaint; mIsFirstPaint = mIsFirstPaint || isFirstPaint;
mLayersUpdated = true; mLayersUpdated = true;
Layer* root = aLayerTree->GetRoot(); Layer* root = aLayerTree->GetRoot();
@ -898,6 +1028,7 @@ public:
virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE; virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree, virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint) MOZ_OVERRIDE; bool isFirstPaint) MOZ_OVERRIDE;
private: private:
@ -997,7 +1128,9 @@ CrossProcessCompositorParent::DeallocPLayers(PLayersParent* aLayers)
} }
void void
CrossProcessCompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree, CrossProcessCompositorParent::ShadowLayersUpdated(
ShadowLayersParent* aLayerTree,
const TargetConfig& aTargetConfig,
bool isFirstPaint) bool isFirstPaint)
{ {
uint64_t id = aLayerTree->GetId(); uint64_t id = aLayerTree->GetId();

View File

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

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