mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound.
This commit is contained in:
commit
9cdadc836a
@ -12,7 +12,6 @@
|
||||
#include "nsCoreUtils.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIServiceManager.h"
|
||||
@ -40,6 +39,7 @@
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/DocumentType.h"
|
||||
@ -395,8 +395,7 @@ NS_IMETHODIMP
|
||||
DocAccessible::GetNameSpaceURIForID(int16_t aNameSpaceID, nsAString& aNameSpaceURI)
|
||||
{
|
||||
if (mDocumentNode) {
|
||||
nsCOMPtr<nsINameSpaceManager> nameSpaceManager =
|
||||
do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
|
||||
nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
|
||||
if (nameSpaceManager)
|
||||
return nameSpaceManager->GetNameSpaceURI(aNameSpaceID, aNameSpaceURI);
|
||||
}
|
||||
|
@ -20,11 +20,11 @@
|
||||
#include "nsIDOMHTMLTextAreaElement.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsITextControlFrame.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDocument.h"
|
||||
@ -34,6 +33,7 @@
|
||||
#include "nsError.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsTableOuterFrame.h"
|
||||
|
||||
|
@ -29,9 +29,9 @@
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "nsView.h"
|
||||
#include "nsViewManager.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "XULMenuAccessibleWrap.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWinUtils.h"
|
||||
|
||||
@ -176,8 +177,7 @@ sdnAccessible::get_attributesForNames(unsigned short aMaxAttribs,
|
||||
return S_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mNode));
|
||||
nsCOMPtr<nsINameSpaceManager> nameSpaceManager =
|
||||
do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
|
||||
nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
|
||||
|
||||
int32_t index = 0;
|
||||
for (index = 0; index < aMaxAttribs; index++) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsIDOMXULDescriptionElement.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTextBoxFrame.h"
|
||||
|
@ -25,9 +25,9 @@
|
||||
#include "nsIDOMXULTextboxElement.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsITextControlFrame.h"
|
||||
#include "nsMenuPopupFrame.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
@ -61,9 +61,6 @@ function PlainTextConsole(print) {
|
||||
});
|
||||
|
||||
// We defined the `__exposedProps__` in our console chrome object.
|
||||
// Although it seems redundant, because we use `createObjectIn` too, in
|
||||
// worker.js, we are following what `ConsoleAPI` does. See:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/dom/base/ConsoleAPI.js#132
|
||||
//
|
||||
// Meanwhile we're investigating with the platform team if `__exposedProps__`
|
||||
// are needed, or are just a left-over.
|
||||
|
@ -199,11 +199,7 @@ const WorkerSandbox = Class({
|
||||
if (!getTabForContentWindow(window)) {
|
||||
let win = getUnsafeWindow(window);
|
||||
|
||||
// export our chrome console to content window, using the same approach
|
||||
// of `ConsoleAPI`:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/dom/base/ConsoleAPI.js#150
|
||||
//
|
||||
// and described here:
|
||||
// export our chrome console to content window, as described here:
|
||||
// https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
|
||||
let con = Cu.createObjectIn(win);
|
||||
|
||||
|
@ -278,11 +278,7 @@ const WorkerSandbox = EventEmitter.compose({
|
||||
if (!getTabForContentWindow(window)) {
|
||||
let win = window.wrappedJSObject ? window.wrappedJSObject : window;
|
||||
|
||||
// export our chrome console to content window, using the same approach
|
||||
// of `ConsoleAPI`:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/dom/base/ConsoleAPI.js#150
|
||||
//
|
||||
// and described here:
|
||||
// export our chrome console to content window as described here:
|
||||
// https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
|
||||
let con = Cu.createObjectIn(win);
|
||||
|
||||
|
@ -339,7 +339,7 @@
|
||||
|
||||
; JavaScript components
|
||||
@BINPATH@/components/ConsoleAPI.manifest
|
||||
@BINPATH@/components/ConsoleAPI.js
|
||||
@BINPATH@/components/ConsoleAPIStorage.js
|
||||
@BINPATH@/components/BrowserElementParent.manifest
|
||||
@BINPATH@/components/BrowserElementParent.js
|
||||
@BINPATH@/components/ContactManager.js
|
||||
|
@ -218,7 +218,9 @@
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
<!-- type="default" forces frames to be created so that the panel's size can be determined -->
|
||||
<panel id="UITourHighlightContainer"
|
||||
type="default"
|
||||
hidden="true"
|
||||
noautofocus="true"
|
||||
noautohide="true"
|
||||
|
@ -7,6 +7,7 @@
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
flip="slide"
|
||||
position="bottomcenter topright"
|
||||
noautofocus="true">
|
||||
<panelmultiview id="PanelUI-multiView" mainViewId="PanelUI-mainView">
|
||||
<panelview id="PanelUI-mainView" context="customizationPanelContextMenu">
|
||||
@ -223,6 +224,7 @@
|
||||
type="arrow"
|
||||
noautofocus="true"
|
||||
context="toolbar-context-menu"
|
||||
position="bottomcenter topright"
|
||||
hidden="true">
|
||||
<vbox id="widget-overflow-scroller">
|
||||
<vbox id="widget-overflow-list" class="widget-overflow-list"
|
||||
|
@ -143,7 +143,7 @@ const PanelUI = {
|
||||
let iconAnchor =
|
||||
document.getAnonymousElementByAttribute(anchor, "class",
|
||||
"toolbarbutton-icon");
|
||||
this.panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
|
||||
this.panel.openPopup(iconAnchor || anchor);
|
||||
|
||||
this.panel.addEventListener("popupshown", function onPopupShown() {
|
||||
this.removeEventListener("popupshown", onPopupShown);
|
||||
|
@ -3491,8 +3491,10 @@ OverflowableToolbar.prototype = {
|
||||
}
|
||||
let doc = this._panel.ownerDocument;
|
||||
this._panel.hidden = false;
|
||||
let contextMenu = doc.getElementById(this._panel.getAttribute("context"));
|
||||
gELS.addSystemEventListener(contextMenu, 'command', this, true);
|
||||
let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
|
||||
this._panel.openPopup(anchor || this._chevron, "bottomcenter topright");
|
||||
this._panel.openPopup(anchor || this._chevron);
|
||||
this._chevron.open = true;
|
||||
|
||||
this._panel.addEventListener("popupshown", function onPopupShown() {
|
||||
@ -3506,15 +3508,10 @@ OverflowableToolbar.prototype = {
|
||||
_onClickChevron: function(aEvent) {
|
||||
if (this._chevron.open) {
|
||||
this._panel.hidePopup();
|
||||
this._chevron.open = false;
|
||||
} else {
|
||||
let doc = aEvent.target.ownerDocument;
|
||||
this._panel.hidden = false;
|
||||
let contextMenu = doc.getElementById(this._panel.getAttribute("context"));
|
||||
gELS.addSystemEventListener(contextMenu, 'command', this, true);
|
||||
let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
|
||||
this._panel.openPopup(anchor || this._chevron, "bottomcenter topright");
|
||||
this.show();
|
||||
}
|
||||
this._chevron.open = !this._chevron.open;
|
||||
},
|
||||
|
||||
_onPanelHiding: function(aEvent) {
|
||||
|
@ -1688,7 +1688,15 @@ CustomizeMode.prototype = {
|
||||
let dragY = aEvent.clientY - this._dragOffset.y;
|
||||
|
||||
// Ensure this is within the container
|
||||
let bounds = expectedParent.getBoundingClientRect();
|
||||
let boundsContainer = expectedParent;
|
||||
// NB: because the panel UI itself is inside a scrolling container, we need
|
||||
// to use the parent bounds (otherwise, if the panel UI is scrolled down,
|
||||
// the numbers we get are in window coordinates which leads to various kinds
|
||||
// of weirdness)
|
||||
if (boundsContainer == this.panelUIContents) {
|
||||
boundsContainer = boundsContainer.parentNode;
|
||||
}
|
||||
let bounds = boundsContainer.getBoundingClientRect();
|
||||
dragX = Math.min(bounds.right, Math.max(dragX, bounds.left));
|
||||
dragY = Math.min(bounds.bottom, Math.max(dragY, bounds.top));
|
||||
|
||||
@ -1700,6 +1708,16 @@ CustomizeMode.prototype = {
|
||||
}
|
||||
} else {
|
||||
let positionManager = DragPositionManager.getManagerForArea(aAreaElement);
|
||||
// Make it relative to the container:
|
||||
dragX -= bounds.left;
|
||||
// NB: but if we're in the panel UI, we need to use the actual panel
|
||||
// contents instead of the scrolling container to determine our origin
|
||||
// offset against:
|
||||
if (expectedParent == this.panelUIContents) {
|
||||
dragY -= this.panelUIContents.getBoundingClientRect().top;
|
||||
} else {
|
||||
dragY -= bounds.top;
|
||||
}
|
||||
// Find the closest node:
|
||||
targetNode = positionManager.find(aAreaElement, dragX, dragY, aDraggedItemId);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ function AreaPositionManager(aContainer) {
|
||||
this._containerInfo = {
|
||||
left: containerRect.left,
|
||||
right: containerRect.right,
|
||||
top: containerRect.top,
|
||||
width: containerRect.width
|
||||
};
|
||||
this._inPanel = aContainer.id == CustomizableUI.AREA_PANEL;
|
||||
@ -76,10 +77,14 @@ AreaPositionManager.prototype = {
|
||||
find: function(aContainer, aX, aY, aDraggedItemId) {
|
||||
let closest = null;
|
||||
let minCartesian = Number.MAX_VALUE;
|
||||
let containerX = this._containerInfo.left;
|
||||
let containerY = this._containerInfo.top;
|
||||
for (let node of aContainer.children) {
|
||||
let coordinates = this._lazyStoreGet(node);
|
||||
let hDiff = coordinates.x - aX;
|
||||
let vDiff = coordinates.y - aY;
|
||||
let offsetX = coordinates.x - containerX;
|
||||
let offsetY = coordinates.y - containerY;
|
||||
let hDiff = offsetX - aX;
|
||||
let vDiff = offsetY - aY;
|
||||
// For wide widgets, we're always going to be further from the center
|
||||
// horizontally. Compensate:
|
||||
if (this.isWide(node)) {
|
||||
|
@ -186,18 +186,17 @@
|
||||
</vbox>
|
||||
|
||||
<vbox id="noFxaAccount">
|
||||
<description>&welcome.description;</description>
|
||||
<label value="&welcome.description;"/>
|
||||
<label class="text-link"
|
||||
onclick="gSyncPane.signUp(); return false;"
|
||||
value="&welcome.createAccount.label;"/>
|
||||
<label class="text-link"
|
||||
onclick="gSyncPane.signIn(); return false;"
|
||||
value="&welcome.signIn.label;"/>
|
||||
<spacer flex="1"/>
|
||||
<separator/>
|
||||
<label class="text-link"
|
||||
onclick="gSyncPane.openOldSyncSupportPage(); return false;"
|
||||
value="&welcome.useOldSync.label;"/>
|
||||
<spacer flex="10"/>
|
||||
</vbox>
|
||||
|
||||
<vbox id="hasFxaAccount">
|
||||
@ -305,11 +304,12 @@
|
||||
flex="1"
|
||||
onchange="gSyncUtils.changeName(this)"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<hbox id="tosPP" pack="center">
|
||||
<label class="text-link"
|
||||
<label class="text-link small"
|
||||
onclick="event.stopPropagation();gSyncUtils.openToS();"
|
||||
value="&prefs.tosLink.label;"/>
|
||||
<label class="text-link"
|
||||
<label class="text-link small"
|
||||
onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"
|
||||
value="&fxaPrivacyNotice.link.label;"/>
|
||||
</hbox>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
function test()
|
||||
{
|
||||
let storage = Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", {}).ConsoleAPIStorage;
|
||||
let storage = Cc["@mozilla.org/consoleAPI-storage;1"].getService(Ci.nsIConsoleAPIStorage);
|
||||
storage.clearEvents();
|
||||
|
||||
let console = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).console;
|
||||
|
@ -11,7 +11,8 @@ function test()
|
||||
const TEST_URI = "data:text/html;charset=utf8,<p>hello world! bug 874061" +
|
||||
"<button onclick='console.log(\"foobar bug 874061\");" +
|
||||
"fooBazBaz.yummy()'>click</button>";
|
||||
let ConsoleAPIStorage = Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", {}).ConsoleAPIStorage;
|
||||
let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
|
||||
.getService(Ci.nsIConsoleAPIStorage);
|
||||
let privateWindow, privateBrowser, privateTab, privateContent;
|
||||
let hud, expectedMessages, nonPrivateMessage;
|
||||
|
||||
|
@ -33,10 +33,10 @@ function test() {
|
||||
|
||||
// The expected stack trace object.
|
||||
let stacktrace = [
|
||||
{ filename: TEST_URI, lineNumber: 9, functionName: "window.foobar585956c", language: 2 },
|
||||
{ filename: TEST_URI, lineNumber: 14, functionName: "foobar585956b", language: 2 },
|
||||
{ filename: TEST_URI, lineNumber: 18, functionName: "foobar585956a", language: 2 },
|
||||
{ filename: TEST_URI, lineNumber: 21, functionName: null, language: 2 }
|
||||
{ filename: TEST_URI, functionName: "window.foobar585956c", language: 2, lineNumber: 9 },
|
||||
{ filename: TEST_URI, functionName: "foobar585956b", language: 2, lineNumber: 14 },
|
||||
{ filename: TEST_URI, functionName: "foobar585956a", language: 2, lineNumber: 18 },
|
||||
{ filename: TEST_URI, functionName: "", language: 2, lineNumber: 21 }
|
||||
];
|
||||
|
||||
ok(obj._stacktrace, "found stacktrace object");
|
||||
|
@ -346,7 +346,7 @@
|
||||
|
||||
; JavaScript components
|
||||
@BINPATH@/components/ConsoleAPI.manifest
|
||||
@BINPATH@/components/ConsoleAPI.js
|
||||
@BINPATH@/components/ConsoleAPIStorage.js
|
||||
@BINPATH@/components/BrowserElementParent.manifest
|
||||
@BINPATH@/components/BrowserElementParent.js
|
||||
@BINPATH@/components/FeedProcessor.manifest
|
||||
|
@ -46,6 +46,14 @@ radio[pane=paneSync] {
|
||||
}
|
||||
%endif
|
||||
|
||||
label.small {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
#tabPrefsBox {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Applications Pane */
|
||||
#BrowserPreferences[animated="true"] #handlersView {
|
||||
height: 25em;
|
||||
@ -148,4 +156,13 @@ radio[pane=paneSync] {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#noFxaAccount {
|
||||
margin: 5px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
#noFxaAccount > label:first-child {
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
%endif
|
||||
|
@ -70,6 +70,9 @@ radio[pane=paneSync] {
|
||||
}
|
||||
%endif
|
||||
|
||||
label.small {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
/* ----- APPLICATIONS PREFPANE ----- */
|
||||
#BrowserPreferences[animated="true"] #handlersView {
|
||||
@ -218,4 +221,13 @@ html|a.inline-link:-moz-focusring {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#noFxaAccount {
|
||||
margin: 12px 4px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
#noFxaAccount > label:first-child {
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
%endif
|
||||
|
@ -2500,6 +2500,16 @@ chatbox {
|
||||
|
||||
%include ../shared/customizableui/customizeMode.inc.css
|
||||
|
||||
/**
|
||||
* This next rule is a hack to disable subpixel anti-aliasing on all
|
||||
* labels during the customize mode transition. Subpixel anti-aliasing
|
||||
* on Windows with Direct2D layers acceleration is particularly slow to
|
||||
* paint, so this hack is how we sidestep that performance bottleneck.
|
||||
*/
|
||||
#main-window:-moz-any([customize-entering],[customize-exiting]) label {
|
||||
transform: perspective(0.01px);
|
||||
}
|
||||
|
||||
#main-window[customize-entered] {
|
||||
background-image: url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png");
|
||||
background-attachment: fixed;
|
||||
|
@ -45,6 +45,14 @@ radio[pane=paneSync] {
|
||||
}
|
||||
%endif
|
||||
|
||||
label.small {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
#tabPrefsBox {
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
/* Applications Pane */
|
||||
#BrowserPreferences[animated="true"] #handlersView {
|
||||
height: 25em;
|
||||
@ -138,4 +146,13 @@ radio[pane=paneSync] {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#noFxaAccount {
|
||||
margin: 6px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
#noFxaAccount > label:first-child {
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
%endif
|
||||
|
@ -5,7 +5,7 @@
|
||||
# Setup for build cache
|
||||
|
||||
bucket=
|
||||
if test -f "$topsrcdir/sccache/sccache.py"; then
|
||||
if test -z "$SCCACHE_DISABLE" -a -f "$topsrcdir/sccache/sccache.py"; then
|
||||
case `hostname` in
|
||||
try*spot*.use1.mozilla.com|try*ec2*.use1.mozilla.com)
|
||||
bucket=mozilla-releng-s3-cache-us-east-1-try
|
||||
|
@ -54,13 +54,13 @@ EXPORTS += [
|
||||
'nsIDocumentInlines.h',
|
||||
'nsIDocumentObserver.h',
|
||||
'nsIMutationObserver.h',
|
||||
'nsINameSpaceManager.h',
|
||||
'nsINode.h',
|
||||
'nsINodeInfo.h',
|
||||
'nsINodeList.h',
|
||||
'nsIScriptElement.h',
|
||||
'nsIStyleSheetLinkingElement.h',
|
||||
'nsLineBreaker.h',
|
||||
'nsNameSpaceManager.h',
|
||||
'nsReferencedElement.h',
|
||||
'nsTreeSanitizer.h',
|
||||
'nsViewportInfo.h',
|
||||
|
@ -68,7 +68,7 @@ class nsIInterfaceRequestor;
|
||||
class nsIIOService;
|
||||
class nsIJSRuntimeService;
|
||||
class nsILineBreaker;
|
||||
class nsINameSpaceManager;
|
||||
class nsNameSpaceManager;
|
||||
class nsINodeInfo;
|
||||
class nsIObserver;
|
||||
class nsIParser;
|
||||
@ -451,7 +451,7 @@ public:
|
||||
|
||||
static nsIParserService* GetParserService();
|
||||
|
||||
static nsINameSpaceManager* NameSpaceManager()
|
||||
static nsNameSpaceManager* NameSpaceManager()
|
||||
{
|
||||
return sNameSpaceManager;
|
||||
}
|
||||
@ -2155,7 +2155,7 @@ private:
|
||||
|
||||
static nsIParserService *sParserService;
|
||||
|
||||
static nsINameSpaceManager *sNameSpaceManager;
|
||||
static nsNameSpaceManager *sNameSpaceManager;
|
||||
|
||||
static nsIIOService *sIOService;
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
|
||||
#include "nsCOMPtr.h" // for member
|
||||
#include "nsIAtom.h" // for member (in nsCOMPtr)
|
||||
#include "nsINameSpaceManager.h" // for kNameSpaceID_*
|
||||
#include "nsISupports.h" // for base class
|
||||
#include "nsNameSpaceManager.h" // for kNameSpaceID_*
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "nsDOMString.h"
|
||||
|
@ -3,10 +3,13 @@
|
||||
* 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/. */
|
||||
|
||||
#ifndef nsINameSpaceManager_h___
|
||||
#define nsINameSpaceManager_h___
|
||||
#ifndef nsNameSpaceManager_h___
|
||||
#define nsNameSpaceManager_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsAString;
|
||||
@ -28,13 +31,45 @@ static const int32_t kNameSpaceID_None = 0;
|
||||
#define kNameSpaceID_XUL 9
|
||||
#define kNameSpaceID_SVG 10
|
||||
#define kNameSpaceID_LastBuiltin 10 // last 'built-in' namespace
|
||||
|
||||
class nsNameSpaceKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef const nsAString* KeyType;
|
||||
typedef const nsAString* KeyTypePointer;
|
||||
|
||||
nsNameSpaceKey(KeyTypePointer aKey) : mKey(aKey)
|
||||
{
|
||||
}
|
||||
nsNameSpaceKey(const nsNameSpaceKey& toCopy) : mKey(toCopy.mKey)
|
||||
{
|
||||
}
|
||||
|
||||
KeyType GetKey() const
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
bool KeyEquals(KeyType aKey) const
|
||||
{
|
||||
return mKey->Equals(*aKey);
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey)
|
||||
{
|
||||
return aKey;
|
||||
}
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey) {
|
||||
return mozilla::HashString(*aKey);
|
||||
}
|
||||
|
||||
enum {
|
||||
ALLOW_MEMMOVE = true
|
||||
};
|
||||
|
||||
private:
|
||||
const nsAString* mKey;
|
||||
};
|
||||
|
||||
#define NS_NAMESPACEMANAGER_CONTRACTID "@mozilla.org/content/namespacemanager;1"
|
||||
|
||||
#define NS_INAMESPACEMANAGER_IID \
|
||||
{ 0xd74e83e6, 0xf932, 0x4289, \
|
||||
{ 0xac, 0x95, 0x9e, 0x10, 0x24, 0x30, 0x88, 0xd6 } }
|
||||
|
||||
/**
|
||||
* The Name Space Manager tracks the association between a NameSpace
|
||||
* URI and the int32_t runtime id. Mappings between NameSpaces and
|
||||
@ -44,29 +79,33 @@ static const int32_t kNameSpaceID_None = 0;
|
||||
* consistent accross the app. NameSpace IDs are only consistent at runtime
|
||||
* ie: they are not guaranteed to be consistent accross app sessions.
|
||||
*
|
||||
* The nsINameSpaceManager needs to have a live reference for as long as
|
||||
* The nsNameSpaceManager needs to have a live reference for as long as
|
||||
* the NameSpace IDs are needed.
|
||||
*
|
||||
*/
|
||||
|
||||
class nsINameSpaceManager : public nsISupports
|
||||
class nsNameSpaceManager
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INAMESPACEMANAGER_IID)
|
||||
virtual ~nsNameSpaceManager() {}
|
||||
|
||||
virtual nsresult RegisterNameSpace(const nsAString& aURI,
|
||||
int32_t& aNameSpaceID) = 0;
|
||||
int32_t& aNameSpaceID);
|
||||
|
||||
virtual nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI) = 0;
|
||||
virtual int32_t GetNameSpaceID(const nsAString& aURI) = 0;
|
||||
virtual nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
|
||||
virtual int32_t GetNameSpaceID(const nsAString& aURI);
|
||||
|
||||
virtual bool HasElementCreator(int32_t aNameSpaceID) = 0;
|
||||
virtual bool HasElementCreator(int32_t aNameSpaceID);
|
||||
|
||||
static nsNameSpaceManager* GetInstance();
|
||||
private:
|
||||
bool Init();
|
||||
nsresult AddNameSpace(const nsAString& aURI, const int32_t aNameSpaceID);
|
||||
|
||||
nsDataHashtable<nsNameSpaceKey,int32_t> mURIToIDTable;
|
||||
nsTArray< nsAutoPtr<nsString> > mURIArray;
|
||||
|
||||
static mozilla::StaticAutoPtr<nsNameSpaceManager> sInstance;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsINameSpaceManager, NS_INAMESPACEMANAGER_IID)
|
||||
|
||||
nsresult NS_GetNameSpaceManager(nsINameSpaceManager** aInstancePtrResult);
|
||||
|
||||
void NS_NameSpaceManagerShutdown();
|
||||
|
||||
#endif // nsINameSpaceManager_h___
|
||||
#endif // nsNameSpaceManager_h___
|
@ -12,7 +12,6 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsError.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsDOMString.h"
|
||||
@ -22,6 +21,7 @@
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsEventListenerManager.h"
|
||||
#include "nsTextNode.h"
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "mozilla/dom/DocumentFragment.h"
|
||||
#include "mozilla/dom/Element.h" // for NS_IMPL_ELEMENT_CLONE
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsError.h"
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
#include "nsDOMCSSAttrDeclaration.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
#include "nsDOMCSSAttrDeclaration.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include "nsINodeList.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
@ -196,7 +196,7 @@ const char kLoadAsData[] = "loadAsData";
|
||||
nsIXPConnect *nsContentUtils::sXPConnect;
|
||||
nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
|
||||
nsIParserService *nsContentUtils::sParserService = nullptr;
|
||||
nsINameSpaceManager *nsContentUtils::sNameSpaceManager;
|
||||
nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
|
||||
nsIIOService *nsContentUtils::sIOService;
|
||||
imgLoader *nsContentUtils::sImgLoader;
|
||||
imgLoader *nsContentUtils::sPrivateImgLoader;
|
||||
@ -371,8 +371,8 @@ nsContentUtils::Init()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_GetNameSpaceManager(&sNameSpaceManager);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
sNameSpaceManager = nsNameSpaceManager::GetInstance();
|
||||
NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
sXPConnect = nsXPConnect::XPConnect();
|
||||
|
||||
@ -384,7 +384,7 @@ nsContentUtils::Init()
|
||||
// Getting the first context can trigger GC, so do this non-lazily.
|
||||
sXPConnect->InitSafeJSContext();
|
||||
|
||||
rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
||||
nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
||||
if (NS_FAILED(rv)) {
|
||||
// This makes life easier, but we can live without it.
|
||||
|
||||
@ -1458,7 +1458,6 @@ nsContentUtils::Shutdown()
|
||||
NS_IF_RELEASE(sConsoleService);
|
||||
sXPConnect = nullptr;
|
||||
NS_IF_RELEASE(sSecurityManager);
|
||||
NS_IF_RELEASE(sNameSpaceManager);
|
||||
NS_IF_RELEASE(sParserService);
|
||||
NS_IF_RELEASE(sIOService);
|
||||
NS_IF_RELEASE(sLineBreaker);
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "nsError.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
|
@ -64,7 +64,7 @@
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMText.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
@ -61,7 +61,6 @@
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorIMESupport.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIScriptError.h"
|
||||
@ -75,6 +74,7 @@
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
@ -8,16 +8,16 @@
|
||||
* between namespace IDs and namespace URIs.
|
||||
*/
|
||||
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/XBLChildrenElement.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
@ -35,82 +35,29 @@ using namespace mozilla::dom;
|
||||
#define kXULNameSpaceURI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
#define kSVGNameSpaceURI "http://www.w3.org/2000/svg"
|
||||
|
||||
class nsNameSpaceKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef const nsAString* KeyType;
|
||||
typedef const nsAString* KeyTypePointer;
|
||||
StaticAutoPtr<nsNameSpaceManager> nsNameSpaceManager::sInstance;
|
||||
|
||||
nsNameSpaceKey(KeyTypePointer aKey) : mKey(aKey)
|
||||
{
|
||||
}
|
||||
nsNameSpaceKey(const nsNameSpaceKey& toCopy) : mKey(toCopy.mKey)
|
||||
{
|
||||
/* static */ nsNameSpaceManager*
|
||||
nsNameSpaceManager::GetInstance() {
|
||||
if (!sInstance) {
|
||||
sInstance = new nsNameSpaceManager();
|
||||
if (sInstance->Init()) {
|
||||
ClearOnShutdown(&sInstance);
|
||||
} else {
|
||||
delete sInstance;
|
||||
sInstance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
KeyType GetKey() const
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
bool KeyEquals(KeyType aKey) const
|
||||
{
|
||||
return mKey->Equals(*aKey);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey)
|
||||
{
|
||||
return aKey;
|
||||
}
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey) {
|
||||
return HashString(*aKey);
|
||||
}
|
||||
|
||||
enum {
|
||||
ALLOW_MEMMOVE = true
|
||||
};
|
||||
|
||||
private:
|
||||
const nsAString* mKey;
|
||||
};
|
||||
|
||||
class NameSpaceManagerImpl : public nsINameSpaceManager {
|
||||
public:
|
||||
NameSpaceManagerImpl()
|
||||
: mURIToIDTable(32)
|
||||
{
|
||||
}
|
||||
virtual ~NameSpaceManagerImpl()
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsresult RegisterNameSpace(const nsAString& aURI, int32_t& aNameSpaceID);
|
||||
|
||||
nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
|
||||
int32_t GetNameSpaceID(const nsAString& aURI);
|
||||
|
||||
bool HasElementCreator(int32_t aNameSpaceID);
|
||||
|
||||
private:
|
||||
nsresult AddNameSpace(const nsAString& aURI, const int32_t aNameSpaceID);
|
||||
|
||||
nsDataHashtable<nsNameSpaceKey,int32_t> mURIToIDTable;
|
||||
nsTArray< nsAutoPtr<nsString> > mURIArray;
|
||||
};
|
||||
|
||||
static NameSpaceManagerImpl* sNameSpaceManager = nullptr;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(NameSpaceManagerImpl, nsINameSpaceManager)
|
||||
|
||||
nsresult NameSpaceManagerImpl::Init()
|
||||
bool nsNameSpaceManager::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
#define REGISTER_NAMESPACE(uri, id) \
|
||||
rv = AddNameSpace(NS_LITERAL_STRING(uri), id); \
|
||||
NS_ENSURE_SUCCESS(rv, rv)
|
||||
NS_ENSURE_SUCCESS(rv, false)
|
||||
|
||||
// Need to be ordered according to ID.
|
||||
REGISTER_NAMESPACE(kXMLNSNameSpaceURI, kNameSpaceID_XMLNS);
|
||||
@ -126,12 +73,12 @@ nsresult NameSpaceManagerImpl::Init()
|
||||
|
||||
#undef REGISTER_NAMESPACE
|
||||
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NameSpaceManagerImpl::RegisterNameSpace(const nsAString& aURI,
|
||||
int32_t& aNameSpaceID)
|
||||
nsNameSpaceManager::RegisterNameSpace(const nsAString& aURI,
|
||||
int32_t& aNameSpaceID)
|
||||
{
|
||||
if (aURI.IsEmpty()) {
|
||||
aNameSpaceID = kNameSpaceID_None; // xmlns="", see bug 75700 for details
|
||||
@ -155,7 +102,7 @@ NameSpaceManagerImpl::RegisterNameSpace(const nsAString& aURI,
|
||||
}
|
||||
|
||||
nsresult
|
||||
NameSpaceManagerImpl::GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI)
|
||||
nsNameSpaceManager::GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI)
|
||||
{
|
||||
NS_PRECONDITION(aNameSpaceID >= 0, "Bogus namespace ID");
|
||||
|
||||
@ -172,7 +119,7 @@ NameSpaceManagerImpl::GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI)
|
||||
}
|
||||
|
||||
int32_t
|
||||
NameSpaceManagerImpl::GetNameSpaceID(const nsAString& aURI)
|
||||
nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI)
|
||||
{
|
||||
if (aURI.IsEmpty()) {
|
||||
return kNameSpaceID_None; // xmlns="", see bug 75700 for details
|
||||
@ -216,7 +163,7 @@ NS_NewElement(Element** aResult,
|
||||
}
|
||||
|
||||
bool
|
||||
NameSpaceManagerImpl::HasElementCreator(int32_t aNameSpaceID)
|
||||
nsNameSpaceManager::HasElementCreator(int32_t aNameSpaceID)
|
||||
{
|
||||
return aNameSpaceID == kNameSpaceID_XHTML ||
|
||||
#ifdef MOZ_XUL
|
||||
@ -227,8 +174,8 @@ NameSpaceManagerImpl::HasElementCreator(int32_t aNameSpaceID)
|
||||
false;
|
||||
}
|
||||
|
||||
nsresult NameSpaceManagerImpl::AddNameSpace(const nsAString& aURI,
|
||||
const int32_t aNameSpaceID)
|
||||
nsresult nsNameSpaceManager::AddNameSpace(const nsAString& aURI,
|
||||
const int32_t aNameSpaceID)
|
||||
{
|
||||
if (aNameSpaceID < 0) {
|
||||
// We've wrapped... Can't do anything else here; just bail.
|
||||
@ -248,32 +195,3 @@ nsresult NameSpaceManagerImpl::AddNameSpace(const nsAString& aURI,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetNameSpaceManager(nsINameSpaceManager** aInstancePtrResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInstancePtrResult);
|
||||
|
||||
if (!sNameSpaceManager) {
|
||||
nsCOMPtr<NameSpaceManagerImpl> manager = new NameSpaceManagerImpl();
|
||||
if (manager) {
|
||||
nsresult rv = manager->Init();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
manager.swap(sNameSpaceManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aInstancePtrResult = sNameSpaceManager;
|
||||
NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ADDREF(*aInstancePtrResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
NS_NameSpaceManagerShutdown()
|
||||
{
|
||||
NS_IF_RELEASE(sNameSpaceManager);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "nsLWBrkCIID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsString.h"
|
||||
#include "prprf.h"
|
||||
|
@ -8,9 +8,9 @@
|
||||
*/
|
||||
|
||||
#include "nsXMLNameSpaceMap.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
template <>
|
||||
class nsDefaultComparator <nsNameSpaceEntry, nsIAtom*> {
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsError.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsRuleData.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsMappedAttributeElement.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsINameSpaceManager.h" // for kNameSpaceID_None
|
||||
#include "nsNameSpaceManager.h" // for kNameSpaceID_None
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIDOMHTMLMapElement.h"
|
||||
#include "nsICookieService.h"
|
||||
#include "nsTArray.h"
|
||||
@ -60,6 +59,7 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
#include "nsIParserService.h"
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIDOMHTMLHeadElement.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
|
@ -371,6 +371,14 @@ MediaSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
return MediaSourceBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::NotifyEvicted(double aStart, double aEnd)
|
||||
{
|
||||
// Cycle through all SourceBuffers and tell them to evict data in
|
||||
// the given range.
|
||||
mSourceBuffers->Evict(aStart, aEnd);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(MediaSource, nsDOMEventTargetHelper,
|
||||
mSourceBuffers, mActiveSourceBuffers)
|
||||
|
||||
|
@ -85,6 +85,11 @@ public:
|
||||
return mDecoder;
|
||||
}
|
||||
|
||||
// Called by SourceBuffers to notify this MediaSource that data has
|
||||
// been evicted from the buffered data. The start and end times
|
||||
// that were evicted are provided.
|
||||
void NotifyEvicted(double aStart, double aEnd);
|
||||
|
||||
private:
|
||||
explicit MediaSource(nsPIDOMWindow* aWindow);
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "MediaSource.h"
|
||||
#include "SubBufferDecoder.h"
|
||||
#include "SourceBufferResource.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaSourceLog;
|
||||
@ -238,4 +239,12 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
double
|
||||
MediaSourceDecoder::GetMediaSourceDuration()
|
||||
{
|
||||
return mMediaSource ?
|
||||
mMediaSource->Duration() :
|
||||
mDuration / static_cast<double>(USECS_PER_S);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -79,6 +79,10 @@ public:
|
||||
return mAudioReader;
|
||||
}
|
||||
|
||||
// Returns the duration in seconds as provided by the attached MediaSource.
|
||||
// If no MediaSource is attached, returns the duration tracked by the decoder.
|
||||
double GetMediaSourceDuration();
|
||||
|
||||
private:
|
||||
dom::MediaSource* mMediaSource;
|
||||
|
||||
|
@ -96,6 +96,23 @@ SubBufferDecoder::GetImageContainer()
|
||||
return mParentDecoder->GetImageContainer();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SubBufferDecoder::ConvertToByteOffset(double aTime)
|
||||
{
|
||||
// Uses a conversion based on (aTime/duration) * length. For the
|
||||
// purposes of eviction this should be adequate since we have the
|
||||
// byte threshold as well to ensure data actually gets evicted and
|
||||
// we ensure we don't evict before the current playable point.
|
||||
double duration = mParentDecoder->GetMediaSourceDuration();
|
||||
if (duration <= 0.0 || IsNaN(duration)) {
|
||||
return -1;
|
||||
}
|
||||
int64_t length = GetResource()->GetLength();
|
||||
MOZ_ASSERT(length > 0);
|
||||
int64_t offset = (aTime / duration) * length;
|
||||
return offset;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
void
|
||||
@ -330,7 +347,56 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
||||
mDecoder->GetResource()->GetLength());
|
||||
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
|
||||
mDecoder->GetResource()->AppendData(aData, aLength);
|
||||
|
||||
// Eviction uses a byte threshold. If the buffer is greater than the
|
||||
// number of bytes then data is evicted. The time range for this
|
||||
// eviction is reported back to the media source. It will then
|
||||
// evict data before that range across all SourceBuffer's it knows
|
||||
// about.
|
||||
const int evict_threshold = 1000000;
|
||||
bool evicted = mDecoder->GetResource()->EvictData(evict_threshold);
|
||||
if (evicted) {
|
||||
double start = 0.0;
|
||||
double end = 0.0;
|
||||
GetBufferedStartEndTime(&start, &end);
|
||||
|
||||
// We notify that we've evicted from the time range 0 through to
|
||||
// the current start point.
|
||||
mMediaSource->NotifyEvicted(0.0, start);
|
||||
}
|
||||
StopUpdating();
|
||||
|
||||
// Schedule the state machine thread to ensure playback starts
|
||||
// if required when data is appended.
|
||||
mMediaSource->GetDecoder()->ScheduleStateMachineThread();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::GetBufferedStartEndTime(double* aStart, double* aEnd)
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
mDecoder->GetBuffered(ranges);
|
||||
ranges->Normalize();
|
||||
int length = ranges->Length();
|
||||
ErrorResult rv;
|
||||
|
||||
if (aStart) {
|
||||
*aStart = length > 0 ? ranges->Start(0, rv) : 0.0;
|
||||
}
|
||||
|
||||
if (aEnd) {
|
||||
*aEnd = length > 0 ? ranges->End(length - 1, rv) : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Evict(double aStart, double aEnd)
|
||||
{
|
||||
// Need to map time to byte offset then evict
|
||||
int64_t end = mDecoder->ConvertToByteOffset(aEnd);
|
||||
if (end > 0) {
|
||||
mDecoder->GetResource()->EvictBefore(end);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(SourceBuffer, nsDOMEventTargetHelper, mMediaSource)
|
||||
|
@ -105,6 +105,9 @@ public:
|
||||
|
||||
void Ended();
|
||||
|
||||
// Evict data in the source buffer in the given time range.
|
||||
void Evict(double aStart, double aEnd);
|
||||
|
||||
private:
|
||||
friend class AsyncEventRunner<SourceBuffer>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
@ -118,6 +121,10 @@ private:
|
||||
// Shared implementation of AppendBuffer overloads.
|
||||
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
|
||||
|
||||
// Provide the minimum start time and maximum end time that is available
|
||||
// in the data buffered by this SourceBuffer.
|
||||
void GetBufferedStartEndTime(double* aStart, double* aEnd);
|
||||
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
|
||||
nsRefPtr<SubBufferDecoder> mDecoder;
|
||||
|
@ -103,6 +103,14 @@ SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Evict(double aStart, double aEnd)
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Evict(aStart, aEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Ended()
|
||||
{
|
||||
|
@ -73,6 +73,9 @@ public:
|
||||
// Mark all SourceBuffers input buffers as ended.
|
||||
void Ended();
|
||||
|
||||
// Evicts data for the given time range from each SourceBuffer in the list.
|
||||
void Evict(double aStart, double aEnd);
|
||||
|
||||
private:
|
||||
friend class AsyncEventRunner<SourceBufferList>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
|
@ -46,7 +46,9 @@ SourceBufferResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
bool blockingRead = !!aBytes;
|
||||
|
||||
while (blockingRead && !mEnded && mOffset + aCount > GetLength()) {
|
||||
while (blockingRead &&
|
||||
!mEnded &&
|
||||
mOffset + aCount > static_cast<uint64_t>(GetLength())) {
|
||||
LOG(PR_LOG_DEBUG, ("%p SBR::Read waiting for data", this));
|
||||
mon.Wait();
|
||||
}
|
||||
@ -65,7 +67,7 @@ SourceBufferResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
memcpy(aBuffer, &mInputBuffer[mOffset], count);
|
||||
mInputBuffer.CopyData(mOffset, count, aBuffer);
|
||||
*aBytes = count;
|
||||
mOffset += count;
|
||||
return NS_OK;
|
||||
@ -124,11 +126,26 @@ SourceBufferResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCo
|
||||
return Read(aBuffer, aCount, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
SourceBufferResource::EvictData(uint32_t aThreshold)
|
||||
{
|
||||
return mInputBuffer.Evict(mOffset, aThreshold);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferResource::EvictBefore(uint64_t aOffset)
|
||||
{
|
||||
// If aOffset is past the current playback offset we don't evict.
|
||||
if (aOffset < mOffset) {
|
||||
mInputBuffer.Evict(aOffset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferResource::AppendData(const uint8_t* aData, uint32_t aLength)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
mInputBuffer.AppendElements(aData, aLength);
|
||||
mInputBuffer.PushBack(new ResourceItem(aData, aLength));
|
||||
mon.NotifyAll();
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef MOZILLA_SOURCEBUFFERRESOURCE_H_
|
||||
#define MOZILLA_SOURCEBUFFERRESOURCE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include "MediaCache.h"
|
||||
#include "MediaResource.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
@ -16,6 +17,7 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
@ -32,6 +34,149 @@ class SourceBuffer;
|
||||
|
||||
class SourceBufferResource MOZ_FINAL : public MediaResource
|
||||
{
|
||||
private:
|
||||
// A SourceBufferResource has a queue containing the data
|
||||
// that is appended to it. The queue holds instances of
|
||||
// ResourceItem which is an array of the bytes. Appending
|
||||
// data to the SourceBufferResource pushes this onto the
|
||||
// queue. As items are played they are taken off the front
|
||||
// of the queue.
|
||||
// Data is evicted once it reaches a size threshold. This
|
||||
// pops the items off the front of the queue and deletes it.
|
||||
// If an eviction happens then the MediaSource is notified
|
||||
// (done in SourceBuffer::AppendData) which then requests
|
||||
// all SourceBuffers to evict data up to approximately
|
||||
// the same timepoint.
|
||||
struct ResourceItem {
|
||||
ResourceItem(uint8_t const* aData, uint32_t aSize) {
|
||||
mData.AppendElements(aData, aSize);
|
||||
}
|
||||
nsTArray<uint8_t> mData;
|
||||
};
|
||||
|
||||
class ResourceQueueDeallocator : public nsDequeFunctor {
|
||||
virtual void* operator() (void* anObject) {
|
||||
delete static_cast<ResourceItem*>(anObject);
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class ResourceQueue : private nsDeque {
|
||||
private:
|
||||
// Logical offset into the resource of the first element
|
||||
// in the queue.
|
||||
uint64_t mOffset;
|
||||
|
||||
public:
|
||||
ResourceQueue() :
|
||||
nsDeque(new ResourceQueueDeallocator()),
|
||||
mOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Clears all items from the queue
|
||||
inline void Clear() {
|
||||
return nsDeque::Erase();
|
||||
}
|
||||
|
||||
// Returns the number of items in the queue
|
||||
inline uint32_t GetSize() {
|
||||
return nsDeque::GetSize();
|
||||
}
|
||||
|
||||
// Returns the logical byte offset of the start of the data.
|
||||
inline uint64_t GetOffset() {
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
inline ResourceItem* ResourceAt(uint32_t aIndex) {
|
||||
return static_cast<ResourceItem*>(nsDeque::ObjectAt(aIndex));
|
||||
}
|
||||
|
||||
// Returns the length of all items in the queue plus the offset.
|
||||
// This is the logical length of the resource.
|
||||
inline uint64_t GetLength() {
|
||||
uint64_t s = mOffset;
|
||||
for (uint32_t i = 0; i < GetSize(); ++i) {
|
||||
ResourceItem* item = ResourceAt(i);
|
||||
s += item->mData.Length();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Returns the index of the resource that contains the given
|
||||
// logical offset. aResourceOffset will contain the offset into
|
||||
// the resource at the given index returned if it is not null. If
|
||||
// no such resource exists, returns GetSize() and aOffset is
|
||||
// untouched.
|
||||
inline uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) {
|
||||
uint64_t offset = mOffset;
|
||||
for (uint32_t i = 0; i < GetSize(); ++i) {
|
||||
ResourceItem* item = ResourceAt(i);
|
||||
// If the item contains the start of the offset we want to
|
||||
// break out of the loop.
|
||||
if (item->mData.Length() + offset > aOffset) {
|
||||
if (aResourceOffset) {
|
||||
*aResourceOffset = aOffset - offset;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
offset += item->mData.Length();
|
||||
}
|
||||
return GetSize();
|
||||
}
|
||||
|
||||
// Copies aCount bytes from aOffset in the queue into aDest.
|
||||
inline void CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
|
||||
uint32_t offset = 0;
|
||||
uint32_t start = GetAtOffset(aOffset, &offset);
|
||||
uint32_t end = std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, GetSize());
|
||||
for (uint32_t i = start; i < end; ++i) {
|
||||
ResourceItem* item = ResourceAt(i);
|
||||
uint32_t bytes = std::min(aCount, item->mData.Length() - offset);
|
||||
if (bytes != 0) {
|
||||
memcpy(aDest, &item->mData[offset], bytes);
|
||||
offset = 0;
|
||||
aCount -= bytes;
|
||||
aDest += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void PushBack(ResourceItem* aItem) {
|
||||
nsDeque::Push(aItem);
|
||||
}
|
||||
|
||||
inline void PushFront(ResourceItem* aItem) {
|
||||
nsDeque::PushFront(aItem);
|
||||
}
|
||||
|
||||
inline ResourceItem* PopBack() {
|
||||
return static_cast<ResourceItem*>(nsDeque::Pop());
|
||||
}
|
||||
|
||||
inline ResourceItem* PopFront() {
|
||||
return static_cast<ResourceItem*>(nsDeque::PopFront());
|
||||
}
|
||||
|
||||
// Evict data in queue if the total queue size is greater than
|
||||
// aThreshold past the offset. Returns true if some data was
|
||||
// actually evicted.
|
||||
inline bool Evict(uint64_t aOffset, uint32_t aThreshold) {
|
||||
bool evicted = false;
|
||||
while (GetLength() - mOffset > aThreshold) {
|
||||
ResourceItem* item = ResourceAt(0);
|
||||
if (item->mData.Length() + mOffset > aOffset) {
|
||||
break;
|
||||
}
|
||||
mOffset += item->mData.Length();
|
||||
delete PopFront();
|
||||
evicted = true;
|
||||
}
|
||||
return evicted;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
SourceBufferResource(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType);
|
||||
@ -62,10 +207,10 @@ public:
|
||||
virtual void Pin() MOZ_OVERRIDE {}
|
||||
virtual void Unpin() MOZ_OVERRIDE {}
|
||||
virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { return 0; }
|
||||
virtual int64_t GetLength() MOZ_OVERRIDE { return mInputBuffer.Length(); }
|
||||
virtual int64_t GetLength() MOZ_OVERRIDE { return mInputBuffer.GetLength(); }
|
||||
virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE { return aOffset; }
|
||||
virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE { return GetLength(); }
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return true; }
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return false; }
|
||||
virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; }
|
||||
virtual bool IsSuspended() MOZ_OVERRIDE { return false; }
|
||||
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE;
|
||||
@ -74,7 +219,8 @@ public:
|
||||
|
||||
virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE
|
||||
{
|
||||
aRanges.AppendElement(MediaByteRange(0, GetLength()));
|
||||
aRanges.AppendElement(MediaByteRange(mInputBuffer.GetOffset(),
|
||||
mInputBuffer.GetLength()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -83,6 +229,12 @@ public:
|
||||
// Used by SourceBuffer.
|
||||
void AppendData(const uint8_t* aData, uint32_t aLength);
|
||||
void Ended();
|
||||
// Remove data from resource if it holds more than the threshold
|
||||
// number of bytes. Returns true if some data was evicted.
|
||||
bool EvictData(uint32_t aThreshold);
|
||||
|
||||
// Remove data from resource before the given offset.
|
||||
void EvictBefore(uint64_t aOffset);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
@ -93,9 +245,11 @@ private:
|
||||
// Notify() (from Seek, AppendData, Ended, or Close) when insufficient
|
||||
// data is available in mData.
|
||||
ReentrantMonitor mMonitor;
|
||||
nsTArray<uint8_t> mInputBuffer;
|
||||
|
||||
int64_t mOffset;
|
||||
// The buffer holding resource data is a queue of ResourceItem's.
|
||||
ResourceQueue mInputBuffer;
|
||||
|
||||
uint64_t mOffset;
|
||||
bool mClosed;
|
||||
bool mEnded;
|
||||
};
|
||||
|
@ -54,6 +54,10 @@ public:
|
||||
return mReader->GetBuffered(aBuffered, 0);
|
||||
}
|
||||
|
||||
// Given a time convert it into an approximate byte offset from the
|
||||
// cached data. Returns -1 if no such value is computable.
|
||||
int64_t ConvertToByteOffset(double aTime);
|
||||
|
||||
private:
|
||||
MediaSourceDecoder* mParentDecoder;
|
||||
nsAutoPtr<MediaDecoderReader> mReader;
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIContentViewer.h"
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
@ -25,12 +25,12 @@
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsParserBase.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsIXULDocument.h"
|
||||
|
@ -34,12 +34,12 @@
|
||||
#include "nsIDOMXULCommandDispatcher.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
|
@ -24,7 +24,6 @@ class nsString;
|
||||
class nsIRDFResource;
|
||||
class nsIRDFLiteral;
|
||||
class nsIRDFService;
|
||||
class nsINameSpaceManager;
|
||||
class nsIDateTimeFormat;
|
||||
class nsICollation;
|
||||
|
||||
|
@ -24,9 +24,9 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsQuickSort.h"
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFInferDataSource.h"
|
||||
@ -45,6 +44,7 @@
|
||||
#include "nsIURL.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsString.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsAttrName.h"
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsTreeContentView.h"
|
||||
|
1399
dom/base/Console.cpp
Normal file
1399
dom/base/Console.cpp
Normal file
File diff suppressed because it is too large
Load Diff
203
dom/base/Console.h
Normal file
203
dom/base/Console.h
Normal file
@ -0,0 +1,203 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_Console_h
|
||||
#define mozilla_dom_Console_h
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/UnionConversions.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsIConsoleAPIStorage;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ConsoleCallData;
|
||||
class ConsoleStackEntry;
|
||||
|
||||
class Console MOZ_FINAL : public nsITimerCallback
|
||||
, public nsIObserver
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console,
|
||||
nsITimerCallback)
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
Console(nsPIDOMWindow* aWindow);
|
||||
~Console();
|
||||
|
||||
// WebIDL methods
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
void
|
||||
Log(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Info(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Warn(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Error(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Exception(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Debug(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Trace(JSContext* aCx);
|
||||
|
||||
void
|
||||
Dir(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Group(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
GroupCollapsed(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
GroupEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Time(JSContext* aCx, const JS::Handle<JS::Value> aTime);
|
||||
|
||||
void
|
||||
TimeEnd(JSContext* aCx, const JS::Handle<JS::Value> aTime);
|
||||
|
||||
void
|
||||
Profile(JSContext* aCx, const Sequence<JS::Value>& aData,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Assert(JSContext* aCx, bool aCondition, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
Count(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
__noSuchMethod__();
|
||||
|
||||
private:
|
||||
enum MethodName
|
||||
{
|
||||
MethodLog,
|
||||
MethodInfo,
|
||||
MethodWarn,
|
||||
MethodError,
|
||||
MethodException,
|
||||
MethodDebug,
|
||||
MethodTrace,
|
||||
MethodDir,
|
||||
MethodGroup,
|
||||
MethodGroupCollapsed,
|
||||
MethodGroupEnd,
|
||||
MethodTime,
|
||||
MethodTimeEnd,
|
||||
MethodAssert,
|
||||
MethodCount
|
||||
};
|
||||
|
||||
void
|
||||
Method(JSContext* aCx, MethodName aName, const nsAString& aString,
|
||||
const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
AppendCallData(const ConsoleCallData& aData);
|
||||
|
||||
void
|
||||
ProcessCallData(ConsoleCallData& aData);
|
||||
|
||||
// If the first JS::Value of the array is a string, this method uses it to
|
||||
// format a string. The supported sequences are:
|
||||
// %s - string
|
||||
// %d,%i - integer
|
||||
// %f - double
|
||||
// %o - a JS object.
|
||||
// The output is an array where any object is a separated item, the rest is
|
||||
// unified in a format string.
|
||||
// Example if the input is:
|
||||
// "string: %s, integer: %d, object: %o, double: %d", 's', 1, window, 0.9
|
||||
// The output will be:
|
||||
// [ "string: s, integer: 1, object: ", window, ", double: 0.9" ]
|
||||
void
|
||||
ProcessArguments(JSContext* aCx, const nsTArray<JS::Heap<JS::Value>>& aData,
|
||||
Sequence<JS::Value>& aSequence);
|
||||
|
||||
void
|
||||
MakeFormatString(nsCString& aFormat, int32_t aInteger, int32_t aMantissa,
|
||||
char aCh);
|
||||
|
||||
// Stringify and Concat all the JS::Value in a single string using ' ' as
|
||||
// separator.
|
||||
void
|
||||
ComposeGroupName(JSContext* aCx, const nsTArray<JS::Heap<JS::Value>>& aData,
|
||||
nsAString& aName);
|
||||
|
||||
JS::Value
|
||||
StartTimer(JSContext* aCx, const JS::Value& aName,
|
||||
DOMHighResTimeStamp aTimestamp);
|
||||
|
||||
JS::Value
|
||||
StopTimer(JSContext* aCx, const JS::Value& aName,
|
||||
DOMHighResTimeStamp aTimestamp);
|
||||
|
||||
// The method populates a Sequence from an array of JS::Value.
|
||||
void
|
||||
ArgumentsToValueList(const nsTArray<JS::Heap<JS::Value>>& aData,
|
||||
Sequence<JS::Value>& aSequence);
|
||||
|
||||
void
|
||||
ProfileMethod(JSContext* aCx, const nsAString& aAction,
|
||||
const Sequence<JS::Value>& aData,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JS::Value
|
||||
IncreaseCounter(JSContext* aCx, const ConsoleStackEntry& aFrame,
|
||||
const nsTArray<JS::Heap<JS::Value>>& aArguments);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
|
||||
nsTArray<ConsoleCallData> mQueuedCalls;
|
||||
nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
|
||||
nsDataHashtable<nsStringHashKey, uint32_t> mCounterRegistry;
|
||||
|
||||
uint64_t mOuterID;
|
||||
uint64_t mInnerID;
|
||||
|
||||
friend class ConsoleCallData;
|
||||
friend class ConsoleCallDataRunnable;
|
||||
friend class ConsoleProfileRunnable;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif /* mozilla_dom_Console_h */
|
@ -1,560 +0,0 @@
|
||||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
|
||||
// The maximum allowed number of concurrent timers per page.
|
||||
const MAX_PAGE_TIMERS = 10000;
|
||||
|
||||
// The maximum allowed number of concurrent counters per page.
|
||||
const MAX_PAGE_COUNTERS = 10000;
|
||||
|
||||
// The regular expression used to parse %s/%d and other placeholders for
|
||||
// variables in strings that need to be interpolated.
|
||||
const ARGUMENT_PATTERN = /%\d*\.?\d*([osdif])\b/g;
|
||||
|
||||
// The maximum stacktrace depth when populating the stacktrace array used for
|
||||
// console.trace().
|
||||
const DEFAULT_MAX_STACKTRACE_DEPTH = 200;
|
||||
|
||||
// The console API methods are async and their action is executed later. This
|
||||
// delay tells how much later.
|
||||
const CALL_DELAY = 15; // milliseconds
|
||||
|
||||
// This constant tells how many messages to process in a single timer execution.
|
||||
const MESSAGES_IN_INTERVAL = 1500;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm");
|
||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
/**
|
||||
* The window.console API implementation. One instance is lazily created for
|
||||
* every inner window, when the window.console object is accessed.
|
||||
*/
|
||||
function ConsoleAPI() {}
|
||||
ConsoleAPI.prototype = {
|
||||
|
||||
classID: Components.ID("{b49c18f8-3379-4fc0-8c90-d7772c1a9ff3}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
_timerInitialized: false,
|
||||
_queuedCalls: null,
|
||||
_window: null,
|
||||
_innerID: null,
|
||||
_outerID: null,
|
||||
_windowDestroyed: false,
|
||||
_timer: null,
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer
|
||||
init: function CA_init(aWindow) {
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", true);
|
||||
|
||||
try {
|
||||
let windowUtils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
this._outerID = windowUtils.outerWindowID;
|
||||
this._innerID = windowUtils.currentInnerWindowID;
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
let chromeObject = {
|
||||
// window.console API
|
||||
log: function CA_log() {
|
||||
self.queueCall("log", arguments);
|
||||
},
|
||||
info: function CA_info() {
|
||||
self.queueCall("info", arguments);
|
||||
},
|
||||
warn: function CA_warn() {
|
||||
self.queueCall("warn", arguments);
|
||||
},
|
||||
error: function CA_error() {
|
||||
self.queueCall("error", arguments);
|
||||
},
|
||||
exception: function CA_exception() {
|
||||
self.queueCall("exception", arguments);
|
||||
},
|
||||
debug: function CA_debug() {
|
||||
self.queueCall("debug", arguments);
|
||||
},
|
||||
trace: function CA_trace() {
|
||||
self.queueCall("trace", arguments);
|
||||
},
|
||||
// Displays an interactive listing of all the properties of an object.
|
||||
dir: function CA_dir() {
|
||||
self.queueCall("dir", arguments);
|
||||
},
|
||||
group: function CA_group() {
|
||||
self.queueCall("group", arguments);
|
||||
},
|
||||
groupCollapsed: function CA_groupCollapsed() {
|
||||
self.queueCall("groupCollapsed", arguments);
|
||||
},
|
||||
groupEnd: function CA_groupEnd() {
|
||||
self.queueCall("groupEnd", arguments);
|
||||
},
|
||||
time: function CA_time() {
|
||||
self.queueCall("time", arguments);
|
||||
},
|
||||
timeEnd: function CA_timeEnd() {
|
||||
self.queueCall("timeEnd", arguments);
|
||||
},
|
||||
profile: function CA_profile() {
|
||||
// Send a notification picked up by the profiler if installed.
|
||||
// This must happen right away otherwise we will miss samples
|
||||
let consoleEvent = {
|
||||
action: "profile",
|
||||
arguments: arguments
|
||||
};
|
||||
consoleEvent.wrappedJSObject = consoleEvent;
|
||||
Services.obs.notifyObservers(consoleEvent, "console-api-profiler",
|
||||
null);
|
||||
},
|
||||
profileEnd: function CA_profileEnd() {
|
||||
// Send a notification picked up by the profiler if installed.
|
||||
// This must happen right away otherwise we will miss samples
|
||||
let consoleEvent = {
|
||||
action: "profileEnd",
|
||||
arguments: arguments
|
||||
};
|
||||
consoleEvent.wrappedJSObject = consoleEvent;
|
||||
Services.obs.notifyObservers(consoleEvent, "console-api-profiler",
|
||||
null);
|
||||
},
|
||||
assert: function CA_assert() {
|
||||
let args = Array.prototype.slice.call(arguments);
|
||||
if(!args.shift()) {
|
||||
self.queueCall("assert", args);
|
||||
}
|
||||
},
|
||||
count: function CA_count() {
|
||||
self.queueCall("count", arguments);
|
||||
},
|
||||
__exposedProps__: {
|
||||
log: "r",
|
||||
info: "r",
|
||||
warn: "r",
|
||||
error: "r",
|
||||
exception: "r",
|
||||
debug: "r",
|
||||
trace: "r",
|
||||
dir: "r",
|
||||
group: "r",
|
||||
groupCollapsed: "r",
|
||||
groupEnd: "r",
|
||||
time: "r",
|
||||
timeEnd: "r",
|
||||
profile: "r",
|
||||
profileEnd: "r",
|
||||
assert: "r",
|
||||
count: "r"
|
||||
}
|
||||
};
|
||||
|
||||
// We need to return an actual content object here, instead of a wrapped
|
||||
// chrome object. This allows things like console.log.bind() to work.
|
||||
let contentObj = Cu.createObjectIn(aWindow);
|
||||
function genPropDesc(fun) {
|
||||
return { enumerable: true, configurable: true, writable: true,
|
||||
value: chromeObject[fun].bind(chromeObject) };
|
||||
}
|
||||
const properties = {
|
||||
log: genPropDesc('log'),
|
||||
info: genPropDesc('info'),
|
||||
warn: genPropDesc('warn'),
|
||||
error: genPropDesc('error'),
|
||||
exception: genPropDesc('exception'),
|
||||
debug: genPropDesc('debug'),
|
||||
trace: genPropDesc('trace'),
|
||||
dir: genPropDesc('dir'),
|
||||
group: genPropDesc('group'),
|
||||
groupCollapsed: genPropDesc('groupCollapsed'),
|
||||
groupEnd: genPropDesc('groupEnd'),
|
||||
time: genPropDesc('time'),
|
||||
timeEnd: genPropDesc('timeEnd'),
|
||||
profile: genPropDesc('profile'),
|
||||
profileEnd: genPropDesc('profileEnd'),
|
||||
assert: genPropDesc('assert'),
|
||||
count: genPropDesc('count'),
|
||||
__noSuchMethod__: { enumerable: true, configurable: true, writable: true,
|
||||
value: function() {} },
|
||||
__mozillaConsole__: { value: true }
|
||||
};
|
||||
|
||||
Object.defineProperties(contentObj, properties);
|
||||
Cu.makeObjectPropsNormal(contentObj);
|
||||
|
||||
this._queuedCalls = [];
|
||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._window = Cu.getWeakReference(aWindow);
|
||||
this.timerRegistry = new Map();
|
||||
this.counterRegistry = new Map();
|
||||
|
||||
return contentObj;
|
||||
},
|
||||
|
||||
observe: function CA_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == "inner-window-destroyed") {
|
||||
let innerWindowID = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (innerWindowID == this._innerID) {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._windowDestroyed = true;
|
||||
if (!this._timerInitialized) {
|
||||
this.timerRegistry.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Queue a call to a console method. See the CALL_DELAY constant.
|
||||
* This method is the entry point for the console.* for workers.
|
||||
*
|
||||
* @param string aMethod
|
||||
* The console method the code has invoked.
|
||||
* @param object aArguments
|
||||
* The arguments passed to the console method.
|
||||
* @param array aStack
|
||||
* The stack of the console method. Used by console.* for workers.
|
||||
*/
|
||||
queueCall: function CA_queueCall(aMethod, aArguments, aStack = null)
|
||||
{
|
||||
let window = this._window.get();
|
||||
let metaForCall = {
|
||||
private: PrivateBrowsingUtils.isWindowPrivate(window),
|
||||
timeStamp: Date.now(),
|
||||
stack: (aStack ? aStack : this.getStackTrace(aMethod != "trace" ? 1 : null)),
|
||||
};
|
||||
|
||||
if (aMethod == "time" || aMethod == "timeEnd") {
|
||||
metaForCall.monotonicTimer = window.performance.now();
|
||||
}
|
||||
|
||||
this._queuedCalls.push([aMethod, aArguments, metaForCall]);
|
||||
|
||||
if (!this._timerInitialized) {
|
||||
this._timer.initWithCallback(this._timerCallback.bind(this), CALL_DELAY,
|
||||
Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||
this._timerInitialized = true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Timer callback used to process each of the queued calls.
|
||||
* @private
|
||||
*/
|
||||
_timerCallback: function CA__timerCallback()
|
||||
{
|
||||
this._queuedCalls.splice(0, MESSAGES_IN_INTERVAL)
|
||||
.forEach(this._processQueuedCall, this);
|
||||
|
||||
if (!this._queuedCalls.length) {
|
||||
this._timerInitialized = false;
|
||||
this._timer.cancel();
|
||||
|
||||
if (this._windowDestroyed) {
|
||||
ConsoleAPIStorage.clearEvents(this._innerID);
|
||||
this.timerRegistry.clear();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Process a queued call to a console method.
|
||||
*
|
||||
* @private
|
||||
* @param array aCall
|
||||
* Array that holds information about the queued call.
|
||||
*/
|
||||
_processQueuedCall: function CA__processQueuedItem(aCall)
|
||||
{
|
||||
let [method, args, meta] = aCall;
|
||||
|
||||
let frame;
|
||||
if (meta.stack.length) {
|
||||
frame = meta.stack[0];
|
||||
} else {
|
||||
frame = {
|
||||
filename: "",
|
||||
lineNumber: 0,
|
||||
functionName: "",
|
||||
};
|
||||
}
|
||||
|
||||
let consoleEvent = {
|
||||
ID: this._outerID,
|
||||
innerID: this._innerID,
|
||||
level: method,
|
||||
filename: frame.filename,
|
||||
lineNumber: frame.lineNumber,
|
||||
functionName: frame.functionName,
|
||||
timeStamp: meta.timeStamp,
|
||||
arguments: args,
|
||||
private: meta.private,
|
||||
};
|
||||
|
||||
switch (method) {
|
||||
case "log":
|
||||
case "info":
|
||||
case "warn":
|
||||
case "error":
|
||||
case "exception":
|
||||
case "debug":
|
||||
case "assert":
|
||||
consoleEvent.arguments = this.processArguments(args);
|
||||
break;
|
||||
case "trace":
|
||||
consoleEvent.stacktrace = meta.stack;
|
||||
break;
|
||||
case "group":
|
||||
case "groupCollapsed":
|
||||
case "groupEnd":
|
||||
try {
|
||||
consoleEvent.groupName = Array.prototype.join.call(args, " ");
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
Cu.reportError(ex.stack);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "dir":
|
||||
break;
|
||||
case "time":
|
||||
consoleEvent.timer = this.startTimer(args[0], meta.monotonicTimer);
|
||||
break;
|
||||
case "timeEnd":
|
||||
consoleEvent.timer = this.stopTimer(args[0], meta.monotonicTimer);
|
||||
break;
|
||||
case "count":
|
||||
consoleEvent.counter = this.increaseCounter(frame, args[0]);
|
||||
break;
|
||||
default:
|
||||
// unknown console API method!
|
||||
return;
|
||||
}
|
||||
|
||||
this.notifyObservers(method, consoleEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify all observers of any console API call.
|
||||
*
|
||||
* @param string aLevel
|
||||
* The message level.
|
||||
* @param object aConsoleEvent
|
||||
* The console event object to send to observers for the given console
|
||||
* API call.
|
||||
*/
|
||||
notifyObservers: function CA_notifyObservers(aLevel, aConsoleEvent)
|
||||
{
|
||||
aConsoleEvent.wrappedJSObject = aConsoleEvent;
|
||||
ConsoleAPIStorage.recordEvent(this._innerID, aConsoleEvent);
|
||||
Services.obs.notifyObservers(aConsoleEvent, "console-api-log-event",
|
||||
this._outerID);
|
||||
},
|
||||
|
||||
/**
|
||||
* Process the console API call arguments in order to perform printf-like
|
||||
* string substitution.
|
||||
*
|
||||
* TODO: object substitution should take into account width and precision
|
||||
* qualifiers (bug 685813).
|
||||
*
|
||||
* @param mixed aArguments
|
||||
* The arguments given to the console API call.
|
||||
**/
|
||||
processArguments: function CA_processArguments(aArguments) {
|
||||
if (aArguments.length < 2 || typeof aArguments[0] != "string") {
|
||||
return aArguments;
|
||||
}
|
||||
|
||||
let args = Array.prototype.slice.call(aArguments);
|
||||
let format = args.shift();
|
||||
let splitter = "%" + format.length + Date.now() + "%";
|
||||
let objects = [];
|
||||
|
||||
// Format specification regular expression.
|
||||
let processed = format.replace(ARGUMENT_PATTERN, function CA_PA_substitute(match, submatch) {
|
||||
switch (submatch) {
|
||||
case "o":
|
||||
objects.push(args.shift());
|
||||
return splitter;
|
||||
case "s":
|
||||
return String(args.shift());
|
||||
case "d":
|
||||
case "i":
|
||||
return parseInt(args.shift());
|
||||
case "f":
|
||||
return parseFloat(args.shift());
|
||||
default:
|
||||
return submatch;
|
||||
};
|
||||
});
|
||||
|
||||
let result = [];
|
||||
let processedArray = processed.split(splitter);
|
||||
processedArray.forEach(function(aValue, aIndex) {
|
||||
if (aValue !== "") {
|
||||
result.push(aValue);
|
||||
}
|
||||
if (objects[aIndex]) {
|
||||
result.push(objects[aIndex]);
|
||||
}
|
||||
});
|
||||
|
||||
return result.concat(args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Build the stacktrace array for the console.trace() call.
|
||||
*
|
||||
* @param number [aMaxDepth=DEFAULT_MAX_STACKTRACE_DEPTH]
|
||||
* Optional maximum stacktrace depth.
|
||||
* @return array
|
||||
* Each element is a stack frame that holds the following properties:
|
||||
* filename, lineNumber, functionName and language.
|
||||
*/
|
||||
getStackTrace: function CA_getStackTrace(aMaxDepth) {
|
||||
if (!aMaxDepth) {
|
||||
aMaxDepth = DEFAULT_MAX_STACKTRACE_DEPTH;
|
||||
}
|
||||
|
||||
let stack = [];
|
||||
let frame = Components.stack.caller.caller;
|
||||
while (frame = frame.caller) {
|
||||
if (frame.language == Ci.nsIProgrammingLanguage.JAVASCRIPT ||
|
||||
frame.language == Ci.nsIProgrammingLanguage.JAVASCRIPT2) {
|
||||
stack.push({
|
||||
filename: frame.filename,
|
||||
lineNumber: frame.lineNumber,
|
||||
functionName: frame.name,
|
||||
language: frame.language,
|
||||
});
|
||||
if (stack.length == aMaxDepth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stack;
|
||||
},
|
||||
|
||||
/*
|
||||
* A registry of started timers.
|
||||
* @type Map
|
||||
*/
|
||||
timerRegistry: null,
|
||||
|
||||
/**
|
||||
* Create a new timer by recording the current time under the specified name.
|
||||
*
|
||||
* @param string aName
|
||||
* The name of the timer.
|
||||
* @param number aTimestamp
|
||||
* A monotonic strictly-increasing timing value that tells when the
|
||||
* timer was started.
|
||||
* @return object
|
||||
* The name property holds the timer name and the started property
|
||||
* holds the time the timer was started. In case of error, it returns
|
||||
* an object with the single property "error" that contains the key
|
||||
* for retrieving the localized error message.
|
||||
**/
|
||||
startTimer: function CA_startTimer(aName, aTimestamp) {
|
||||
if (!aName) {
|
||||
return;
|
||||
}
|
||||
if (this.timerRegistry.size > MAX_PAGE_TIMERS - 1) {
|
||||
return { error: "maxTimersExceeded" };
|
||||
}
|
||||
let key = aName.toString();
|
||||
if (!this.timerRegistry.has(key)) {
|
||||
this.timerRegistry.set(key, aTimestamp);
|
||||
}
|
||||
return { name: aName, started: this.timerRegistry.get(key) };
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop the timer with the specified name and retrieve the elapsed time.
|
||||
*
|
||||
* @param string aName
|
||||
* The name of the timer.
|
||||
* @param number aTimestamp
|
||||
* A monotonic strictly-increasing timing value that tells when the
|
||||
* timer was stopped.
|
||||
* @return object
|
||||
* The name property holds the timer name and the duration property
|
||||
* holds the number of milliseconds since the timer was started.
|
||||
**/
|
||||
stopTimer: function CA_stopTimer(aName, aTimestamp) {
|
||||
if (!aName) {
|
||||
return;
|
||||
}
|
||||
let key = aName.toString();
|
||||
if (!this.timerRegistry.has(key)) {
|
||||
return;
|
||||
}
|
||||
let duration = aTimestamp - this.timerRegistry.get(key);
|
||||
this.timerRegistry.delete(key);
|
||||
return { name: aName, duration: duration };
|
||||
},
|
||||
|
||||
/*
|
||||
* A registry of counsole.count() counters.
|
||||
* @type Map
|
||||
*/
|
||||
counterRegistry: null,
|
||||
|
||||
/**
|
||||
* Increases the given counter by one or creates a new counter if the label
|
||||
* is not known so far.
|
||||
*
|
||||
* @param object aFrame
|
||||
* The current stack frame to extract the filename and linenumber
|
||||
* from the console.count() invocation.
|
||||
* @param string aLabel
|
||||
* The label of the counter. If no label is provided, the script url
|
||||
* and line number is used for associating the counters
|
||||
* @return object
|
||||
* The label property holds the counters label and the count property
|
||||
* holds the current count.
|
||||
**/
|
||||
increaseCounter: function CA_increaseCounter(aFrame, aLabel) {
|
||||
let key = null, label = null;
|
||||
try {
|
||||
label = key = aLabel ? aLabel + "" : "";
|
||||
} catch (ex) { }
|
||||
if (!key) {
|
||||
key = aFrame.filename + ":" + aFrame.lineNumber;
|
||||
}
|
||||
let counter = null;
|
||||
if (!this.counterRegistry.has(key)) {
|
||||
if (this.counterRegistry.size > MAX_PAGE_COUNTERS - 1) {
|
||||
return { error: "maxCountersExceeded" };
|
||||
}
|
||||
counter = { label: label, count: 1 };
|
||||
this.counterRegistry.set(key, counter);
|
||||
} else {
|
||||
counter = this.counterRegistry.get(key);
|
||||
counter.count += 1;
|
||||
}
|
||||
return { label: counter.label, count: counter.count };
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ConsoleAPI]);
|
@ -1,3 +1,2 @@
|
||||
component {b49c18f8-3379-4fc0-8c90-d7772c1a9ff3} ConsoleAPI.js
|
||||
contract @mozilla.org/console-api;1 {b49c18f8-3379-4fc0-8c90-d7772c1a9ff3}
|
||||
category JavaScript-global-property console @mozilla.org/console-api;1
|
||||
component {96cf7855-dfa9-4c6d-8276-f9705b4890f2} ConsoleAPIStorage.js
|
||||
contract @mozilla.org/consoleAPI-storage;1 {96cf7855-dfa9-4c6d-8276-f9705b4890f2}
|
||||
|
@ -13,10 +13,10 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const STORAGE_MAX_EVENTS = 200;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ConsoleAPIStorage"];
|
||||
|
||||
var _consoleStorage = new Map();
|
||||
|
||||
const CONSOLEAPISTORAGE_CID = Components.ID('{96cf7855-dfa9-4c6d-8276-f9705b4890f2}');
|
||||
|
||||
/**
|
||||
* The ConsoleAPIStorage is meant to cache window.console API calls for later
|
||||
* reuse by other components when needed. For example, the Web Console code can
|
||||
@ -38,9 +38,20 @@ var _consoleStorage = new Map();
|
||||
* // Clear the events for the given inner window ID.
|
||||
* ConsoleAPIStorage.clearEvents(innerWindowID);
|
||||
*/
|
||||
this.ConsoleAPIStorage = {
|
||||
function ConsoleAPIStorageService() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
ConsoleAPIStorageService.prototype = {
|
||||
classID : CONSOLEAPISTORAGE_CID,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleAPIStorage,
|
||||
Ci.nsIObserver]),
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: CONSOLEAPISTORAGE_CID,
|
||||
contractID: '@mozilla.org/consoleAPI-storage;1',
|
||||
interfaces: [Ci.nsIConsoleAPIStorage, Ci.nsIObserver],
|
||||
flags: Ci.nsIClassInfo.SINGLETON
|
||||
}),
|
||||
|
||||
observe: function CS_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
@ -51,7 +62,7 @@ this.ConsoleAPIStorage = {
|
||||
}
|
||||
else if (aTopic == "inner-window-destroyed") {
|
||||
let innerWindowID = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
this.clearEvents(innerWindowID);
|
||||
this.clearEvents(innerWindowID + "");
|
||||
}
|
||||
else if (aTopic == "memory-pressure") {
|
||||
this.clearEvents();
|
||||
@ -140,4 +151,4 @@ this.ConsoleAPIStorage = {
|
||||
},
|
||||
};
|
||||
|
||||
ConsoleAPIStorage.init();
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ConsoleAPIStorageService]);
|
@ -7,6 +7,7 @@
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIConsoleAPIStorage.idl',
|
||||
'nsIDOMDOMCursor.idl',
|
||||
'nsIDOMDOMRequest.idl',
|
||||
'nsIEntropyCollector.idl',
|
||||
@ -49,6 +50,7 @@ EXPORTS += [
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'BarProps.h',
|
||||
'Console.h',
|
||||
'DOMCursor.h',
|
||||
'DOMError.h',
|
||||
'DOMException.h',
|
||||
@ -67,6 +69,7 @@ EXPORTS.mozilla.dom += [
|
||||
UNIFIED_SOURCES += [
|
||||
'BarProps.cpp',
|
||||
'CompositionStringSynthesizer.cpp',
|
||||
'Console.cpp',
|
||||
'Crypto.cpp',
|
||||
'DOMCursor.cpp',
|
||||
'DOMError.cpp',
|
||||
@ -117,14 +120,13 @@ SOURCES += [
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'ConsoleAPI.js',
|
||||
'ConsoleAPI.manifest',
|
||||
'ConsoleAPIStorage.js',
|
||||
'SiteSpecificUserAgent.js',
|
||||
'SiteSpecificUserAgent.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ConsoleAPIStorage.jsm',
|
||||
'DOMRequestHelper.jsm',
|
||||
'IndexedDBHelper.jsm',
|
||||
'ObjectWrapper.jsm',
|
||||
@ -143,6 +145,7 @@ LOCAL_INCLUDES += [
|
||||
'../src/geolocation',
|
||||
'../src/storage',
|
||||
'../time',
|
||||
'../workers',
|
||||
'../xbl',
|
||||
'/content/base/src',
|
||||
'/content/html/document/src',
|
||||
|
@ -207,6 +207,7 @@
|
||||
#include "TimeChangeObserver.h"
|
||||
#include "mozilla/dom/AudioContext.h"
|
||||
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
||||
#include "mozilla/dom/Console.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "nsITabChild.h"
|
||||
@ -1439,6 +1440,8 @@ nsGlobalWindow::CleanUp()
|
||||
mApplicationCache = nullptr;
|
||||
mIndexedDB = nullptr;
|
||||
|
||||
mConsole = nullptr;
|
||||
|
||||
mPerformance = nullptr;
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@ -1753,6 +1756,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
@ -1810,6 +1814,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -13360,6 +13365,59 @@ nsGlobalWindow::SetHasAudioAvailableEventListeners()
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetConsole(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aConsole)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsRefPtr<Console> console = GetConsole(rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> thisObj(aCx, mJSObject);
|
||||
if (!mJSObject) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!JS_WrapObject(aCx, &thisObj) ||
|
||||
!WrapNewBindingObject(aCx, thisObj, console, aConsole)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::SetConsole(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
JS::Rooted<JSObject*> thisObj(aCx, mJSObject);
|
||||
if (!mJSObject) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!JS_WrapObject(aCx, &thisObj) ||
|
||||
!JS_DefineProperty(aCx, thisObj, "console", aValue,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Console*
|
||||
nsGlobalWindow::GetConsole(ErrorResult& aRv)
|
||||
{
|
||||
FORWARD_TO_INNER_OR_THROW(GetConsole, (aRv), aRv, nullptr);
|
||||
|
||||
if (!mConsole) {
|
||||
mConsole = new Console(this);
|
||||
}
|
||||
|
||||
return mConsole;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
void
|
||||
nsGlobalWindow::EnableNetworkEvent(uint32_t aType)
|
||||
|
@ -106,6 +106,7 @@ namespace mozilla {
|
||||
class Selection;
|
||||
namespace dom {
|
||||
class BarProp;
|
||||
class Console;
|
||||
class Function;
|
||||
class Gamepad;
|
||||
class MediaQueryList;
|
||||
@ -820,6 +821,8 @@ public:
|
||||
mozilla::dom::Navigator* GetNavigator(mozilla::ErrorResult& aError);
|
||||
nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
|
||||
|
||||
mozilla::dom::Console* GetConsole(mozilla::ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
bool AlertOrConfirm(bool aAlert, const nsAString& aMessage,
|
||||
mozilla::ErrorResult& aError);
|
||||
@ -1454,6 +1457,7 @@ protected:
|
||||
nsString mDefaultStatus;
|
||||
nsGlobalWindowObserver* mObserver; // Inner windows only.
|
||||
nsCOMPtr<nsIDOMCrypto> mCrypto;
|
||||
nsRefPtr<mozilla::dom::Console> mConsole;
|
||||
|
||||
nsCOMPtr<nsIDOMStorage> mLocalStorage;
|
||||
nsCOMPtr<nsIDOMStorage> mSessionStorage;
|
||||
|
44
dom/base/nsIConsoleAPIStorage.idl
Normal file
44
dom/base/nsIConsoleAPIStorage.idl
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(6701600a-17ca-417e-98f9-4ceb175dd15d)]
|
||||
interface nsIConsoleAPIStorage : nsISupports
|
||||
{
|
||||
/**
|
||||
* Get the events array by inner window ID or all events from all windows.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to get the array of
|
||||
* cached events.
|
||||
* @returns array
|
||||
* The array of cached events for the given window. If no |aId| is
|
||||
* given this function returns all of the cached events, from any
|
||||
* window.
|
||||
*/
|
||||
jsval getEvents([optional] in DOMString aId);
|
||||
|
||||
/**
|
||||
* Record an event associated with the given window ID.
|
||||
*
|
||||
* @param string aId
|
||||
* The ID of the inner window for which the event occurred or "jsm" for
|
||||
* messages logged from JavaScript modules..
|
||||
* @param object aEvent
|
||||
* A JavaScript object you want to store.
|
||||
*/
|
||||
void recordEvent(in DOMString aId, in jsval aEvent);
|
||||
|
||||
/**
|
||||
* Clear storage data for the given window.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to clear the
|
||||
* messages. If this is not specified all of the cached messages are
|
||||
* cleared, from all window objects.
|
||||
*/
|
||||
void clearEvents([optional] in DOMString aId);
|
||||
};
|
@ -6,3 +6,4 @@ support-files =
|
||||
[test_bug715041_removal.xul]
|
||||
[test_domrequesthelper.xul]
|
||||
[test_url.xul]
|
||||
[test_console.xul]
|
||||
|
@ -10,6 +10,7 @@ support-files =
|
||||
[test_appname_override.html]
|
||||
[test_bug913761.html]
|
||||
[test_clearTimeoutIntervalNoArg.html]
|
||||
[test_consoleEmptyStack.html]
|
||||
[test_constructor-assignment.html]
|
||||
[test_constructor.html]
|
||||
[test_document.all_unqualified.html]
|
||||
|
34
dom/base/test/test_console.xul
Normal file
34
dom/base/test/test_console.xul
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<window title="Test for URL API"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<iframe id="iframe" />
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
ok("console" in window, "Console exists");
|
||||
window.console.log(42);
|
||||
window.console = 42;
|
||||
is(window.console, 42, "Console is replacable");
|
||||
|
||||
var frame = document.getElementById("iframe");
|
||||
ok(frame, "Frame must exist");
|
||||
frame.src="http://mochi.test:8888/tests/dom/base/test/file_empty.html";
|
||||
frame.onload = function() {
|
||||
ok("console" in frame.contentWindow, "Console exists in the iframe");
|
||||
frame.contentWindow.console.log(42);
|
||||
frame.contentWindow.console = 42;
|
||||
is(frame.contentWindow.console, 42, "Console is replacable in the iframe");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
]]></script>
|
||||
</window>
|
27
dom/base/test/test_consoleEmptyStack.html
Normal file
27
dom/base/test/test_consoleEmptyStack.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test for empty stack in console</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.setTimeout(console.log.bind(console), 0, "xyz");
|
||||
|
||||
window.addEventListener("fake", console.log.bind(console, "xyz"));
|
||||
|
||||
window.addEventListener("fake", function() {
|
||||
ok(true, "Still alive");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
window.dispatchEvent(new Event("fake"));
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -245,6 +245,10 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::CompositionEvent',
|
||||
},
|
||||
|
||||
'Console': {
|
||||
'implicitJSContext': [ 'trace', 'time', 'timeEnd' ],
|
||||
},
|
||||
|
||||
'ConvolverNode': {
|
||||
'implicitJSContext': [ 'buffer' ],
|
||||
'resultNotAddRefed': [ 'buffer' ],
|
||||
@ -1515,12 +1519,7 @@ DOMInterfaces = {
|
||||
'implicitJSContext': [
|
||||
'close', 'importScripts',
|
||||
],
|
||||
},
|
||||
|
||||
'WorkerConsole': {
|
||||
'headerFile': 'mozilla/dom/workers/bindings/Console.h',
|
||||
'workers': True,
|
||||
'implicitJSContext': [ 'trace', 'time', 'timeEnd' ],
|
||||
'binaryNames': { 'console': 'getConsole', },
|
||||
},
|
||||
|
||||
'WorkerLocation': {
|
||||
|
@ -11775,7 +11775,7 @@ struct PrototypeTraits;
|
||||
|
||||
curr = CGWrapper(curr, post='\n')
|
||||
|
||||
headers.update(["nsDebug.h", "mozilla/dom/UnionTypes.h", "XPCWrapper.h"])
|
||||
headers.update(["nsDebug.h", "mozilla/dom/UnionTypes.h"])
|
||||
curr = CGHeaders([], [], [], [], headers, [], 'UnionConversions', curr)
|
||||
|
||||
# Add include guards.
|
||||
|
@ -297,9 +297,9 @@ this.DataStore.prototype = {
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("DataStore:Changed",
|
||||
{ store: this.name, owner: this.owner,
|
||||
{ store: this.name, owner: this._owner,
|
||||
message: { revisionId: aRevisionId, id: aId,
|
||||
operation: aOperation } } );
|
||||
operation: aOperation, owner: this._owner } } );
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
|
@ -30,6 +30,11 @@
|
||||
|
||||
function eventListener(obj) {
|
||||
ok(obj, "OnChangeListener is called with data");
|
||||
ok("revisionId" in obj, "the event contains a revisionId");
|
||||
ok("id" in obj, "the event contains a id");
|
||||
ok("operation" in obj, "the event contains a operation");
|
||||
ok("owner" in obj, "the event contains a owner");
|
||||
is(obj.owner, 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_changes.html', 'Owner matches');
|
||||
finish();
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIJSEventListener.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsIContent.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIDOMXULControlElement.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsITextControlElement.h"
|
||||
|
@ -24,7 +24,7 @@ interface nsIVariant;
|
||||
* @see <http://www.whatwg.org/html/#window>
|
||||
*/
|
||||
|
||||
[scriptable, uuid(97b6784b-ab12-4f79-8422-d7868a4cc7dc)]
|
||||
[scriptable, uuid(8c115ab3-cf96-492c-850c-3b18056b45e2)]
|
||||
interface nsIDOMWindow : nsISupports
|
||||
{
|
||||
// the current browsing context
|
||||
@ -504,6 +504,11 @@ interface nsIDOMWindow : nsISupports
|
||||
|
||||
[implicit_jscontext] attribute jsval onmouseenter;
|
||||
[implicit_jscontext] attribute jsval onmouseleave;
|
||||
|
||||
/**
|
||||
* Console API
|
||||
*/
|
||||
[implicit_jscontext] attribute jsval console;
|
||||
};
|
||||
|
||||
[scriptable, uuid(2146c906-57f7-486c-a1b4-8cdb57ef577f)]
|
||||
|
@ -166,10 +166,10 @@ function testConsoleGroup(aMessageObject) {
|
||||
function startTraceTest() {
|
||||
gLevel = "trace";
|
||||
gArgs = [
|
||||
{filename: TEST_URI, lineNumber: 6, functionName: "window.foobar585956c", language: 2},
|
||||
{filename: TEST_URI, lineNumber: 11, functionName: "foobar585956b", language: 2},
|
||||
{filename: TEST_URI, lineNumber: 15, functionName: "foobar585956a", language: 2},
|
||||
{filename: TEST_URI, lineNumber: 1, functionName: "onclick", language: 2}
|
||||
{filename: TEST_URI, functionName: "window.foobar585956c", language: 2, lineNumber: 6},
|
||||
{filename: TEST_URI, functionName: "foobar585956b", language: 2, lineNumber: 11},
|
||||
{filename: TEST_URI, functionName: "foobar585956a", language: 2, lineNumber: 15},
|
||||
{filename: TEST_URI, functionName: "onclick", language: 2, lineNumber: 1}
|
||||
];
|
||||
|
||||
let button = gWindow.document.getElementById("test-trace");
|
||||
@ -190,7 +190,7 @@ function startLocationTest() {
|
||||
};
|
||||
gLevel = "log";
|
||||
gArgs = [
|
||||
{filename: TEST_URI, lineNumber: 19, functionName: "foobar646025", arguments: ["omg", "o", "d"]}
|
||||
{filename: TEST_URI, functionName: "foobar646025", arguments: ["omg", "o", "d"], lineNumber: 19}
|
||||
];
|
||||
|
||||
let button = gWindow.document.getElementById("test-location");
|
||||
@ -213,15 +213,34 @@ function observeConsoleTest() {
|
||||
win.console.info("arg", "extra arg");
|
||||
yield undefined;
|
||||
|
||||
// We don't currently support width and precision qualifiers, but we don't
|
||||
// choke on them either.
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.14159");
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %1.0f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.14");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %1.2f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.141590");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.1415900");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %0.7f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("log", "%d, %s, %l");
|
||||
win.console.log("%d, %s, %l");
|
||||
yield undefined;
|
||||
|
@ -4,9 +4,8 @@
|
||||
const TEST_URI = "http://example.com/browser/dom/tests/browser/test-console-api.html";
|
||||
const TEST_URI_NAV = "http://example.com/browser/dom/tests/browser/";
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", tempScope);
|
||||
let ConsoleAPIStorage = tempScope.ConsoleAPIStorage;
|
||||
let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
|
||||
.getService(Ci.nsIConsoleAPIStorage);
|
||||
|
||||
var apiCallCount;
|
||||
|
||||
|
@ -12,8 +12,8 @@ function test() {
|
||||
let consoleObserver;
|
||||
let testURI =
|
||||
"http://example.com/browser/dom/tests/browser/test-console-api.html";
|
||||
let CSS = {};
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", CSS);
|
||||
let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
|
||||
.getService(Ci.nsIConsoleAPIStorage);
|
||||
|
||||
function getInnerWindowId(aWindow) {
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
@ -36,7 +36,7 @@ function test() {
|
||||
consoleObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "console-api-log-event") {
|
||||
afterEvents = CSS.ConsoleAPIStorage.getEvents(innerID);
|
||||
afterEvents = ConsoleAPIStorage.getEvents(innerID);
|
||||
is(beforeEvents.length == afterEvents.length - 1, storageShouldOccur,
|
||||
"storage should" + (storageShouldOccur ? "" : " not") + " occur");
|
||||
|
||||
@ -56,7 +56,7 @@ function test() {
|
||||
// We expect that console API messages are always stored.
|
||||
storageShouldOccur = true;
|
||||
innerID = getInnerWindowId(aWindow);
|
||||
beforeEvents = CSS.ConsoleAPIStorage.getEvents(innerID);
|
||||
beforeEvents = ConsoleAPIStorage.getEvents(innerID);
|
||||
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
||||
}
|
||||
|
||||
function nativeCallback() {
|
||||
new Promise(function(resolve, reject) { resolve(42); }).then(console.log);
|
||||
new Promise(function(resolve, reject) { resolve(42); }).then(console.log.bind(console));
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
87
dom/webidl/Console.webidl
Normal file
87
dom/webidl/Console.webidl
Normal file
@ -0,0 +1,87 @@
|
||||
/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
[ChromeOnly]
|
||||
interface Console {
|
||||
void log(any... data);
|
||||
void info(any... data);
|
||||
void warn(any... data);
|
||||
void error(any... data);
|
||||
void _exception(any... data);
|
||||
void debug(any... data);
|
||||
void trace();
|
||||
void dir(any... data);
|
||||
void group(any... data);
|
||||
void groupCollapsed(any... data);
|
||||
void groupEnd(any... data);
|
||||
void time(any time);
|
||||
void timeEnd(any time);
|
||||
|
||||
[Throws]
|
||||
void profile(any... data);
|
||||
|
||||
[Throws]
|
||||
void profileEnd(any... data);
|
||||
|
||||
void assert(boolean condition, any... data);
|
||||
void count(any... data);
|
||||
|
||||
void ___noSuchMethod__();
|
||||
};
|
||||
|
||||
// This is used to propagate console events to the observers.
|
||||
dictionary ConsoleEvent {
|
||||
(unsigned long or DOMString) ID;
|
||||
(unsigned long or DOMString) innerID;
|
||||
DOMString level = "";
|
||||
DOMString filename = "";
|
||||
unsigned long lineNumber = 0;
|
||||
DOMString functionName = "";
|
||||
double timeStamp = 0;
|
||||
sequence<any> arguments;
|
||||
boolean private = false;
|
||||
sequence<ConsoleStackEntry> stacktrace;
|
||||
DOMString groupName = "";
|
||||
any timer = null;
|
||||
any counter = null;
|
||||
};
|
||||
|
||||
// Event for profile operations
|
||||
dictionary ConsoleProfileEvent {
|
||||
DOMString action = "";
|
||||
sequence<any> arguments;
|
||||
};
|
||||
|
||||
// This dictionary is used to manage stack trace data.
|
||||
dictionary ConsoleStackEntry {
|
||||
DOMString filename = "";
|
||||
unsigned long lineNumber = 0;
|
||||
DOMString functionName = "";
|
||||
unsigned long language = 0;
|
||||
};
|
||||
|
||||
dictionary ConsoleTimerStart {
|
||||
DOMString name = "";
|
||||
double started = 0;
|
||||
};
|
||||
|
||||
dictionary ConsoleTimerEnd {
|
||||
DOMString name = "";
|
||||
double duration = 0;
|
||||
};
|
||||
|
||||
dictionary ConsoleTimerError {
|
||||
DOMString error = "maxTimersExceeded";
|
||||
};
|
||||
|
||||
dictionary ConsoleCounter {
|
||||
DOMString label = "";
|
||||
unsigned long count = 0;
|
||||
};
|
||||
|
||||
dictionary ConsoleCounterError {
|
||||
DOMString error = "maxCountersExceeded";
|
||||
};
|
@ -8,6 +8,7 @@ dictionary DataStoreChangeEventInit : EventInit {
|
||||
DOMString revisionId = "";
|
||||
DataStoreKey id = 0;
|
||||
DOMString operation = "";
|
||||
DOMString owner = "";
|
||||
};
|
||||
|
||||
[Func="Navigator::HasDataStoreSupport",
|
||||
@ -16,4 +17,5 @@ interface DataStoreChangeEvent : Event {
|
||||
readonly attribute DOMString revisionId;
|
||||
readonly attribute DataStoreKey id;
|
||||
readonly attribute DOMString operation;
|
||||
readonly attribute DOMString owner;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user