mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c.
This commit is contained in:
commit
9fa9f53229
2
CLOBBER
2
CLOBBER
@ -18,4 +18,4 @@
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
Bug 908208 - ipdl dependencies are busted, so we must clobber. See Bug 907394 for a solution.
|
||||
Bug 899210 - xpidl header generation is somehow busted so we need to clobber on windows
|
||||
|
@ -779,7 +779,7 @@ XULTreeItemAccessibleBase::GetBounds(int32_t* aX, int32_t* aY,
|
||||
NS_IMETHODIMP
|
||||
XULTreeItemAccessibleBase::SetSelected(bool aSelect)
|
||||
{
|
||||
if (IsDefunct() || !mTreeView)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsITreeSelection> selection;
|
||||
@ -797,7 +797,7 @@ XULTreeItemAccessibleBase::SetSelected(bool aSelect)
|
||||
NS_IMETHODIMP
|
||||
XULTreeItemAccessibleBase::TakeFocus()
|
||||
{
|
||||
if (IsDefunct() || !mTreeView)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsITreeSelection> selection;
|
||||
@ -812,8 +812,6 @@ XULTreeItemAccessibleBase::TakeFocus()
|
||||
Relation
|
||||
XULTreeItemAccessibleBase::RelationByType(uint32_t aType)
|
||||
{
|
||||
if (!mTreeView)
|
||||
return Relation();
|
||||
|
||||
switch (aType) {
|
||||
case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
|
||||
@ -956,8 +954,6 @@ XULTreeItemAccessibleBase::GroupPosition()
|
||||
uint64_t
|
||||
XULTreeItemAccessibleBase::NativeState()
|
||||
{
|
||||
if (!mTreeView)
|
||||
return states::DEFUNCT;
|
||||
|
||||
// focusable and selectable states
|
||||
uint64_t state = NativeInteractiveState();
|
||||
@ -1062,8 +1058,6 @@ XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset,
|
||||
bool
|
||||
XULTreeItemAccessibleBase::IsExpandable()
|
||||
{
|
||||
if (!mTreeView)
|
||||
return false;
|
||||
|
||||
bool isContainer = false;
|
||||
mTreeView->IsContainer(mRow, &isContainer);
|
||||
@ -1089,8 +1083,6 @@ XULTreeItemAccessibleBase::IsExpandable()
|
||||
void
|
||||
XULTreeItemAccessibleBase::GetCellName(nsITreeColumn* aColumn, nsAString& aName)
|
||||
{
|
||||
if (!mTreeView)
|
||||
return;
|
||||
|
||||
mTreeView->GetCellText(mRow, aColumn, aName);
|
||||
|
||||
|
@ -778,8 +778,6 @@ XULTreeGridCellAccessible::RelationByType(uint32_t aType)
|
||||
void
|
||||
XULTreeGridCellAccessible::CellInvalidated()
|
||||
{
|
||||
if (!mTreeView)
|
||||
return;
|
||||
|
||||
nsAutoString textEquiv;
|
||||
|
||||
@ -852,8 +850,6 @@ XULTreeGridCellAccessible::DispatchClickEvent(nsIContent* aContent,
|
||||
bool
|
||||
XULTreeGridCellAccessible::IsEditable() const
|
||||
{
|
||||
if (!mTreeView)
|
||||
return false;
|
||||
|
||||
// XXX: logic corresponds to tree.xml, it's preferable to have interface
|
||||
// method to check it.
|
||||
|
@ -1285,7 +1285,7 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
playPlugin: function() {
|
||||
gPluginHandler.activateSinglePlugin(this.target.ownerDocument.defaultView.top, this.target);
|
||||
gPluginHandler._showClickToPlayNotification(this.browser, this.target);
|
||||
},
|
||||
|
||||
hidePlugin: function() {
|
||||
|
@ -373,4 +373,11 @@ MOCHITEST_BROWSER_FILES += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
# browser_CTP_context_menu.js fails intermittently on Linux (bug 909342)
|
||||
ifndef MOZ_WIDGET_GTK
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_CTP_context_menu.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
103
browser/base/content/test/browser_CTP_context_menu.js
Normal file
103
browser/base/content/test/browser_CTP_context_menu.js
Normal file
@ -0,0 +1,103 @@
|
||||
var rootDir = getRootDirectory(gTestPath);
|
||||
const gTestRoot = rootDir;
|
||||
const gHttpTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
|
||||
|
||||
var gTestBrowser = null;
|
||||
var gNextTest = null;
|
||||
var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
clearAllPluginPermissions();
|
||||
Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
|
||||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
});
|
||||
Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
|
||||
|
||||
let newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", true);
|
||||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
|
||||
|
||||
prepareTest(runAfterPluginBindingAttached(test1), gHttpTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
clearAllPluginPermissions();
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
// The plugin events are async dispatched and can come after the load event
|
||||
// This just allows the events to fire before we then go on to test the states
|
||||
executeSoon(gNextTest);
|
||||
}
|
||||
|
||||
function prepareTest(nextTest, url) {
|
||||
gNextTest = nextTest;
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Due to layout being async, "PluginBindAttached" may trigger later.
|
||||
// This wraps a function to force a layout flush, thus triggering it,
|
||||
// and schedules the function execution so they're definitely executed
|
||||
// afterwards.
|
||||
function runAfterPluginBindingAttached(func) {
|
||||
return function() {
|
||||
let doc = gTestBrowser.contentDocument;
|
||||
let elems = doc.getElementsByTagName('embed');
|
||||
if (elems.length < 1) {
|
||||
elems = doc.getElementsByTagName('object');
|
||||
}
|
||||
elems[0].clientTop;
|
||||
executeSoon(func);
|
||||
};
|
||||
}
|
||||
|
||||
// Test that the activate action in content menus for CTP plugins works
|
||||
function test1() {
|
||||
let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(popupNotification, "Test 1, Should have a click-to-play notification");
|
||||
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 1, Plugin should not be activated");
|
||||
|
||||
window.document.addEventListener("popupshown", test2, false);
|
||||
EventUtils.synthesizeMouseAtCenter(plugin,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
gTestBrowser.contentWindow);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
window.document.removeEventListener("popupshown", test2, false);
|
||||
let activate = window.document.getElementById("context-ctp-play");
|
||||
ok(activate, "Test 2, Should have a context menu entry for activating the plugin");
|
||||
|
||||
// Trigger the click-to-play popup
|
||||
activate.doCommand();
|
||||
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(notification, "Test 2, Should have a click-to-play notification");
|
||||
ok(!notification.dismissed, "Test 2, The click-to-play notification should not be dismissed");
|
||||
|
||||
// Activate the plugin
|
||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
waitForCondition(() => objLoadingContent.activated, test3, "Waited too long for plugin to activate");
|
||||
}
|
||||
|
||||
function test3() {
|
||||
finishTest();
|
||||
}
|
@ -147,6 +147,8 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_console_navigation_marker.js \
|
||||
browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js \
|
||||
browser_webconsole_bug_762593_insecure_passwords_about_blank_web_console_warning.js \
|
||||
browser_webconsole_allow_mixedcontent_securityerrors.js \
|
||||
browser_webconsole_block_mixedcontent_securityerrors.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
@ -254,6 +256,7 @@ MOCHITEST_BROWSER_FILES += \
|
||||
test-iframe1.html \
|
||||
test-iframe2.html \
|
||||
test-iframe3.html \
|
||||
test-mixedcontent-securityerrors.html \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -0,0 +1,69 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// The test loads a web page with mixed active and display content
|
||||
// on it while the "block mixed content" settings are _off_.
|
||||
// It then checks that the loading mixed content warning messages
|
||||
// are logged to the console and have the correct "Learn More"
|
||||
// url appended to them.
|
||||
// Bug 875456 - Log mixed content messages from the Mixed Content
|
||||
// Blocker to the Security Pane in the Web Console
|
||||
|
||||
const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html";
|
||||
const LEARN_MORE_URI = "https://developer.mozilla.org/en/Security/MixedContent";
|
||||
|
||||
function test()
|
||||
{
|
||||
SpecialPowers.pushPrefEnv({"set":
|
||||
[["security.mixed_content.block_active_content", false],
|
||||
["security.mixed_content.block_display_content", false]
|
||||
]}, loadingMixedContentTest);
|
||||
}
|
||||
|
||||
function loadingMixedContentTest()
|
||||
{
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
openConsole(null, function testSecurityErrorLogged (hud) {
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
name: "Logged mixed active content",
|
||||
text: "Loading mixed (insecure) active content on a secure page \"http://example.com/\"",
|
||||
category: CATEGORY_SECURITY,
|
||||
severity: SEVERITY_WARNING
|
||||
},
|
||||
{
|
||||
name: "Logged mixed passive content - image",
|
||||
text: "Loading mixed (insecure) display content on a secure page \"http://example.com/tests/image/test/mochitest/blue.png\"",
|
||||
category: CATEGORY_SECURITY,
|
||||
severity: SEVERITY_WARNING
|
||||
},
|
||||
],
|
||||
}).then(() => testClickOpenNewTab(hud));
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
function testClickOpenNewTab(hud) {
|
||||
let warningNode = hud.outputNode.querySelector(".webconsole-learn-more-link");
|
||||
|
||||
// Invoke the click event and check if a new tab would
|
||||
// open to the correct page.
|
||||
let linkOpened = false;
|
||||
let oldOpenUILinkIn = window.openUILinkIn;
|
||||
window.openUILinkIn = function(aLink) {
|
||||
if (aLink == LEARN_MORE_URI) {
|
||||
linkOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouse(warningNode, 2, 2, {},
|
||||
warningNode.ownerDocument.defaultView);
|
||||
ok(linkOpened, "Clicking the Learn More Warning node opens the desired page");
|
||||
window.openUILinkIn = oldOpenUILinkIn;
|
||||
|
||||
finishTest();
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// The test loads a web page with mixed active and display content
|
||||
// on it while the "block mixed content" settings are _on_.
|
||||
// It then checks that the blocked mixed content warning messages
|
||||
// are logged to the console and have the correct "Learn More"
|
||||
// url appended to them. After the first test finishes, it invokes
|
||||
// a second test that overrides the mixed content blocker settings
|
||||
// by clicking on the doorhanger shield and validates that the
|
||||
// appropriate messages are logged to console.
|
||||
// Bug 875456 - Log mixed content messages from the Mixed Content
|
||||
// Blocker to the Security Pane in the Web Console
|
||||
|
||||
const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html";
|
||||
const LEARN_MORE_URI = "https://developer.mozilla.org/en/Security/MixedContent";
|
||||
|
||||
function test()
|
||||
{
|
||||
SpecialPowers.pushPrefEnv({"set": [["security.mixed_content.block_active_content", true],
|
||||
["security.mixed_content.block_display_content", true]]}, blockMixedContentTest1);
|
||||
}
|
||||
|
||||
function blockMixedContentTest1()
|
||||
{
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, onLoad, true);
|
||||
openConsole(null, function testSecurityErrorLogged (hud) {
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
name: "Logged blocking mixed active content",
|
||||
text: "Blocked loading mixed active content \"http://example.com/\"",
|
||||
category: CATEGORY_SECURITY,
|
||||
severity: SEVERITY_ERROR
|
||||
},
|
||||
{
|
||||
name: "Logged blocking mixed passive content - image",
|
||||
text: "Blocked loading mixed active content \"http://example.com/\"",
|
||||
category: CATEGORY_SECURITY,
|
||||
severity: SEVERITY_ERROR
|
||||
},
|
||||
],
|
||||
}).then(() => {
|
||||
testClickOpenNewTab(hud);
|
||||
// Call the second (MCB override) test.
|
||||
mixedContentOverrideTest2(hud);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
function mixedContentOverrideTest2(hud)
|
||||
{
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", browser);
|
||||
ok(notification, "Mixed Content Doorhanger didn't appear");
|
||||
// Click on the doorhanger.
|
||||
notification.secondaryActions[0].callback();
|
||||
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
name: "Logged blocking mixed active content",
|
||||
text: "Loading mixed (insecure) active content on a secure"+
|
||||
" page \"http://example.com/\"",
|
||||
category: CATEGORY_SECURITY,
|
||||
severity: SEVERITY_WARNING
|
||||
},
|
||||
{
|
||||
name: "Logged blocking mixed passive content - image",
|
||||
text: "Loading mixed (insecure) display content on a secure page"+
|
||||
" \"http://example.com/tests/image/test/mochitest/blue.png\"",
|
||||
category: CATEGORY_SECURITY,
|
||||
severity: SEVERITY_WARNING
|
||||
},
|
||||
],
|
||||
}).then(() => {
|
||||
testClickOpenNewTab(hud);
|
||||
finishTest();
|
||||
});
|
||||
}
|
||||
|
||||
function testClickOpenNewTab(hud) {
|
||||
let warningNode = hud.outputNode.querySelector(".webconsole-learn-more-link");
|
||||
|
||||
// Invoke the click event and check if a new tab would
|
||||
// open to the correct page.
|
||||
let linkOpened = false;
|
||||
let oldOpenUILinkIn = window.openUILinkIn;
|
||||
window.openUILinkIn = function(aLink) {
|
||||
if (aLink == LEARN_MORE_URI) {
|
||||
linkOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouse(warningNode, 2, 2, {},
|
||||
warningNode.ownerDocument.defaultView);
|
||||
ok(linkOpened, "Clicking the Learn More Warning node opens the desired page");
|
||||
window.openUILinkIn = oldOpenUILinkIn;
|
||||
|
||||
}
|
@ -1087,7 +1087,7 @@ function waitForMessages(aOptions)
|
||||
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
||||
aRule.consoleTimeEnd || aRule.type);
|
||||
|
||||
if (aRule.category && aElement.category != aRule.category) {
|
||||
if ("category" in aRule && aElement.category != aRule.category) {
|
||||
if (partialMatch) {
|
||||
is(aElement.category, aRule.category,
|
||||
"message category for rule: " + displayRule(aRule));
|
||||
|
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
Bug 875456 - Log mixed content messages from the Mixed Content Blocker to the
|
||||
Security Pane in the Web Console
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Mixed Content test - http on https</title>
|
||||
<script src="testscript.js"></script>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://example.com"></iframe>
|
||||
<img src="http://example.com/tests/image/test/mochitest/blue.png"></img>
|
||||
</body>
|
||||
</html>
|
@ -1446,21 +1446,36 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
addMoreInfoLink: function WCF_addMoreInfoLink(aNode, aScriptError)
|
||||
{
|
||||
// We have a single category for now, but more are to be
|
||||
// expected soon
|
||||
let url;
|
||||
if (aScriptError.category == "Insecure Password Field") {
|
||||
this.addInsecurePasswordsWarningNode(aNode);
|
||||
url = INSECURE_PASSWORDS_LEARN_MORE;
|
||||
}
|
||||
else if (aScriptError.category == "Mixed Content Message" ||
|
||||
aScriptError.category == "Mixed Content Blocker") {
|
||||
url = MIXED_CONTENT_LEARN_MORE;
|
||||
}
|
||||
else {
|
||||
// Unknown category. Return without adding more info node.
|
||||
return;
|
||||
}
|
||||
|
||||
this.addLearnMoreWarningNode(aNode, url);
|
||||
},
|
||||
|
||||
/*
|
||||
* Appends a clickable insecure passwords warning node to the node passed
|
||||
* Appends a clickable warning node to the node passed
|
||||
* as a parameter to the function. When a user clicks on the appended
|
||||
* warning node, the browser navigates to a page where the user can learn
|
||||
* more about security issues associated with insecure passwords.
|
||||
* warning node, the browser navigates to the provided url.
|
||||
*
|
||||
* @param aNode
|
||||
* The node to which we will be adding a clickable warning node.
|
||||
* @param aURL
|
||||
* The url which points to the page where the user can learn more
|
||||
* about security issues associated with the specific message that's
|
||||
* being logged.
|
||||
*/
|
||||
addInsecurePasswordsWarningNode:
|
||||
function WCF_addInsecurePasswordsWarningNode(aNode)
|
||||
addLearnMoreWarningNode:
|
||||
function WCF_addLearnMoreWarningNode(aNode, aURL)
|
||||
{
|
||||
let moreInfoLabel =
|
||||
"[" + l10n.getStr("webConsoleMoreInfoLabel") + "]";
|
||||
@ -1472,7 +1487,7 @@ WebConsoleFrame.prototype = {
|
||||
linkNode.classList.add("webconsole-msg-link");
|
||||
aNode.appendChild(linkNode);
|
||||
|
||||
// Create the actual insecure passwords warning node and make it clickable
|
||||
// Create the actual warning node and make it clickable
|
||||
let warningNode = this.document.createElement("label");
|
||||
warningNode.setAttribute("value", moreInfoLabel);
|
||||
warningNode.setAttribute("title", moreInfoLabel);
|
||||
@ -1480,7 +1495,7 @@ WebConsoleFrame.prototype = {
|
||||
warningNode.classList.add("webconsole-learn-more-link");
|
||||
|
||||
warningNode.addEventListener("click", function(aEvent) {
|
||||
this.owner.openLink(INSECURE_PASSWORDS_LEARN_MORE);
|
||||
this.owner.openLink(aURL);
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
}.bind(this));
|
||||
@ -4551,6 +4566,7 @@ var Utils = {
|
||||
return CATEGORY_CSS;
|
||||
|
||||
case "Mixed Content Blocker":
|
||||
case "Mixed Content Message":
|
||||
case "CSP":
|
||||
case "Invalid HSTS Headers":
|
||||
case "Insecure Password Field":
|
||||
|
@ -48,22 +48,6 @@ public interface Actions {
|
||||
*/
|
||||
void sendGeckoEvent(String geckoEvent, String data);
|
||||
|
||||
/**
|
||||
* Sends a preferences get event to Gecko.
|
||||
*
|
||||
* @param requestId The id of this request.
|
||||
* @param prefNames The preferences being requested.
|
||||
*/
|
||||
void sendPreferencesGetEvent(int requestId, String[] prefNames);
|
||||
|
||||
/**
|
||||
* Sends a preferences observe event to Gecko.
|
||||
*
|
||||
* @param requestId The id of this request.
|
||||
* @param prefNames The preferences being requested.
|
||||
*/
|
||||
void sendPreferencesObserveEvent(int requestId, String[] prefNames);
|
||||
|
||||
/**
|
||||
* Listens for a gecko event to be sent from the Gecko instance.
|
||||
* The returned object can be used to test if the event has been
|
||||
|
@ -44,8 +44,6 @@ public class FennecNativeActions implements Actions {
|
||||
private Method mRegisterEventListener;
|
||||
private Method mUnregisterEventListener;
|
||||
private Method mBroadcastEvent;
|
||||
private Method mPreferencesGetEvent;
|
||||
private Method mPreferencesObserveEvent;
|
||||
private Method mSetDrawListener;
|
||||
private Method mQuerySql;
|
||||
private Object mRobocopApi;
|
||||
@ -68,8 +66,6 @@ public class FennecNativeActions implements Actions {
|
||||
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
|
||||
mUnregisterEventListener = mApiClass.getMethod("unregisterEventListener", String.class, mEventListenerClass);
|
||||
mBroadcastEvent = mApiClass.getMethod("broadcastEvent", String.class, String.class);
|
||||
mPreferencesGetEvent = mApiClass.getMethod("preferencesGetEvent", Integer.TYPE, String[].class);
|
||||
mPreferencesObserveEvent = mApiClass.getMethod("preferencesObserveEvent", Integer.TYPE, String[].class);
|
||||
mSetDrawListener = mApiClass.getMethod("setDrawListener", mDrawListenerClass);
|
||||
mQuerySql = mApiClass.getMethod("querySql", String.class, String.class);
|
||||
|
||||
@ -269,24 +265,6 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPreferencesEvent(Method method, int requestId, String[] prefNames) {
|
||||
try {
|
||||
method.invoke(mRobocopApi, requestId, prefNames);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPreferencesGetEvent(int requestId, String[] prefNames) {
|
||||
sendPreferencesEvent(mPreferencesGetEvent, requestId, prefNames);
|
||||
}
|
||||
|
||||
public void sendPreferencesObserveEvent(int requestId, String[] prefNames) {
|
||||
sendPreferencesEvent(mPreferencesObserveEvent, requestId, prefNames);
|
||||
}
|
||||
|
||||
class DrawListenerProxy implements InvocationHandler {
|
||||
private final PaintExpecter mPaintExpecter;
|
||||
|
||||
|
@ -200,7 +200,7 @@ class FileKind(object):
|
||||
if filename.endswith('.cpp'):
|
||||
return FileKind.CPP
|
||||
|
||||
if filename.endswith(('inlines.h', '-inl.h')):
|
||||
if filename.endswith(('inlines.h', '-inl.h', 'Inlines.h')):
|
||||
return FileKind.INL_H
|
||||
|
||||
if filename.endswith('.h'):
|
||||
|
@ -31,6 +31,11 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
enum nsMixedContentBlockerMessageType {
|
||||
eBlocked = 0x00,
|
||||
eUserOverride = 0x01
|
||||
};
|
||||
|
||||
// Is mixed script blocking (fonts, plugin content, scripts, stylesheets,
|
||||
// iframes, websockets, XHR) enabled?
|
||||
bool nsMixedContentBlocker::sBlockMixedScript = false;
|
||||
@ -147,22 +152,42 @@ nsMixedContentBlocker::~nsMixedContentBlocker()
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMixedContentBlocker, nsIContentPolicy)
|
||||
|
||||
void
|
||||
LogBlockingMixedContent(MixedContentTypes classification,
|
||||
nsIURI* aContentLocation,
|
||||
nsIDocument* aRootDoc)
|
||||
static void
|
||||
LogMixedContentMessage(MixedContentTypes aClassification,
|
||||
nsIURI* aContentLocation,
|
||||
nsIDocument* aRootDoc,
|
||||
nsMixedContentBlockerMessageType aMessageType)
|
||||
{
|
||||
nsAutoCString messageCategory;
|
||||
uint32_t severityFlag;
|
||||
nsAutoCString messageLookupKey;
|
||||
|
||||
if (aMessageType == eBlocked) {
|
||||
severityFlag = nsIScriptError::errorFlag;
|
||||
messageCategory.AssignLiteral("Mixed Content Blocker");
|
||||
if (aClassification == eMixedDisplay) {
|
||||
messageLookupKey.AssignLiteral("BlockMixedDisplayContent");
|
||||
} else {
|
||||
messageLookupKey.AssignLiteral("BlockMixedActiveContent");
|
||||
}
|
||||
} else {
|
||||
severityFlag = nsIScriptError::warningFlag;
|
||||
messageCategory.AssignLiteral("Mixed Content Message");
|
||||
if (aClassification == eMixedDisplay) {
|
||||
messageLookupKey.AssignLiteral("LoadingMixedDisplayContent");
|
||||
} else {
|
||||
messageLookupKey.AssignLiteral("LoadingMixedActiveContent");
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString locationSpec;
|
||||
aContentLocation->GetSpec(locationSpec);
|
||||
NS_ConvertUTF8toUTF16 locationSpecUTF16(locationSpec);
|
||||
|
||||
const PRUnichar* strings[] = { locationSpecUTF16.get() };
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Mixed Content Blocker"),
|
||||
aRootDoc,
|
||||
nsContentUtils::ReportToConsole(severityFlag, messageCategory, aRootDoc,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
classification == eMixedDisplay ? "BlockMixedDisplayContent" : "BlockMixedActiveContent",
|
||||
strings, ArrayLength(strings));
|
||||
messageLookupKey.get(), strings, ArrayLength(strings));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -453,6 +478,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
||||
// If the content is display content, and the pref says display content should be blocked, block it.
|
||||
if (sBlockMixedDisplay && classification == eMixedDisplay) {
|
||||
if (allowMixedContent) {
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride);
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
rootDoc->SetHasMixedActiveContentLoaded(true);
|
||||
if (!rootDoc->GetHasMixedDisplayContentLoaded() && NS_SUCCEEDED(stateRV)) {
|
||||
@ -460,7 +486,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
||||
}
|
||||
} else {
|
||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
LogBlockingMixedContent(classification, aContentLocation, rootDoc);
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
||||
if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) {
|
||||
eventSink->OnSecurityChange(aRequestingContext, (State | nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT));
|
||||
}
|
||||
@ -471,6 +497,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
||||
// If the content is active content, and the pref says active content should be blocked, block it
|
||||
// unless the user has choosen to override the pref
|
||||
if (allowMixedContent) {
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride);
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
// See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
|
||||
if (rootDoc->GetHasMixedActiveContentLoaded()) {
|
||||
@ -501,7 +528,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
||||
} else {
|
||||
//User has not overriden the pref by Disabling protection. Reject the request and update the security state.
|
||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
LogBlockingMixedContent(classification, aContentLocation, rootDoc);
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
||||
// See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
|
||||
if (rootDoc->GetHasMixedActiveContentBlocked()) {
|
||||
return NS_OK;
|
||||
@ -519,6 +546,9 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
||||
} else {
|
||||
// The content is not blocked by the mixed content prefs.
|
||||
|
||||
// Log a message that we are loading mixed content.
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride);
|
||||
|
||||
// Fire the event from a script runner as it is unsafe to run script
|
||||
// from within ShouldLoad
|
||||
nsContentUtils::AddScriptRunner(
|
||||
|
@ -547,7 +547,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
||||
sNumLivingContexts++;
|
||||
SetIsDOMBinding();
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
#ifdef USE_SKIA_GPU
|
||||
mForceSoftware = false;
|
||||
#endif
|
||||
}
|
||||
@ -564,10 +564,8 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
||||
NS_IF_RELEASE(sErrorTarget);
|
||||
}
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
std::vector<CanvasRenderingContext2D*>::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), this);
|
||||
if (iter != DemotableContexts().end())
|
||||
DemotableContexts().erase(iter);
|
||||
#ifdef USE_SKIA_GPU
|
||||
RemoveDemotableContext(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -746,13 +744,14 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
|
||||
Redraw(newr);
|
||||
}
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
|
||||
void CanvasRenderingContext2D::Demote()
|
||||
{
|
||||
#ifdef USE_SKIA_GPU
|
||||
if (!IsTargetValid() || mForceSoftware)
|
||||
return;
|
||||
|
||||
RemoveDemotableContext(this);
|
||||
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
RefPtr<DrawTarget> oldTarget = mTarget;
|
||||
mTarget = nullptr;
|
||||
@ -764,11 +763,21 @@ void CanvasRenderingContext2D::Demote()
|
||||
if (!IsTargetValid())
|
||||
return;
|
||||
|
||||
// Put back the content from the old DrawTarget
|
||||
// Restore the content from the old DrawTarget
|
||||
mgfx::Rect r(0, 0, mWidth, mHeight);
|
||||
mTarget->DrawSurface(snapshot, r, r);
|
||||
|
||||
// Restore the clips and transform
|
||||
for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) {
|
||||
mTarget->PushClip(CurrentState().clipsPushed[i]);
|
||||
}
|
||||
|
||||
mTarget->SetTransform(oldTarget->GetTransform());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
|
||||
std::vector<CanvasRenderingContext2D*>&
|
||||
CanvasRenderingContext2D::DemotableContexts()
|
||||
{
|
||||
@ -790,8 +799,6 @@ CanvasRenderingContext2D::DemoteOldestContextIfNecessary()
|
||||
return;
|
||||
|
||||
CanvasRenderingContext2D* oldest = contexts.front();
|
||||
contexts.erase(contexts.begin());
|
||||
|
||||
oldest->Demote();
|
||||
}
|
||||
|
||||
@ -805,6 +812,14 @@ CanvasRenderingContext2D::AddDemotableContext(CanvasRenderingContext2D* context)
|
||||
DemotableContexts().push_back(context);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::RemoveDemotableContext(CanvasRenderingContext2D* context)
|
||||
{
|
||||
std::vector<CanvasRenderingContext2D*>::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), context);
|
||||
if (iter != DemotableContexts().end())
|
||||
DemotableContexts().erase(iter);
|
||||
}
|
||||
|
||||
#define MIN_SKIA_GL_DIMENSION 16
|
||||
|
||||
bool
|
||||
|
@ -367,6 +367,8 @@ public:
|
||||
double h, const nsAString& bgColor, uint32_t flags,
|
||||
mozilla::ErrorResult& error);
|
||||
|
||||
void Demote();
|
||||
|
||||
nsresult Redraw();
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
@ -567,13 +569,11 @@ protected:
|
||||
}
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
|
||||
// Recreate the DrawTarget in software mode
|
||||
void Demote();
|
||||
|
||||
static std::vector<CanvasRenderingContext2D*>& DemotableContexts();
|
||||
static void DemoteOldestContextIfNecessary();
|
||||
|
||||
static void AddDemotableContext(CanvasRenderingContext2D* context);
|
||||
static void RemoveDemotableContext(CanvasRenderingContext2D* context);
|
||||
|
||||
// Do not use GL
|
||||
bool mForceSoftware;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// CONSTRUCTOR & DESTRUCTOR
|
||||
@ -51,3 +52,76 @@ WebGL2Context::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
|
||||
return dom::WebGL2RenderingContextBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// WebGL 2 initialisation
|
||||
|
||||
bool
|
||||
WebGLContext::InitWebGL2()
|
||||
{
|
||||
MOZ_ASSERT(IsWebGL2(), "WebGLContext is not a WebGL 2 context!");
|
||||
|
||||
const WebGLExtensionID sExtensionNativelySupportedArr[] = {
|
||||
ANGLE_instanced_arrays,
|
||||
OES_element_index_uint,
|
||||
OES_standard_derivatives,
|
||||
OES_texture_float,
|
||||
OES_texture_float_linear,
|
||||
OES_vertex_array_object,
|
||||
WEBGL_depth_texture,
|
||||
WEBGL_draw_buffers
|
||||
};
|
||||
const GLFeature::Enum sFeatureRequiredArr[] = {
|
||||
GLFeature::blend_minmax,
|
||||
GLFeature::transform_feedback
|
||||
};
|
||||
|
||||
// check WebGL extensions that are supposed to be natively supported
|
||||
for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr)); i++)
|
||||
{
|
||||
WebGLExtensionID extension = sExtensionNativelySupportedArr[i];
|
||||
|
||||
if (!IsExtensionSupported(extension)) {
|
||||
GenerateWarning("WebGL 2 requires %s!", GetExtensionString(extension));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check required OpenGL extensions
|
||||
if (!gl->IsExtensionSupported(GLContext::EXT_gpu_shader4)) {
|
||||
GenerateWarning("WebGL 2 requires GL_EXT_gpu_shader4!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check OpenGL features
|
||||
if (!gl->IsSupported(GLFeature::occlusion_query) &&
|
||||
!gl->IsSupported(GLFeature::occlusion_query_boolean))
|
||||
{
|
||||
/*
|
||||
* on desktop, we fake occlusion_query_boolean with occlusion_query if
|
||||
* necessary. See WebGLContextAsyncQueries.cpp.
|
||||
*/
|
||||
GenerateWarning("WebGL 2 requires occlusion queries!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sFeatureRequiredArr)); i++)
|
||||
{
|
||||
if (!gl->IsSupported(sFeatureRequiredArr[i])) {
|
||||
GenerateWarning("WebGL 2 requires GLFeature::%s!", GLContext::GetFeatureName(sFeatureRequiredArr[i]));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ok WebGL 2 is compatible, we can enable natively supported extensions.
|
||||
for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr)); i++) {
|
||||
EnableExtension(sExtensionNativelySupportedArr[i]);
|
||||
|
||||
MOZ_ASSERT(IsExtensionEnabled(sExtensionNativelySupportedArr[i]));
|
||||
}
|
||||
|
||||
// we initialise WebGL 2 related stuff.
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &mGLMaxTransformFeedbackSeparateAttribs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -615,6 +615,7 @@ WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f, uint32_t aFl
|
||||
} else if (srcPremultAlpha && !dstPremultAlpha) {
|
||||
gfxUtils::UnpremultiplyImageSurface(surf);
|
||||
}
|
||||
surf->MarkDirty();
|
||||
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
|
||||
pat->SetFilter(f);
|
||||
@ -913,11 +914,6 @@ WebGLContext::GetContextAttributes(Nullable<dom::WebGLContextAttributesInitializ
|
||||
result.mPreserveDrawingBuffer = mOptions.preserveDrawingBuffer;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
|
||||
return mExtensions.SafeElementAt(ext);
|
||||
}
|
||||
|
||||
/* [noscript] DOMString mozGetUnderlyingParamString(in WebGLenum pname); */
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
|
||||
@ -947,245 +943,6 @@ WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
|
||||
{
|
||||
// Chrome contexts need access to debug information even when
|
||||
// webgl.disable-extensions is set. This is used in the graphics
|
||||
// section of about:support.
|
||||
if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
|
||||
switch (ext) {
|
||||
case WEBGL_debug_renderer_info:
|
||||
return true;
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IsExtensionSupported(ext);
|
||||
}
|
||||
|
||||
bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
{
|
||||
if (mDisableExtensions) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ext) {
|
||||
case OES_element_index_uint:
|
||||
return gl->IsSupported(GLFeature::element_index_uint);
|
||||
case OES_standard_derivatives:
|
||||
return gl->IsSupported(GLFeature::standard_derivatives);
|
||||
case WEBGL_lose_context:
|
||||
// We always support this extension.
|
||||
return true;
|
||||
case OES_texture_float:
|
||||
return gl->IsSupported(GLFeature::texture_float);
|
||||
case OES_texture_float_linear:
|
||||
return gl->IsSupported(GLFeature::texture_float_linear);
|
||||
case OES_vertex_array_object:
|
||||
return WebGLExtensionVertexArray::IsSupported(this);
|
||||
case EXT_texture_filter_anisotropic:
|
||||
return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
|
||||
return true;
|
||||
}
|
||||
else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WEBGL_compressed_texture_atc:
|
||||
return gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture);
|
||||
case WEBGL_compressed_texture_pvrtc:
|
||||
return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
|
||||
case WEBGL_depth_texture:
|
||||
return gl->IsSupported(GLFeature::packed_depth_stencil) &&
|
||||
gl->IsSupported(GLFeature::depth_texture);
|
||||
case ANGLE_instanced_arrays:
|
||||
return WebGLExtensionInstancedArrays::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
|
||||
switch (ext) {
|
||||
case WEBGL_draw_buffers:
|
||||
return WebGLExtensionDrawBuffers::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CompareWebGLExtensionName(const nsACString& name, const char *other)
|
||||
{
|
||||
return name.Equals(other, nsCaseInsensitiveCStringComparator());
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& rv)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return nullptr;
|
||||
|
||||
NS_LossyConvertUTF16toASCII name(aName);
|
||||
|
||||
WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
|
||||
|
||||
// step 1: figure what extension is wanted
|
||||
if (CompareWebGLExtensionName(name, "OES_element_index_uint"))
|
||||
{
|
||||
ext = OES_element_index_uint;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "OES_texture_float"))
|
||||
{
|
||||
ext = OES_texture_float;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "OES_texture_float_linear"))
|
||||
{
|
||||
ext = OES_texture_float_linear;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "OES_vertex_array_object"))
|
||||
{
|
||||
ext = OES_vertex_array_object;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "OES_standard_derivatives"))
|
||||
{
|
||||
ext = OES_standard_derivatives;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "EXT_texture_filter_anisotropic"))
|
||||
{
|
||||
ext = EXT_texture_filter_anisotropic;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context"))
|
||||
{
|
||||
ext = WEBGL_lose_context;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "WEBGL_lose_context"))
|
||||
{
|
||||
ext = WEBGL_lose_context;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc"))
|
||||
{
|
||||
ext = WEBGL_compressed_texture_s3tc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "WEBGL_compressed_texture_s3tc"))
|
||||
{
|
||||
ext = WEBGL_compressed_texture_s3tc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc"))
|
||||
{
|
||||
ext = WEBGL_compressed_texture_atc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc"))
|
||||
{
|
||||
ext = WEBGL_compressed_texture_pvrtc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "WEBGL_debug_renderer_info"))
|
||||
{
|
||||
ext = WEBGL_debug_renderer_info;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture"))
|
||||
{
|
||||
ext = WEBGL_depth_texture;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "WEBGL_depth_texture"))
|
||||
{
|
||||
ext = WEBGL_depth_texture;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "WEBGL_draw_buffers"))
|
||||
{
|
||||
ext = WEBGL_draw_buffers;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "ANGLE_instanced_arrays"))
|
||||
{
|
||||
ext = ANGLE_instanced_arrays;
|
||||
}
|
||||
|
||||
if (ext == WebGLExtensionID_unknown_extension) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// step 2: check if the extension is supported
|
||||
if (!IsExtensionSupported(cx, ext)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// step 3: if the extension hadn't been previously been created, create it now, thus enabling it
|
||||
if (!IsExtensionEnabled(ext)) {
|
||||
EnableExtension(ext);
|
||||
}
|
||||
|
||||
return WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::EnableExtension(WebGLExtensionID ext)
|
||||
{
|
||||
mExtensions.EnsureLengthAtLeast(ext + 1);
|
||||
|
||||
MOZ_ASSERT(IsExtensionEnabled(ext) == false);
|
||||
|
||||
WebGLExtensionBase* obj = nullptr;
|
||||
switch (ext) {
|
||||
case OES_element_index_uint:
|
||||
obj = new WebGLExtensionElementIndexUint(this);
|
||||
break;
|
||||
case OES_standard_derivatives:
|
||||
obj = new WebGLExtensionStandardDerivatives(this);
|
||||
break;
|
||||
case EXT_texture_filter_anisotropic:
|
||||
obj = new WebGLExtensionTextureFilterAnisotropic(this);
|
||||
break;
|
||||
case WEBGL_lose_context:
|
||||
obj = new WebGLExtensionLoseContext(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
obj = new WebGLExtensionCompressedTextureS3TC(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_atc:
|
||||
obj = new WebGLExtensionCompressedTextureATC(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_pvrtc:
|
||||
obj = new WebGLExtensionCompressedTexturePVRTC(this);
|
||||
break;
|
||||
case WEBGL_debug_renderer_info:
|
||||
obj = new WebGLExtensionDebugRendererInfo(this);
|
||||
break;
|
||||
case WEBGL_depth_texture:
|
||||
obj = new WebGLExtensionDepthTexture(this);
|
||||
break;
|
||||
case OES_texture_float:
|
||||
obj = new WebGLExtensionTextureFloat(this);
|
||||
break;
|
||||
case OES_texture_float_linear:
|
||||
obj = new WebGLExtensionTextureFloatLinear(this);
|
||||
break;
|
||||
case WEBGL_draw_buffers:
|
||||
obj = new WebGLExtensionDrawBuffers(this);
|
||||
break;
|
||||
case OES_vertex_array_object:
|
||||
obj = new WebGLExtensionVertexArray(this);
|
||||
break;
|
||||
case ANGLE_instanced_arrays:
|
||||
obj = new WebGLExtensionInstancedArrays(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "should not get there.");
|
||||
}
|
||||
|
||||
mExtensions[ext] = obj;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ClearScreen()
|
||||
{
|
||||
@ -1554,51 +1311,6 @@ WebGLContext::ForceRestoreContext()
|
||||
mContextStatus = ContextLostAwaitingRestore;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval)
|
||||
{
|
||||
retval.SetNull();
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
nsTArray<nsString>& arr = retval.SetValue();
|
||||
|
||||
if (IsExtensionSupported(cx, OES_element_index_uint))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_element_index_uint"));
|
||||
if (IsExtensionSupported(cx, OES_texture_float))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
|
||||
if (IsExtensionSupported(cx, OES_texture_float_linear))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_texture_float_linear"));
|
||||
if (IsExtensionSupported(cx, OES_standard_derivatives))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives"));
|
||||
if (IsExtensionSupported(cx, EXT_texture_filter_anisotropic))
|
||||
arr.AppendElement(NS_LITERAL_STRING("EXT_texture_filter_anisotropic"));
|
||||
if (IsExtensionSupported(cx, WEBGL_lose_context))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
|
||||
if (IsExtensionSupported(cx, WEBGL_lose_context))
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_lose_context"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_s3tc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_s3tc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_compressed_texture_s3tc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_atc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_pvrtc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_debug_renderer_info))
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_debug_renderer_info"));
|
||||
if (IsExtensionSupported(cx, WEBGL_depth_texture))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
|
||||
if (IsExtensionSupported(cx, WEBGL_depth_texture))
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_depth_texture"));
|
||||
if (IsExtensionSupported(cx, WEBGL_draw_buffers))
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_draw_buffers"));
|
||||
if (IsExtensionSupported(cx, OES_vertex_array_object))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_vertex_array_object"));
|
||||
if (IsExtensionSupported(cx, ANGLE_instanced_arrays))
|
||||
arr.AppendElement(NS_LITERAL_STRING("ANGLE_instanced_arrays"));
|
||||
}
|
||||
|
||||
//
|
||||
// XPCOM goop
|
||||
//
|
||||
|
@ -149,8 +149,6 @@ public:
|
||||
virtual JSObject* WrapObject(JSContext *cx,
|
||||
JS::Handle<JSObject*> scope) = 0;
|
||||
|
||||
virtual bool IsWebGL2() const = 0;
|
||||
|
||||
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
@ -961,7 +959,8 @@ protected:
|
||||
ContextLostAwaitingRestore
|
||||
};
|
||||
|
||||
// extensions
|
||||
// -------------------------------------------------------------------------
|
||||
// WebGL extensions (implemented in WebGLContextExtensions.cpp)
|
||||
enum WebGLExtensionID {
|
||||
EXT_texture_filter_anisotropic,
|
||||
OES_element_index_uint,
|
||||
@ -977,6 +976,7 @@ protected:
|
||||
WEBGL_lose_context,
|
||||
WEBGL_draw_buffers,
|
||||
ANGLE_instanced_arrays,
|
||||
WebGLExtensionID_max,
|
||||
WebGLExtensionID_unknown_extension
|
||||
};
|
||||
nsTArray<nsRefPtr<WebGLExtensionBase> > mExtensions;
|
||||
@ -991,8 +991,19 @@ protected:
|
||||
bool IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const;
|
||||
bool IsExtensionSupported(WebGLExtensionID ext) const;
|
||||
|
||||
static const char* GetExtensionString(WebGLExtensionID ext);
|
||||
|
||||
nsTArray<WebGLenum> mCompressedTextureFormats;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// WebGL 2 specifics (implemented in WebGL2Context.cpp)
|
||||
|
||||
virtual bool IsWebGL2() const = 0;
|
||||
|
||||
bool InitWebGL2();
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Validation functions (implemented in WebGLContextValidate.cpp)
|
||||
bool InitAndValidateGL();
|
||||
|
@ -59,9 +59,9 @@ WebGLContext::BindBufferBase(WebGLenum target, WebGLuint index, WebGLBuffer* buf
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
|
||||
WebGLRefPtr<WebGLBuffer>* indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
|
||||
|
||||
if (!bufferSlot) {
|
||||
if (!indexedBufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,6 +74,11 @@ WebGLContext::BindBufferBase(WebGLenum target, WebGLuint index, WebGLBuffer* buf
|
||||
}
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bindBuffer");
|
||||
|
||||
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
|
||||
|
||||
*indexedBufferSlot = buffer;
|
||||
*bufferSlot = buffer;
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -95,9 +100,9 @@ WebGLContext::BindBufferRange(WebGLenum target, WebGLuint index, WebGLBuffer* bu
|
||||
if (buffer && buffer->IsDeleted())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
|
||||
WebGLRefPtr<WebGLBuffer>* indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
|
||||
|
||||
if (!bufferSlot) {
|
||||
if (!indexedBufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,6 +115,11 @@ WebGLContext::BindBufferRange(WebGLenum target, WebGLuint index, WebGLBuffer* bu
|
||||
}
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bindBuffer");
|
||||
|
||||
MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
|
||||
|
||||
*indexedBufferSlot = buffer;
|
||||
*bufferSlot = buffer;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
290
content/canvas/src/WebGLContextExtensions.cpp
Normal file
290
content/canvas/src/WebGLContextExtensions.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 "WebGLContext.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include "AccessCheck.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
// must match WebGLContext::WebGLExtensionID
|
||||
static const char *sExtensionNames[] = {
|
||||
"EXT_texture_filter_anisotropic",
|
||||
"OES_element_index_uint",
|
||||
"OES_standard_derivatives",
|
||||
"OES_texture_float",
|
||||
"OES_texture_float_linear",
|
||||
"OES_vertex_array_object",
|
||||
"WEBGL_compressed_texture_atc",
|
||||
"WEBGL_compressed_texture_pvrtc",
|
||||
"WEBGL_compressed_texture_s3tc",
|
||||
"WEBGL_debug_renderer_info",
|
||||
"WEBGL_depth_texture",
|
||||
"WEBGL_lose_context",
|
||||
"WEBGL_draw_buffers",
|
||||
"ANGLE_instanced_arrays"
|
||||
};
|
||||
|
||||
/* static */ const char*
|
||||
WebGLContext::GetExtensionString(WebGLExtensionID ext)
|
||||
{
|
||||
static_assert(MOZ_ARRAY_LENGTH(sExtensionNames) == size_t(WebGLExtensionID_max),
|
||||
"Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
|
||||
|
||||
MOZ_ASSERT(ext < WebGLExtensionID_max, "unknown extension!");
|
||||
|
||||
return sExtensionNames[ext];
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
|
||||
return mExtensions.SafeElementAt(ext);
|
||||
}
|
||||
|
||||
bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
|
||||
{
|
||||
// Chrome contexts need access to debug information even when
|
||||
// webgl.disable-extensions is set. This is used in the graphics
|
||||
// section of about:support.
|
||||
if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
|
||||
switch (ext) {
|
||||
case WEBGL_debug_renderer_info:
|
||||
return true;
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IsExtensionSupported(ext);
|
||||
}
|
||||
|
||||
bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
{
|
||||
if (mDisableExtensions) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ext) {
|
||||
case OES_element_index_uint:
|
||||
return gl->IsSupported(GLFeature::element_index_uint);
|
||||
case OES_standard_derivatives:
|
||||
return gl->IsSupported(GLFeature::standard_derivatives);
|
||||
case WEBGL_lose_context:
|
||||
// We always support this extension.
|
||||
return true;
|
||||
case OES_texture_float:
|
||||
return gl->IsSupported(GLFeature::texture_float);
|
||||
case OES_texture_float_linear:
|
||||
return gl->IsSupported(GLFeature::texture_float_linear);
|
||||
case OES_vertex_array_object:
|
||||
return WebGLExtensionVertexArray::IsSupported(this);
|
||||
case EXT_texture_filter_anisotropic:
|
||||
return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
|
||||
return true;
|
||||
}
|
||||
else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WEBGL_compressed_texture_atc:
|
||||
return gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture);
|
||||
case WEBGL_compressed_texture_pvrtc:
|
||||
return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
|
||||
case WEBGL_depth_texture:
|
||||
return gl->IsSupported(GLFeature::packed_depth_stencil) &&
|
||||
gl->IsSupported(GLFeature::depth_texture);
|
||||
case ANGLE_instanced_arrays:
|
||||
return WebGLExtensionInstancedArrays::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
|
||||
switch (ext) {
|
||||
case WEBGL_draw_buffers:
|
||||
return WebGLExtensionDrawBuffers::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CompareWebGLExtensionName(const nsACString& name, const char *other)
|
||||
{
|
||||
return name.Equals(other, nsCaseInsensitiveCStringComparator());
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& rv)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return nullptr;
|
||||
|
||||
NS_LossyConvertUTF16toASCII name(aName);
|
||||
|
||||
WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
|
||||
|
||||
// step 1: figure what extension is wanted
|
||||
for (size_t i = 0; i < size_t(WebGLExtensionID_max); i++)
|
||||
{
|
||||
WebGLExtensionID extension = WebGLExtensionID(i);
|
||||
|
||||
if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
|
||||
ext = extension;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ext == WebGLExtensionID_unknown_extension)
|
||||
{
|
||||
/**
|
||||
* We keep backward compatibility for these deprecated vendor-prefixed
|
||||
* alias. Do not add new ones anymore. Hide it behind the
|
||||
* webgl.enable-draft-extensions flag instead.
|
||||
*/
|
||||
if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context")) {
|
||||
ext = WEBGL_lose_context;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
|
||||
ext = WEBGL_compressed_texture_s3tc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
|
||||
ext = WEBGL_compressed_texture_atc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
|
||||
ext = WEBGL_compressed_texture_pvrtc;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
|
||||
ext = WEBGL_depth_texture;
|
||||
}
|
||||
}
|
||||
|
||||
if (ext == WebGLExtensionID_unknown_extension) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// step 2: check if the extension is supported
|
||||
if (!IsExtensionSupported(cx, ext)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// step 3: if the extension hadn't been previously been created, create it now, thus enabling it
|
||||
if (!IsExtensionEnabled(ext)) {
|
||||
EnableExtension(ext);
|
||||
}
|
||||
|
||||
return WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::EnableExtension(WebGLExtensionID ext)
|
||||
{
|
||||
mExtensions.EnsureLengthAtLeast(ext + 1);
|
||||
|
||||
MOZ_ASSERT(IsExtensionEnabled(ext) == false);
|
||||
|
||||
WebGLExtensionBase* obj = nullptr;
|
||||
switch (ext) {
|
||||
case OES_element_index_uint:
|
||||
obj = new WebGLExtensionElementIndexUint(this);
|
||||
break;
|
||||
case OES_standard_derivatives:
|
||||
obj = new WebGLExtensionStandardDerivatives(this);
|
||||
break;
|
||||
case EXT_texture_filter_anisotropic:
|
||||
obj = new WebGLExtensionTextureFilterAnisotropic(this);
|
||||
break;
|
||||
case WEBGL_lose_context:
|
||||
obj = new WebGLExtensionLoseContext(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
obj = new WebGLExtensionCompressedTextureS3TC(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_atc:
|
||||
obj = new WebGLExtensionCompressedTextureATC(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_pvrtc:
|
||||
obj = new WebGLExtensionCompressedTexturePVRTC(this);
|
||||
break;
|
||||
case WEBGL_debug_renderer_info:
|
||||
obj = new WebGLExtensionDebugRendererInfo(this);
|
||||
break;
|
||||
case WEBGL_depth_texture:
|
||||
obj = new WebGLExtensionDepthTexture(this);
|
||||
break;
|
||||
case OES_texture_float:
|
||||
obj = new WebGLExtensionTextureFloat(this);
|
||||
break;
|
||||
case OES_texture_float_linear:
|
||||
obj = new WebGLExtensionTextureFloatLinear(this);
|
||||
break;
|
||||
case WEBGL_draw_buffers:
|
||||
obj = new WebGLExtensionDrawBuffers(this);
|
||||
break;
|
||||
case OES_vertex_array_object:
|
||||
obj = new WebGLExtensionVertexArray(this);
|
||||
break;
|
||||
case ANGLE_instanced_arrays:
|
||||
obj = new WebGLExtensionInstancedArrays(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "should not get there.");
|
||||
}
|
||||
|
||||
mExtensions[ext] = obj;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval)
|
||||
{
|
||||
retval.SetNull();
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
nsTArray<nsString>& arr = retval.SetValue();
|
||||
|
||||
for (size_t i = 0; i < size_t(WebGLExtensionID_max); i++)
|
||||
{
|
||||
WebGLExtensionID extension = WebGLExtensionID(i);
|
||||
|
||||
if (IsExtensionSupported(cx, extension)) {
|
||||
arr.AppendElement(NS_ConvertUTF8toUTF16(GetExtensionString(extension)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We keep backward compatibility for these deprecated vendor-prefixed
|
||||
* alias. Do not add new ones anymore. Hide it behind the
|
||||
* webgl.enable-draft-extensions flag instead.
|
||||
*/
|
||||
if (IsExtensionSupported(cx, WEBGL_lose_context))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_s3tc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_atc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_compressed_texture_pvrtc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
|
||||
if (IsExtensionSupported(cx, WEBGL_depth_texture))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
|
||||
}
|
||||
|
@ -911,10 +911,6 @@ WebGLContext::InitAndValidateGL()
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWebGL2()) {
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &mGLMaxTransformFeedbackSeparateAttribs);
|
||||
}
|
||||
|
||||
// Always 1 for GLES2
|
||||
mMaxFramebufferColorAttachments = 1;
|
||||
|
||||
@ -966,14 +962,7 @@ WebGLContext::InitAndValidateGL()
|
||||
}
|
||||
|
||||
if (IsWebGL2() &&
|
||||
(!IsExtensionSupported(OES_vertex_array_object) ||
|
||||
!IsExtensionSupported(WEBGL_draw_buffers) ||
|
||||
!IsExtensionSupported(ANGLE_instanced_arrays) ||
|
||||
!gl->IsExtensionSupported(gl::GLContext::EXT_gpu_shader4) ||
|
||||
!gl->IsExtensionSupported(gl::GLContext::EXT_blend_minmax) ||
|
||||
(!gl->IsSupported(gl::GLFeature::occlusion_query) &&
|
||||
!gl->IsSupported(gl::GLFeature::occlusion_query_boolean))
|
||||
))
|
||||
!InitWebGL2())
|
||||
{
|
||||
// Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
|
||||
return false;
|
||||
@ -993,15 +982,5 @@ WebGLContext::InitAndValidateGL()
|
||||
mDefaultVertexArray->mAttribBuffers.SetLength(mGLMaxVertexAttribs);
|
||||
mBoundVertexArray = mDefaultVertexArray;
|
||||
|
||||
if (IsWebGL2()) {
|
||||
EnableExtension(OES_vertex_array_object);
|
||||
EnableExtension(WEBGL_draw_buffers);
|
||||
EnableExtension(ANGLE_instanced_arrays);
|
||||
|
||||
MOZ_ASSERT(IsExtensionEnabled(OES_vertex_array_object));
|
||||
MOZ_ASSERT(IsExtensionEnabled(WEBGL_draw_buffers));
|
||||
MOZ_ASSERT(IsExtensionEnabled(ANGLE_instanced_arrays));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLContextReporter.cpp',
|
||||
'WebGLContextState.cpp',
|
||||
'WebGLContextValidate.cpp',
|
||||
'WebGLContextExtensions.cpp',
|
||||
'WebGLContextFramebufferOperations.cpp',
|
||||
'WebGLContextVertexArray.cpp',
|
||||
'WebGLContextVertices.cpp',
|
||||
|
@ -88,6 +88,7 @@ MOCHITEST_FILES = \
|
||||
file_drawImage_document_domain.html \
|
||||
test_windingRuleUndefined.html \
|
||||
test_strokeText_throw.html \
|
||||
test_bug902651.html \
|
||||
$(NULL)
|
||||
|
||||
# SkiaGL on Android/Gonk does not implement these composite ops yet
|
||||
|
44
content/canvas/test/test_bug902651.html
Normal file
44
content/canvas/test/test_bug902651.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE HTML>
|
||||
<title>Canvas test: canvas demotion</title>
|
||||
<script src="/MochiKit/MochiKit.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<body>
|
||||
<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||
<script>
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function () {
|
||||
|
||||
var canvas = document.getElementById('c');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.fillStyle = 'rgb(50, 50, 50)';
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
ctx.translate(25, 25);
|
||||
|
||||
SpecialPowers.wrap(ctx).demote();
|
||||
|
||||
setTimeout(function() {
|
||||
ctx.fillStyle = 'rgb(127, 127, 127)';
|
||||
ctx.fillRect(0, 0, 10, 10);
|
||||
|
||||
var pixels = ctx.getImageData(0, 0, 1, 1);
|
||||
|
||||
ok(pixels.data[0] === 50, "pixels.data[0] expected 50, got " + pixels.data[0]);
|
||||
ok(pixels.data[1] === 50, "pixels.data[1] expected 50, got " + pixels.data[1]);
|
||||
ok(pixels.data[2] === 50, "pixels.data[2] expected 50, got " + pixels.data[2]);
|
||||
|
||||
pixels = ctx.getImageData(25, 25, 1, 1);
|
||||
|
||||
ok(pixels.data[0] === 127, "pixels.data[0] expected 127, got " + pixels.data[0]);
|
||||
ok(pixels.data[1] === 127, "pixels.data[1] expected 127, got " + pixels.data[1]);
|
||||
ok(pixels.data[2] === 127, "pixels.data[2] expected 127, got " + pixels.data[2]);
|
||||
|
||||
SimpleTest.finish();
|
||||
}, 50);
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -240,6 +240,14 @@ DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHi
|
||||
return stream.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DOMMediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled)
|
||||
{
|
||||
if (mStream) {
|
||||
mStream->SetTrackEnabled(aTrackID, aEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DOMMediaStream::CombineWithPrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
|
@ -84,6 +84,12 @@ public:
|
||||
virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; }
|
||||
virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {}
|
||||
|
||||
/**
|
||||
* Overridden in DOMLocalMediaStreams to allow getUserMedia to disable
|
||||
* media at the SourceMediaStream.
|
||||
*/
|
||||
virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled);
|
||||
|
||||
bool IsFinished();
|
||||
/**
|
||||
* Returns a principal indicating who may access this stream. The stream contents
|
||||
|
@ -100,6 +100,10 @@ public:
|
||||
* Insert aDuration of null data at the end of the segment.
|
||||
*/
|
||||
virtual void AppendNullData(TrackTicks aDuration) = 0;
|
||||
/**
|
||||
* Replace contents with disabled data of the same duration
|
||||
*/
|
||||
virtual void ReplaceWithDisabled() = 0;
|
||||
/**
|
||||
* Remove all contents, setting duration to 0.
|
||||
*/
|
||||
@ -190,6 +194,15 @@ public:
|
||||
}
|
||||
mDuration += aDuration;
|
||||
}
|
||||
virtual void ReplaceWithDisabled()
|
||||
{
|
||||
if (GetType() != AUDIO) {
|
||||
MOZ_CRASH("Disabling unknown segment type");
|
||||
}
|
||||
TrackTicks duration = GetDuration();
|
||||
Clear();
|
||||
AppendNullData(duration);
|
||||
}
|
||||
virtual void Clear()
|
||||
{
|
||||
mDuration = 0;
|
||||
|
@ -1912,29 +1912,15 @@ MediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled)
|
||||
}
|
||||
|
||||
void
|
||||
MediaStream::ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment)
|
||||
MediaStream::ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment, MediaSegment* aRawSegment)
|
||||
{
|
||||
// mMutex must be owned here if this is a SourceMediaStream
|
||||
if (!mDisabledTrackIDs.Contains(aTrackID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aSegment->GetType()) {
|
||||
case MediaSegment::AUDIO: {
|
||||
TrackTicks duration = aSegment->GetDuration();
|
||||
aSegment->Clear();
|
||||
aSegment->AppendNullData(duration);
|
||||
break;
|
||||
}
|
||||
case MediaSegment::VIDEO: {
|
||||
for (VideoSegment::ChunkIterator i(*static_cast<VideoSegment*>(aSegment));
|
||||
!i.IsEnded(); i.Next()) {
|
||||
VideoChunk& chunk = *i;
|
||||
chunk.SetForceBlack(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("Unknown track type");
|
||||
aSegment->ReplaceWithDisabled();
|
||||
if (aRawSegment) {
|
||||
aRawSegment->ReplaceWithDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1990,6 +1976,10 @@ SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegme
|
||||
// Indirect listeners (via subsequent TrackUnion nodes) are synced to
|
||||
// playout time, and so can be delayed by buffering.
|
||||
|
||||
// Apply track disabling before notifying any consumers directly
|
||||
// or inserting into the graph
|
||||
ApplyTrackDisabling(aID, aSegment, aRawSegment);
|
||||
|
||||
// Must notify first, since AppendFrom() will empty out aSegment
|
||||
NotifyDirectConsumers(track, aRawSegment ? aRawSegment : aSegment);
|
||||
track->mData->AppendFrom(aSegment); // note: aSegment is now dead
|
||||
|
@ -459,7 +459,7 @@ public:
|
||||
|
||||
StreamBuffer::Track* EnsureTrack(TrackID aTrack, TrackRate aSampleRate);
|
||||
|
||||
void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment);
|
||||
void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment, MediaSegment* aRawSegment = nullptr);
|
||||
|
||||
DOMMediaStream* GetWrapper()
|
||||
{
|
||||
@ -679,6 +679,11 @@ public:
|
||||
FinishWithLockHeld();
|
||||
}
|
||||
|
||||
// Overriding allows us to hold the mMutex lock while changing the track enable status
|
||||
void SetTrackEnabledImpl(TrackID aTrackID, bool aEnabled) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
MediaStream::SetTrackEnabledImpl(aTrackID, aEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* End all tracks and Finish() this stream. Used to voluntarily revoke access
|
||||
@ -937,6 +942,11 @@ public:
|
||||
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo) = 0;
|
||||
void SetAutofinishImpl(bool aAutofinish) { mAutofinish = aAutofinish; }
|
||||
|
||||
/**
|
||||
* Forward SetTrackEnabled() to the input MediaStream(s) and translate the ID
|
||||
*/
|
||||
virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {};
|
||||
|
||||
protected:
|
||||
// This state is all accessed only on the media graph thread.
|
||||
|
||||
|
@ -52,10 +52,7 @@ void
|
||||
MediaStreamTrack::SetEnabled(bool aEnabled)
|
||||
{
|
||||
mEnabled = aEnabled;
|
||||
MediaStream* stream = mStream->GetStream();
|
||||
if (stream) {
|
||||
stream->SetTrackEnabled(mTrackID, aEnabled);
|
||||
}
|
||||
mStream->SetTrackEnabled(mTrackID, aEnabled);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -115,6 +115,17 @@ public:
|
||||
mFilterCallback = aCallback;
|
||||
}
|
||||
|
||||
// Forward SetTrackEnabled(output_track_id, enabled) to the Source MediaStream,
|
||||
// translating the output track ID into the correct ID in the source.
|
||||
virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {
|
||||
for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) {
|
||||
if (mTrackMap[i].mOutputTrackID == aOutputID) {
|
||||
mTrackMap[i].mInputPort->GetSource()->
|
||||
SetTrackEnabled(mTrackMap[i].mInputTrackID, aEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
TrackIDFilterCallback mFilterCallback;
|
||||
|
||||
|
@ -107,6 +107,14 @@ public:
|
||||
}
|
||||
return &c->mFrame;
|
||||
}
|
||||
// Override default impl
|
||||
virtual void ReplaceWithDisabled() MOZ_OVERRIDE {
|
||||
for (ChunkIterator i(*this);
|
||||
!i.IsEnded(); i.Next()) {
|
||||
VideoChunk& chunk = *i;
|
||||
chunk.SetForceBlack(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Segment-generic methods not in MediaSegmentBase
|
||||
static Type StaticType() { return VIDEO; }
|
||||
|
@ -612,7 +612,7 @@ MediaEngineWebRTCVideoSource::AllocImpl() {
|
||||
mCameraThread,
|
||||
this,
|
||||
this,
|
||||
mWindowId);
|
||||
nsGlobalWindow::GetInnerWindowWithId(mWindowId));
|
||||
mCameraManager->Register(mDOMCameraControl);
|
||||
}
|
||||
|
||||
@ -662,7 +662,7 @@ MediaEngineWebRTCVideoSource::SnapshotImpl() {
|
||||
|
||||
// nsICameraGetCameraCallback
|
||||
nsresult
|
||||
MediaEngineWebRTCVideoSource::HandleEvent(nsICameraControl* camera) {
|
||||
MediaEngineWebRTCVideoSource::HandleEvent(nsISupports* /* unused */) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
|
||||
mNativeCameraControl = static_cast<nsGonkCameraControl*>(mDOMCameraControl->GetNativeCameraControl().get());
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define nsIXMLContentSink_h___
|
||||
|
||||
#include "nsIContentSink.h"
|
||||
#include "nsIParserNode.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIDocument;
|
||||
|
@ -26,7 +26,7 @@ WindowNamedPropertiesHandler::getOwnPropertyDescriptor(JSContext* aCx,
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject* global = JS_GetGlobalForObject(aCx, aProxy);
|
||||
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy));
|
||||
nsresult rv =
|
||||
nsDOMClassInfo::ScriptSecurityManager()->CheckPropertyAccess(aCx, global,
|
||||
"Window", aId,
|
||||
|
@ -554,8 +554,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(CameraControl, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CameraCapabilities, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
@ -1432,10 +1430,6 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CameraControl, nsICameraControl)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsICameraControl)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CameraCapabilities, nsICameraCapabilities)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsICameraCapabilities)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
@ -2190,12 +2184,13 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::PostCreatePrototype(JSContext* aCx, JSObject* aProto)
|
||||
{
|
||||
nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, aProto);
|
||||
JS::Rooted<JSObject*> proto(aCx, aProto);
|
||||
|
||||
nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, proto);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We should probably move this into the CreateInterfaceObjects for Window
|
||||
// once it is on WebIDL bindings.
|
||||
JS::Rooted<JSObject*> proto(aCx, aProto);
|
||||
WindowNamedPropertiesHandler::Install(aCx, proto);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -140,7 +140,6 @@ DOMCI_CLASS(FMRadio)
|
||||
DOMCI_CLASS(BluetoothDevice)
|
||||
#endif
|
||||
|
||||
DOMCI_CLASS(CameraControl)
|
||||
DOMCI_CLASS(CameraCapabilities)
|
||||
|
||||
DOMCI_CLASS(LockedFile)
|
||||
|
@ -255,7 +255,7 @@ nsHistory::ReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
}
|
||||
|
||||
void
|
||||
nsHistory::PushOrReplaceState(JSContext* aCx, JS::Value aData,
|
||||
nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
const nsAString& aTitle, const nsAString& aUrl,
|
||||
ErrorResult& aRv, bool aReplace)
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ protected:
|
||||
return win->GetDocShell();
|
||||
}
|
||||
|
||||
void PushOrReplaceState(JSContext* aCx, JS::Value aData,
|
||||
void PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
const nsAString& aTitle, const nsAString& aUrl,
|
||||
mozilla::ErrorResult& aRv, bool aReplace);
|
||||
|
||||
|
@ -176,6 +176,14 @@ DOMInterfaces = {
|
||||
'headerFile': 'CallsList.h',
|
||||
},
|
||||
|
||||
'CameraControl': {
|
||||
'nativeType': 'mozilla::nsDOMCameraControl',
|
||||
'headerFile': 'DOMCameraControl.h',
|
||||
'binaryNames': {
|
||||
"release": "ReleaseHardware"
|
||||
}
|
||||
},
|
||||
|
||||
'CameraManager': {
|
||||
'nativeType': 'nsDOMCameraManager',
|
||||
'headerFile': 'DOMCameraManager.h'
|
||||
@ -1815,3 +1823,13 @@ addExternalIface('XULCommandDispatcher')
|
||||
addExternalIface('DataTransfer', notflattened=True)
|
||||
addExternalIface('GetCameraCallback', nativeType='nsICameraGetCameraCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraErrorCallback', nativeType='nsICameraErrorCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraCapabilities', nativeType='nsICameraCapabilities', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraAutoFocusCallback', nativeType='nsICameraAutoFocusCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraShutterCallback', nativeType='nsICameraShutterCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraClosedCallback', nativeType='nsICameraClosedCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraTakePictureCallback', nativeType='nsICameraTakePictureCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraReleaseCallback', nativeType='nsICameraReleaseCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraStartRecordingCallback', nativeType='nsICameraStartRecordingCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraPreviewStateChange', nativeType='nsICameraPreviewStateChange', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraPreviewStreamCallback', nativeType='nsICameraPreviewStreamCallback', headerFile='nsIDOMCameraManager.h')
|
||||
addExternalIface('CameraRecorderStateChange', nativeType='nsICameraRecorderStateChange', headerFile='nsIDOMCameraManager.h')
|
||||
|
@ -80,7 +80,14 @@ class CGNativePropertyHooks(CGThing):
|
||||
def declare(self):
|
||||
if self.descriptor.workers:
|
||||
return ""
|
||||
return "extern const NativePropertyHooks* sNativePropertyHooks;\n"
|
||||
return """// We declare this as an array so that retrieving a pointer to this
|
||||
// binding's property hooks only requires compile/link-time resolvable
|
||||
// address arithmetic. Declaring it as a pointer instead would require
|
||||
// doing a run-time load to fetch a pointer to this binding's property
|
||||
// hooks. And then structures which embedded a pointer to this structure
|
||||
// would require a run-time load for proper initialization, which would
|
||||
// then induce static constructors. Lots of static constructors.
|
||||
extern const NativePropertyHooks sNativePropertyHooks[];"""
|
||||
def define(self):
|
||||
if self.descriptor.workers:
|
||||
return ""
|
||||
@ -125,10 +132,9 @@ class CGNativePropertyHooks(CGThing):
|
||||
CGGeneric(constructorID),
|
||||
CGGeneric(parentHooks)],
|
||||
",\n")),
|
||||
pre="static const NativePropertyHooks sNativePropertyHooksStruct = {\n",
|
||||
pre="const NativePropertyHooks sNativePropertyHooks[] = { {\n",
|
||||
post=("\n"
|
||||
"};\n"
|
||||
"const NativePropertyHooks* sNativePropertyHooks = &sNativePropertyHooksStruct;\n")).define()
|
||||
"} };\n")).define()
|
||||
|
||||
def NativePropertyHooks(descriptor):
|
||||
return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks"
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsThread.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/dom/CameraControlBinding.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/unused.h"
|
||||
@ -23,15 +25,11 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
DOMCI_DATA(CameraControl, nsICameraControl)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(nsDOMCameraControl,
|
||||
mDOMCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(nsDOMCameraControl, mDOMCapabilities, mWindow)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraControl)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICameraControl)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraControl)
|
||||
@ -42,235 +40,242 @@ nsDOMCameraControl::~nsDOMCameraControl()
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
/* readonly attribute nsICameraCapabilities capabilities; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetCapabilities(nsICameraCapabilities** aCapabilities)
|
||||
JSObject*
|
||||
nsDOMCameraControl::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return CameraControlBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
nsICameraCapabilities*
|
||||
nsDOMCameraControl::Capabilities()
|
||||
{
|
||||
if (!mDOMCapabilities) {
|
||||
mDOMCapabilities = new DOMCameraCapabilities(mCameraControl);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICameraCapabilities> capabilities = mDOMCapabilities;
|
||||
capabilities.forget(aCapabilities);
|
||||
return NS_OK;
|
||||
return mDOMCapabilities;
|
||||
}
|
||||
|
||||
/* attribute DOMString effect; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetEffect(nsAString& aEffect)
|
||||
void
|
||||
nsDOMCameraControl::GetEffect(nsString& aEffect, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_EFFECT, aEffect);
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_EFFECT, aEffect);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetEffect(const nsAString& aEffect)
|
||||
void
|
||||
nsDOMCameraControl::SetEffect(const nsAString& aEffect, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_EFFECT, aEffect);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_EFFECT, aEffect);
|
||||
}
|
||||
|
||||
/* attribute DOMString whiteBalanceMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetWhiteBalanceMode(nsAString& aWhiteBalanceMode)
|
||||
void
|
||||
nsDOMCameraControl::GetWhiteBalanceMode(nsString& aWhiteBalanceMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode)
|
||||
void
|
||||
nsDOMCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString sceneMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetSceneMode(nsAString& aSceneMode)
|
||||
void
|
||||
nsDOMCameraControl::GetSceneMode(nsString& aSceneMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetSceneMode(const nsAString& aSceneMode)
|
||||
void
|
||||
nsDOMCameraControl::SetSceneMode(const nsAString& aSceneMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString flashMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFlashMode(nsAString& aFlashMode)
|
||||
void
|
||||
nsDOMCameraControl::GetFlashMode(nsString& aFlashMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetFlashMode(const nsAString& aFlashMode)
|
||||
void
|
||||
nsDOMCameraControl::SetFlashMode(const nsAString& aFlashMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString focusMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusMode(nsAString& aFocusMode)
|
||||
void
|
||||
nsDOMCameraControl::GetFocusMode(nsString& aFocusMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetFocusMode(const nsAString& aFocusMode)
|
||||
void
|
||||
nsDOMCameraControl::SetFocusMode(const nsAString& aFocusMode, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
}
|
||||
|
||||
/* attribute double zoom; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetZoom(double* aZoom)
|
||||
double
|
||||
nsDOMCameraControl::GetZoom(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_ZOOM, aZoom);
|
||||
double zoom;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_ZOOM, &zoom);
|
||||
return zoom;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetZoom(double aZoom)
|
||||
|
||||
void
|
||||
nsDOMCameraControl::SetZoom(double aZoom, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom);
|
||||
}
|
||||
|
||||
/* attribute jsval meteringAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetMeteringAreas(JSContext* cx, JS::Value* aMeteringAreas)
|
||||
JS::Value
|
||||
nsDOMCameraControl::GetMeteringAreas(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetMeteringAreas(JSContext* cx, const JS::Value& aMeteringAreas)
|
||||
{
|
||||
return mCameraControl->SetMeteringAreas(cx, aMeteringAreas);
|
||||
JS::Rooted<JS::Value> areas(cx);
|
||||
aRv = mCameraControl->Get(cx, CAMERA_PARAM_METERINGAREAS, areas.address());
|
||||
return areas;
|
||||
}
|
||||
|
||||
/* attribute jsval focusAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusAreas(JSContext* cx, JS::Value* aFocusAreas)
|
||||
void
|
||||
nsDOMCameraControl::SetMeteringAreas(JSContext* cx, JS::Handle<JS::Value> aMeteringAreas, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetFocusAreas(JSContext* cx, const JS::Value& aFocusAreas)
|
||||
{
|
||||
return mCameraControl->SetFocusAreas(cx, aFocusAreas);
|
||||
aRv = mCameraControl->SetMeteringAreas(cx, aMeteringAreas);
|
||||
}
|
||||
|
||||
/* readonly attribute double focalLength; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocalLength(double* aFocalLength)
|
||||
JS::Value
|
||||
nsDOMCameraControl::GetFocusAreas(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCALLENGTH, aFocalLength);
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
aRv = mCameraControl->Get(cx, CAMERA_PARAM_FOCUSAREAS, value.address());
|
||||
return value;
|
||||
}
|
||||
void
|
||||
nsDOMCameraControl::SetFocusAreas(JSContext* cx, JS::Handle<JS::Value> aFocusAreas, ErrorResult& aRv)
|
||||
{
|
||||
aRv = mCameraControl->SetFocusAreas(cx, aFocusAreas);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceNear; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusDistanceNear(double* aFocusDistanceNear)
|
||||
double
|
||||
nsDOMCameraControl::GetFocalLength(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCENEAR, aFocusDistanceNear);
|
||||
double focalLength;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_FOCALLENGTH, &focalLength);
|
||||
return focalLength;
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceOptimum; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusDistanceOptimum(double* aFocusDistanceOptimum)
|
||||
double
|
||||
nsDOMCameraControl::GetFocusDistanceNear(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, aFocusDistanceOptimum);
|
||||
double distance;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCENEAR, &distance);
|
||||
return distance;
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceFar; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusDistanceFar(double* aFocusDistanceFar)
|
||||
double
|
||||
nsDOMCameraControl::GetFocusDistanceOptimum(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEFAR, aFocusDistanceFar);
|
||||
double distance;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, &distance);
|
||||
return distance;
|
||||
}
|
||||
|
||||
/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetExposureCompensation(const JS::Value& aCompensation, JSContext* cx)
|
||||
double
|
||||
nsDOMCameraControl::GetFocusDistanceFar(ErrorResult& aRv)
|
||||
{
|
||||
if (aCompensation.isNullOrUndefined()) {
|
||||
double distance;
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEFAR, &distance);
|
||||
return distance;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMCameraControl::SetExposureCompensation(const Optional<double>& aCompensation, ErrorResult& aRv)
|
||||
{
|
||||
if (!aCompensation.WasPassed()) {
|
||||
// use NaN to switch the camera back into auto mode
|
||||
return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN);
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN);
|
||||
}
|
||||
|
||||
aRv = mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, aCompensation.Value());
|
||||
}
|
||||
|
||||
double
|
||||
nsDOMCameraControl::GetExposureCompensation(ErrorResult& aRv)
|
||||
{
|
||||
double compensation;
|
||||
if (!JS_ValueToNumber(cx, aCompensation, &compensation)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, compensation);
|
||||
aRv = mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, &compensation);
|
||||
return compensation;
|
||||
}
|
||||
|
||||
/* readonly attribute double exposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetExposureCompensation(double* aExposureCompensation)
|
||||
already_AddRefed<nsICameraShutterCallback>
|
||||
nsDOMCameraControl::GetOnShutter(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, aExposureCompensation);
|
||||
nsCOMPtr<nsICameraShutterCallback> cb;
|
||||
aRv = mCameraControl->Get(getter_AddRefs(cb));
|
||||
return cb.forget();
|
||||
}
|
||||
|
||||
/* attribute nsICameraShutterCallback onShutter; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetOnShutter(nsICameraShutterCallback** aOnShutter)
|
||||
void
|
||||
nsDOMCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(aOnShutter);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter)
|
||||
{
|
||||
return mCameraControl->Set(aOnShutter);
|
||||
aRv = mCameraControl->Set(aOnShutter);
|
||||
}
|
||||
|
||||
/* attribute nsICameraClosedCallback onClosed; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetOnClosed(nsICameraClosedCallback** aOnClosed)
|
||||
already_AddRefed<nsICameraClosedCallback>
|
||||
nsDOMCameraControl::GetOnClosed(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(aOnClosed);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetOnClosed(nsICameraClosedCallback* aOnClosed)
|
||||
{
|
||||
return mCameraControl->Set(aOnClosed);
|
||||
nsCOMPtr<nsICameraClosedCallback> onClosed;
|
||||
aRv = mCameraControl->Get(getter_AddRefs(onClosed));
|
||||
return onClosed.forget();
|
||||
}
|
||||
|
||||
/* attribute nsICameraRecorderStateChange onRecorderStateChange; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetOnRecorderStateChange(nsICameraRecorderStateChange** aOnRecorderStateChange)
|
||||
void
|
||||
nsDOMCameraControl::SetOnClosed(nsICameraClosedCallback* aOnClosed,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(aOnRecorderStateChange);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetOnRecorderStateChange(nsICameraRecorderStateChange* aOnRecorderStateChange)
|
||||
{
|
||||
return mCameraControl->Set(aOnRecorderStateChange);
|
||||
aRv = mCameraControl->Set(aOnClosed);
|
||||
}
|
||||
|
||||
/* attribute nsICameraPreviewStateChange onPreviewStateChange; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetOnPreviewStateChange(nsICameraPreviewStateChange** aOnPreviewStateChange)
|
||||
already_AddRefed<nsICameraRecorderStateChange>
|
||||
nsDOMCameraControl::GetOnRecorderStateChange(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->Get(aOnPreviewStateChange);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetOnPreviewStateChange(nsICameraPreviewStateChange* aOnPreviewStateChange)
|
||||
{
|
||||
return mCameraControl->Set(aOnPreviewStateChange);
|
||||
nsCOMPtr<nsICameraRecorderStateChange> cb;
|
||||
aRv = mCameraControl->Get(getter_AddRefs(cb));
|
||||
return cb.forget();
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] void startRecording (in jsval aOptions, in nsIDOMDeviceStorage storageArea, in DOMString filename, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsIDOMDeviceStorage* storageArea, const nsAString& filename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
void
|
||||
nsDOMCameraControl::SetOnRecorderStateChange(nsICameraRecorderStateChange* aOnRecorderStateChange,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(storageArea, NS_ERROR_INVALID_ARG);
|
||||
aRv = mCameraControl->Set(aOnRecorderStateChange);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMCameraControl::StartRecording(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aOptions,
|
||||
nsDOMDeviceStorage& storageArea,
|
||||
const nsAString& filename,
|
||||
nsICameraStartRecordingCallback* onSuccess,
|
||||
const Optional<nsICameraErrorCallback*>& onError,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(onSuccess, "no onSuccess handler passed");
|
||||
mozilla::idl::CameraStartRecordingOptions options;
|
||||
|
||||
// Default values, until the dictionary parser can handle them.
|
||||
options.rotation = 0;
|
||||
options.maxFileSizeBytes = 0;
|
||||
options.maxVideoLengthMs = 0;
|
||||
nsresult rv = options.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = options.Init(aCx, aOptions.address());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (!obs) {
|
||||
NS_WARNING("Could not get the Observer service for CameraControl::StartRecording.");
|
||||
return NS_ERROR_FAILURE;
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
obs->NotifyObservers(nullptr,
|
||||
@ -296,19 +301,21 @@ nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsIDOMDeviceStorag
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIFile> folder;
|
||||
rv = storageArea->GetRootDirectoryForFile(filename, getter_AddRefs(folder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return mCameraControl->StartRecording(&options, folder, filename, onSuccess, onError);
|
||||
aRv = storageArea.GetRootDirectoryForFile(filename, getter_AddRefs(folder));
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
aRv = mCameraControl->StartRecording(&options, folder, filename, onSuccess,
|
||||
onError.WasPassed() ? onError.Value() : nullptr);
|
||||
}
|
||||
|
||||
/* void stopRecording (); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::StopRecording()
|
||||
void
|
||||
nsDOMCameraControl::StopRecording(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (!obs) {
|
||||
NS_WARNING("Could not get the Observer service for CameraControl::StopRecording.");
|
||||
return NS_ERROR_FAILURE;
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
obs->NotifyObservers(nullptr,
|
||||
@ -327,55 +334,71 @@ nsDOMCameraControl::StopRecording()
|
||||
}
|
||||
#endif
|
||||
|
||||
return mCameraControl->StopRecording();
|
||||
aRv = mCameraControl->StopRecording();
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetPreviewStream(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
void
|
||||
nsDOMCameraControl::GetPreviewStream(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aOptions,
|
||||
nsICameraPreviewStreamCallback* onSuccess,
|
||||
const Optional<nsICameraErrorCallback*>& onError,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
mozilla::idl::CameraSize size;
|
||||
nsresult rv = size.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = size.Init(aCx, aOptions.address());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return mCameraControl->GetPreviewStream(size, onSuccess, onError);
|
||||
aRv = mCameraControl->GetPreviewStream(size, onSuccess,
|
||||
onError.WasPassed()
|
||||
? onError.Value() : nullptr);
|
||||
}
|
||||
|
||||
/* void resumePreview(); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::ResumePreview()
|
||||
void
|
||||
nsDOMCameraControl::ResumePreview(ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->StartPreview(nullptr);
|
||||
aRv = mCameraControl->StartPreview(nullptr);
|
||||
}
|
||||
|
||||
/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
already_AddRefed<nsICameraPreviewStateChange>
|
||||
nsDOMCameraControl::GetOnPreviewStateChange() const
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
return mCameraControl->AutoFocus(onSuccess, onError);
|
||||
nsCOMPtr<nsICameraPreviewStateChange> cb;
|
||||
mCameraControl->Get(getter_AddRefs(cb));
|
||||
return cb.forget();
|
||||
}
|
||||
|
||||
/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
void
|
||||
nsDOMCameraControl::SetOnPreviewStateChange(nsICameraPreviewStateChange* aCb)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
mCameraControl->Set(aCb);
|
||||
}
|
||||
|
||||
RootedDictionary<CameraPictureOptions> options(cx);
|
||||
void
|
||||
nsDOMCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess,
|
||||
const Optional<nsICameraErrorCallback*>& onError,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
aRv = mCameraControl->AutoFocus(onSuccess,
|
||||
onError.WasPassed() ? onError.Value() : nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMCameraControl::TakePicture(JSContext* aCx,
|
||||
const CameraPictureOptions& aOptions,
|
||||
nsICameraTakePictureCallback* onSuccess,
|
||||
const Optional<nsICameraErrorCallback*>& aOnError,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
mozilla::idl::CameraSize size;
|
||||
mozilla::idl::CameraPosition pos;
|
||||
|
||||
JS::Rooted<JS::Value> optionVal(cx, aOptions);
|
||||
if (!options.Init(cx, optionVal)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
aRv = size.Init(aCx, &aOptions.mPictureSize);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = size.Init(cx, &options.mPictureSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
/**
|
||||
* Default values, until the dictionary parser can handle them.
|
||||
* NaN indicates no value provided.
|
||||
@ -384,29 +407,45 @@ nsDOMCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureC
|
||||
pos.longitude = NAN;
|
||||
pos.altitude = NAN;
|
||||
pos.timestamp = NAN;
|
||||
rv = pos.Init(cx, &options.mPosition);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = pos.Init(aCx, &aOptions.mPosition);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return mCameraControl->TakePicture(size, options.mRotation, options.mFileFormat, pos, options.mDateTime, onSuccess, onError);
|
||||
nsICameraErrorCallback* onError =
|
||||
aOnError.WasPassed() ? aOnError.Value() : nullptr;
|
||||
aRv = mCameraControl->TakePicture(size, aOptions.mRotation,
|
||||
aOptions.mFileFormat, pos,
|
||||
aOptions.mDateTime, onSuccess, onError);
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] void GetPreviewStreamVideoMode (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetPreviewStreamVideoMode(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
void
|
||||
nsDOMCameraControl::GetPreviewStreamVideoMode(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aOptions,
|
||||
nsICameraPreviewStreamCallback* onSuccess,
|
||||
const Optional<nsICameraErrorCallback*>& onError,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
mozilla::idl::CameraRecorderOptions options;
|
||||
nsresult rv = options.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = options.Init(aCx, aOptions.address());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return mCameraControl->GetPreviewStreamVideoMode(&options, onSuccess, onError);
|
||||
aRv = mCameraControl->GetPreviewStreamVideoMode(&options, onSuccess,
|
||||
onError.WasPassed()
|
||||
? onError.Value() : nullptr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
void
|
||||
nsDOMCameraControl::ReleaseHardware(const Optional<nsICameraReleaseCallback*>& onSuccess,
|
||||
const Optional<nsICameraErrorCallback*>& onError,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return mCameraControl->ReleaseHardware(onSuccess, onError);
|
||||
aRv =
|
||||
mCameraControl->ReleaseHardware(
|
||||
onSuccess.WasPassed() ? onSuccess.Value() : nullptr,
|
||||
onError.WasPassed() ? onError.Value() : nullptr);
|
||||
}
|
||||
|
||||
class GetCameraResult : public nsRunnable
|
||||
|
@ -16,19 +16,27 @@
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
class nsDOMDeviceStorage;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class CameraPictureOptions;
|
||||
template<typename T> class Optional;
|
||||
}
|
||||
class ErrorResult;
|
||||
|
||||
// Main camera control.
|
||||
class nsDOMCameraControl : public nsICameraControl
|
||||
class nsDOMCameraControl MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCameraControl)
|
||||
NS_DECL_NSICAMERACONTROL
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMCameraControl)
|
||||
|
||||
nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread,
|
||||
nsICameraGetCameraCallback* onSuccess,
|
||||
nsICameraErrorCallback* onError, uint64_t aWindowId);
|
||||
nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow);
|
||||
nsresult Result(nsresult aResult,
|
||||
const nsMainThreadPtrHandle<nsICameraGetCameraCallback>& onSuccess,
|
||||
const nsMainThreadPtrHandle<nsICameraErrorCallback>& onError,
|
||||
@ -37,6 +45,52 @@ public:
|
||||
|
||||
void Shutdown();
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const { return mWindow; }
|
||||
|
||||
// WebIDL
|
||||
nsICameraCapabilities* Capabilities();
|
||||
void GetEffect(nsString& aEffect, ErrorResult& aRv);
|
||||
void SetEffect(const nsAString& aEffect, ErrorResult& aRv);
|
||||
void GetWhiteBalanceMode(nsString& aMode, ErrorResult& aRv);
|
||||
void SetWhiteBalanceMode(const nsAString& aMode, ErrorResult& aRv);
|
||||
void GetSceneMode(nsString& aMode, ErrorResult& aRv);
|
||||
void SetSceneMode(const nsAString& aMode, ErrorResult& aRv);
|
||||
void GetFlashMode(nsString& aMode, ErrorResult& aRv);
|
||||
void SetFlashMode(const nsAString& aMode, ErrorResult& aRv);
|
||||
void GetFocusMode(nsString& aMode, ErrorResult& aRv);
|
||||
void SetFocusMode(const nsAString& aMode, ErrorResult& aRv);
|
||||
double GetZoom(ErrorResult& aRv);
|
||||
void SetZoom(double aZoom, ErrorResult& aRv);
|
||||
JS::Value GetMeteringAreas(JSContext* aCx, ErrorResult& aRv);
|
||||
void SetMeteringAreas(JSContext* aCx, JS::Handle<JS::Value> aAreas, ErrorResult& aRv);
|
||||
JS::Value GetFocusAreas(JSContext* aCx, ErrorResult& aRv);
|
||||
void SetFocusAreas(JSContext* aCx, JS::Handle<JS::Value> aAreas, ErrorResult& aRv);
|
||||
double GetFocalLength(ErrorResult& aRv);
|
||||
double GetFocusDistanceNear(ErrorResult& aRv);
|
||||
double GetFocusDistanceOptimum(ErrorResult& aRv);
|
||||
double GetFocusDistanceFar(ErrorResult& aRv);
|
||||
void SetExposureCompensation(const dom::Optional<double>& aCompensation, ErrorResult& aRv);
|
||||
double GetExposureCompensation(ErrorResult& aRv);
|
||||
already_AddRefed<nsICameraShutterCallback> GetOnShutter(ErrorResult& aRv);
|
||||
void SetOnShutter(nsICameraShutterCallback* aCb, ErrorResult& aRv);
|
||||
already_AddRefed<nsICameraClosedCallback> GetOnClosed(ErrorResult& aRv);
|
||||
void SetOnClosed(nsICameraClosedCallback* aCb, ErrorResult& aRv);
|
||||
already_AddRefed<nsICameraRecorderStateChange> GetOnRecorderStateChange(ErrorResult& aRv);
|
||||
void SetOnRecorderStateChange(nsICameraRecorderStateChange* aCb, ErrorResult& aRv);
|
||||
void AutoFocus(nsICameraAutoFocusCallback* aOnSuccess, const dom::Optional<nsICameraErrorCallback*>& aOnErro, ErrorResult& aRvr);
|
||||
void TakePicture(JSContext* aCx, const dom::CameraPictureOptions& aOptions,
|
||||
nsICameraTakePictureCallback* onSuccess,
|
||||
const dom::Optional<nsICameraErrorCallback* >& onError,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<nsICameraPreviewStateChange> GetOnPreviewStateChange() const;
|
||||
void SetOnPreviewStateChange(nsICameraPreviewStateChange* aOnStateChange);
|
||||
void GetPreviewStreamVideoMode(JSContext* cx, JS::Handle<JS::Value> aOptions, nsICameraPreviewStreamCallback* onSuccess, const dom::Optional<nsICameraErrorCallback* >& onError, ErrorResult& aRv);
|
||||
void StartRecording(JSContext* cx, JS::Handle<JS::Value> aOptions, nsDOMDeviceStorage& storageArea, const nsAString& filename, nsICameraStartRecordingCallback* onSuccess, const dom::Optional<nsICameraErrorCallback* >& onError, ErrorResult& aRv);
|
||||
void StopRecording(ErrorResult& aRv);
|
||||
void GetPreviewStream(JSContext* cx, JS::Handle<JS::Value> aOptions, nsICameraPreviewStreamCallback* onSuccess, const dom::Optional<nsICameraErrorCallback* >& onError, ErrorResult& aRv);
|
||||
void ResumePreview(ErrorResult& aRv);
|
||||
void ReleaseHardware(const dom::Optional<nsICameraReleaseCallback* >& onSuccess, const dom::Optional<nsICameraErrorCallback* >& onError, ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMCameraControl();
|
||||
|
||||
@ -44,12 +98,15 @@ private:
|
||||
nsDOMCameraControl(const nsDOMCameraControl&) MOZ_DELETE;
|
||||
nsDOMCameraControl& operator=(const nsDOMCameraControl&) MOZ_DELETE;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
nsRefPtr<ICameraControl> mCameraControl; // non-DOM camera control
|
||||
nsCOMPtr<nsICameraCapabilities> mDOMCapabilities;
|
||||
// An agent used to join audio channel service.
|
||||
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -127,9 +127,9 @@ nsDOMCameraManager::GetCamera(const CameraSelector& aOptions,
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
// Creating this object will trigger the onSuccess handler
|
||||
nsCOMPtr<nsDOMCameraControl> cameraControl =
|
||||
nsRefPtr<nsDOMCameraControl> cameraControl =
|
||||
new nsDOMCameraControl(cameraId, mCameraThread,
|
||||
onSuccess, onError.WasPassed() ? onError.Value() : nullptr, mWindowId);
|
||||
onSuccess, onError.WasPassed() ? onError.Value() : nullptr, mWindow);
|
||||
|
||||
Register(cameraControl);
|
||||
}
|
||||
|
@ -59,8 +59,10 @@ private:
|
||||
* store a reference in the 'mCameraControl' member (which is why it is
|
||||
* defined here).
|
||||
*/
|
||||
nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId)
|
||||
nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow) :
|
||||
mWindow(aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow, "shouldn't be created with null window!");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -143,9 +143,10 @@ static const char* getKeyText(uint32_t aKey)
|
||||
}
|
||||
|
||||
// nsDOMCameraControl implementation-specific constructor
|
||||
nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId)
|
||||
: mDOMCapabilities(nullptr)
|
||||
nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow)
|
||||
: mDOMCapabilities(nullptr), mWindow(aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow, "shouldn't be created with null window!");
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
/**
|
||||
@ -160,8 +161,8 @@ nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThr
|
||||
* nsDOMCameraControl or memory will leak!
|
||||
*/
|
||||
NS_ADDREF_THIS();
|
||||
nsRefPtr<nsGonkCameraControl> control = new nsGonkCameraControl(aCameraId, aCameraThread, this, onSuccess, onError, aWindowId);
|
||||
control->DispatchInit(this, onSuccess, onError, aWindowId);
|
||||
nsRefPtr<nsGonkCameraControl> control = new nsGonkCameraControl(aCameraId, aCameraThread, this, onSuccess, onError, aWindow->WindowID());
|
||||
control->DispatchInit(this, onSuccess, onError, aWindow->WindowID());
|
||||
mCameraControl = control;
|
||||
}
|
||||
|
||||
|
@ -217,171 +217,8 @@ interface nsICameraErrorCallback : nsISupports
|
||||
void handleEvent(in DOMString error);
|
||||
};
|
||||
|
||||
/*
|
||||
attributes here affect the preview, any pictures taken, and/or
|
||||
any video recorded by the camera.
|
||||
*/
|
||||
[scriptable, uuid(74dc7f1f-c88f-4774-860b-44aef9de5dc8)]
|
||||
interface nsICameraControl : nsISupports
|
||||
{
|
||||
readonly attribute nsICameraCapabilities capabilities;
|
||||
|
||||
/* one of the vales chosen from capabilities.effects;
|
||||
default is "none" */
|
||||
attribute DOMString effect;
|
||||
|
||||
/* one of the values chosen from capabilities.whiteBalanceModes;
|
||||
default is "auto" */
|
||||
attribute DOMString whiteBalanceMode;
|
||||
|
||||
/* one of the valus chosen from capabilities.sceneModes;
|
||||
default is "auto" */
|
||||
attribute DOMString sceneMode;
|
||||
|
||||
/* one of the values chosen from capabilities.flashModes;
|
||||
default is "auto" */
|
||||
attribute DOMString flashMode;
|
||||
|
||||
/* one of the values chosen from capabilities.focusModes;
|
||||
default is "auto", if supported, or "fixed" */
|
||||
attribute DOMString focusMode;
|
||||
|
||||
/* one of the values chosen from capabilities.zoomRatios; other
|
||||
values will be rounded to the nearest supported value;
|
||||
default is 1.0 */
|
||||
attribute double zoom;
|
||||
|
||||
/* an array of one or more objects that define where the
|
||||
camera will perform light metering, each defining the properties:
|
||||
{
|
||||
top: -1000,
|
||||
left: -1000,
|
||||
bottom: 1000,
|
||||
right: 1000,
|
||||
weight: 1000
|
||||
}
|
||||
|
||||
'top', 'left', 'bottom', and 'right' all range from -1000 at
|
||||
the top-/leftmost of the sensor to 1000 at the bottom-/rightmost
|
||||
of the sensor.
|
||||
|
||||
objects missing one or more of these properties will be ignored;
|
||||
if the array contains more than capabilities.maxMeteringAreas,
|
||||
extra areas will be ignored.
|
||||
|
||||
this attribute can be set to null to allow the camera to determine
|
||||
where to perform light metering. */
|
||||
[implicit_jscontext]
|
||||
attribute jsval meteringAreas;
|
||||
|
||||
/* an array of one or more objects that define where the camera will
|
||||
perform auto-focusing, with the same definition as meteringAreas.
|
||||
|
||||
if the array contains more than capabilities.maxFocusAreas, extra
|
||||
areas will be ignored.
|
||||
|
||||
this attribute can be set to null to allow the camera to determine
|
||||
where to focus. */
|
||||
[implicit_jscontext]
|
||||
attribute jsval focusAreas;
|
||||
|
||||
/* focal length in millimetres */
|
||||
readonly attribute double focalLength;
|
||||
|
||||
/* the distances in metres to where the image subject appears to be
|
||||
in focus. 'focusDistanceOptimum' is where the subject will appear
|
||||
sharpest; the difference between 'focusDistanceFar' and
|
||||
'focusDistanceNear' is the image's depth of field.
|
||||
|
||||
'focusDistanceFar' may be infinity. */
|
||||
readonly attribute double focusDistanceNear;
|
||||
readonly attribute double focusDistanceOptimum;
|
||||
readonly attribute double focusDistanceFar;
|
||||
|
||||
/* 'compensation' is optional, and if missing, will
|
||||
set the camera to use automatic exposure compensation.
|
||||
|
||||
acceptable values must range from minExposureCompensation
|
||||
to maxExposureCompensation in steps of stepExposureCompensation;
|
||||
invalid values will be rounded to the nearest valid value. */
|
||||
[implicit_jscontext]
|
||||
void setExposureCompensation([optional] in jsval compensation);
|
||||
readonly attribute double exposureCompensation;
|
||||
|
||||
/* the function to call on the camera's shutter event, to trigger
|
||||
a shutter sound and/or a visual shutter indicator. */
|
||||
attribute nsICameraShutterCallback onShutter;
|
||||
|
||||
/* the function to call when the camera hardware is closed
|
||||
by the underlying framework, e.g. when another app makes a more
|
||||
recent call to get the camera. */
|
||||
attribute nsICameraClosedCallback onClosed;
|
||||
|
||||
/* the function to call when the recorder changes state, either because
|
||||
the recording process encountered an error, or because one of the
|
||||
recording limits (see CameraStartRecordingOptions) was reached. */
|
||||
attribute nsICameraRecorderStateChange onRecorderStateChange;
|
||||
|
||||
/* the function to call when the preview stream is actually started and
|
||||
stopped; this is usually used to enable and disable the camera UI,
|
||||
since the low-level hardware often does not support taking pictures
|
||||
unless the preview is running. */
|
||||
attribute nsICameraPreviewStateChange onPreviewStateChange;
|
||||
|
||||
/* tell the camera to attempt to focus the image */
|
||||
void autoFocus(in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
|
||||
/* capture an image and return it as a blob to the 'onSuccess' callback;
|
||||
if the camera supports it, this may be invoked while the camera is
|
||||
already recording video.
|
||||
|
||||
invoking this function will stop the preview stream, which must be
|
||||
manually restarted (e.g. by calling .play() on it). */
|
||||
[implicit_jscontext]
|
||||
void takePicture(in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
|
||||
/* get a media stream to be used as a camera viewfinder in video mode;
|
||||
'aOptions' is an CameraRecorderOptions object. */
|
||||
[implicit_jscontext]
|
||||
void getPreviewStreamVideoMode(in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
|
||||
/* start recording video; 'aOptions' is a
|
||||
CameraStartRecordingOptions object. */
|
||||
[implicit_jscontext]
|
||||
void startRecording(in jsval aOptions, in nsIDOMDeviceStorage storageArea, in DOMString filename, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
|
||||
/* stop precording video. */
|
||||
void stopRecording();
|
||||
|
||||
/* get a media stream to be used as a camera viewfinder; the options
|
||||
define the desired frame size of the preview, chosen from
|
||||
capabilities.previewSizes, e.g.:
|
||||
{
|
||||
height: 640,
|
||||
width: 480,
|
||||
}
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void getPreviewStream(in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
|
||||
/* call in or after the takePicture() onSuccess callback to
|
||||
resume the camera preview stream. */
|
||||
void resumePreview();
|
||||
|
||||
/* release the camera so that other applications can use it; you should
|
||||
probably call this whenever the camera is not longer in the foreground
|
||||
(depending on your usage model).
|
||||
|
||||
the callbacks are optional, unless you really need to know when
|
||||
the hardware is ultimately released.
|
||||
|
||||
once this is called, the camera control object is to be considered
|
||||
defunct; a new instance will need to be created to access the camera. */
|
||||
[binaryname(ReleaseHardware)] void release([optional] in nsICameraReleaseCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(a267afbc-d91c-413a-8de5-0b94aecffa3e)]
|
||||
[scriptable, function, uuid(16de7703-dc43-4766-99c5-ff30a9ab92d7)]
|
||||
interface nsICameraGetCameraCallback : nsISupports
|
||||
{
|
||||
void handleEvent(in nsICameraControl camera);
|
||||
void handleEvent(in nsISupports camera);
|
||||
};
|
||||
|
@ -30,7 +30,6 @@ include URIParams;
|
||||
include "mozilla/chrome/RegistryMessageUtils.h";
|
||||
include "mozilla/dom/PermissionMessageUtils.h";
|
||||
include "mozilla/dom/TabMessageUtils.h";
|
||||
include "mozilla/dom/Element.h";
|
||||
include "mozilla/HalTypes.h";
|
||||
include "mozilla/layout/RenderFrameUtils.h";
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
|
@ -14,3 +14,5 @@ InvalidSTSHeaders=The site specified an invalid Strict-Transport-Security header
|
||||
InsecurePasswordsPresentOnPage=Password fields present on an insecure (http://) page. This is a security risk that allows user login credentials to be stolen.
|
||||
InsecureFormActionPasswordsPresent=Password fields present in a form with an insecure (http://) form action. This is a security risk that allows user login credentials to be stolen.
|
||||
InsecurePasswordsPresentOnIframe=Password fields present on an insecure (http://) iframe. This is a security risk that allows user login credentials to be stolen.
|
||||
LoadingMixedActiveContent=Loading mixed (insecure) active content on a secure page "%1$S"
|
||||
LoadingMixedDisplayContent=Loading mixed (insecure) display content on a secure page "%1$S"
|
||||
|
@ -312,6 +312,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// let us intervene for direct listeners when someone does track.enabled = false
|
||||
virtual void SetTrackEnabled(TrackID aID, bool aEnabled) MOZ_OVERRIDE
|
||||
{
|
||||
// We encapsulate the SourceMediaStream and TrackUnion into one entity, so
|
||||
// we can handle the disabling at the SourceMediaStream
|
||||
|
||||
// We need to find the input track ID for output ID aID, so we let the TrackUnion
|
||||
// forward the request to the source and translate the ID
|
||||
GetStream()->AsProcessedStream()->ForwardTrackEnabled(aID, aEnabled);
|
||||
}
|
||||
|
||||
// The actual MediaStream is a TrackUnionStream. But these resources need to be
|
||||
// explicitly destroyed too.
|
||||
nsRefPtr<SourceMediaStream> mSourceStream;
|
||||
|
@ -1015,6 +1015,7 @@ PeerConnectionObserver.prototype = {
|
||||
},
|
||||
|
||||
handleIceStateChanges: function(iceState) {
|
||||
var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
|
||||
switch (iceState) {
|
||||
case Ci.IPeerConnection.kIceWaiting:
|
||||
this._dompc.changeIceConnectionState("new");
|
||||
@ -1033,10 +1034,12 @@ PeerConnectionObserver.prototype = {
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceConnected:
|
||||
// ICE gathering complete.
|
||||
histogram.add(true);
|
||||
this._dompc.changeIceConnectionState("connected");
|
||||
this.callCB(this._onicechange, "connected");
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceFailed:
|
||||
histogram.add(false);
|
||||
this._dompc.changeIceConnectionState("failed");
|
||||
this.callCB(this._onicechange, "failed");
|
||||
break;
|
||||
|
@ -5,7 +5,7 @@ fails-if(!haveTestPlugin) == plugin-sanity.html div-sanity.html
|
||||
fails-if(!haveTestPlugin) == plugin-asyncbitmap-sanity.html div-sanity.html
|
||||
fails-if(!haveTestPlugin) == plugin-asyncdxgi-sanity.html div-sanity.html
|
||||
skip-if(!haveTestPlugin) == plugin-asyncbitmap-update.html plugin-async-update-ref.html
|
||||
skip-if(!haveTestPlugin) == plugin-asyncdxgi-update.html plugin-async-update-ref.html
|
||||
random-if(OSX==10.6||OSX==10.7) skip-if(!haveTestPlugin) == plugin-asyncdxgi-update.html plugin-async-update-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) == plugin-alpha-opacity.html div-alpha-opacity.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1-ref.html # bug 631832
|
||||
|
195
dom/webidl/CameraControl.webidl
Normal file
195
dom/webidl/CameraControl.webidl
Normal file
@ -0,0 +1,195 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; 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/.
|
||||
*/
|
||||
|
||||
interface CameraCapabilities;
|
||||
interface GetCameraCallback;
|
||||
interface CameraErrorCallback;
|
||||
interface CameraShutterCallback;
|
||||
interface CameraClosedCallback;
|
||||
interface CameraRecorderStateChange;
|
||||
interface CameraAutoFocusCallback;
|
||||
interface CameraTakePictureCallback;
|
||||
interface CameraPreviewStateChange;
|
||||
interface CameraPreviewStreamCallback;
|
||||
interface CameraStartRecordingCallback;
|
||||
interface CameraReleaseCallback;
|
||||
|
||||
/*
|
||||
attributes here affect the preview, any pictures taken, and/or
|
||||
any video recorded by the camera.
|
||||
*/
|
||||
interface CameraControl {
|
||||
readonly attribute CameraCapabilities capabilities;
|
||||
|
||||
/* one of the values chosen from capabilities.effects;
|
||||
default is "none" */
|
||||
[Throws]
|
||||
attribute DOMString effect;
|
||||
|
||||
/* one of the values chosen from capabilities.whiteBalanceModes;
|
||||
default is "auto" */
|
||||
[Throws]
|
||||
attribute DOMString whiteBalanceMode;
|
||||
|
||||
/* one of the values chosen from capabilities.sceneModes;
|
||||
default is "auto" */
|
||||
[Throws]
|
||||
attribute DOMString sceneMode;
|
||||
|
||||
/* one of the values chosen from capabilities.flashModes;
|
||||
default is "auto" */
|
||||
[Throws]
|
||||
attribute DOMString flashMode;
|
||||
|
||||
/* one of the values chosen from capabilities.focusModes;
|
||||
default is "auto", if supported, or "fixed" */
|
||||
[Throws]
|
||||
attribute DOMString focusMode;
|
||||
|
||||
/* one of the values chosen from capabilities.zoomRatios; other
|
||||
values will be rounded to the nearest supported value;
|
||||
default is 1.0 */
|
||||
[Throws]
|
||||
attribute double zoom;
|
||||
|
||||
/* an array of one or more objects that define where the
|
||||
camera will perform light metering, each defining the properties:
|
||||
{
|
||||
top: -1000,
|
||||
left: -1000,
|
||||
bottom: 1000,
|
||||
right: 1000,
|
||||
weight: 1000
|
||||
}
|
||||
|
||||
'top', 'left', 'bottom', and 'right' all range from -1000 at
|
||||
the top-/leftmost of the sensor to 1000 at the bottom-/rightmost
|
||||
of the sensor.
|
||||
|
||||
objects missing one or more of these properties will be ignored;
|
||||
if the array contains more than capabilities.maxMeteringAreas,
|
||||
extra areas will be ignored.
|
||||
|
||||
this attribute can be set to null to allow the camera to determine
|
||||
where to perform light metering. */
|
||||
[Throws]
|
||||
attribute any meteringAreas;
|
||||
|
||||
/* an array of one or more objects that define where the camera will
|
||||
perform auto-focusing, with the same definition as meteringAreas.
|
||||
|
||||
if the array contains more than capabilities.maxFocusAreas, extra
|
||||
areas will be ignored.
|
||||
|
||||
this attribute can be set to null to allow the camera to determine
|
||||
where to focus. */
|
||||
[Throws]
|
||||
attribute any focusAreas;
|
||||
|
||||
/* focal length in millimetres */
|
||||
[Throws]
|
||||
readonly attribute double focalLength;
|
||||
|
||||
/* the distances in metres to where the image subject appears to be
|
||||
in focus. 'focusDistanceOptimum' is where the subject will appear
|
||||
sharpest; the difference between 'focusDistanceFar' and
|
||||
'focusDistanceNear' is the image's depth of field.
|
||||
|
||||
'focusDistanceFar' may be infinity. */
|
||||
[Throws]
|
||||
readonly attribute double focusDistanceNear;
|
||||
[Throws]
|
||||
readonly attribute double focusDistanceOptimum;
|
||||
[Throws]
|
||||
readonly attribute unrestricted double focusDistanceFar;
|
||||
|
||||
/* 'compensation' is optional, and if missing, will
|
||||
set the camera to use automatic exposure compensation.
|
||||
|
||||
acceptable values must range from minExposureCompensation
|
||||
to maxExposureCompensation in steps of stepExposureCompensation;
|
||||
invalid values will be rounded to the nearest valid value. */
|
||||
[Throws]
|
||||
void setExposureCompensation(optional double compensation);
|
||||
[Throws]
|
||||
readonly attribute unrestricted double exposureCompensation;
|
||||
|
||||
/* the function to call on the camera's shutter event, to trigger
|
||||
a shutter sound and/or a visual shutter indicator. */
|
||||
[Throws]
|
||||
attribute CameraShutterCallback? onShutter;
|
||||
|
||||
/* the function to call when the camera hardware is closed
|
||||
by the underlying framework, e.g. when another app makes a more
|
||||
recent call to get the camera. */
|
||||
[Throws]
|
||||
attribute CameraClosedCallback? onClosed;
|
||||
|
||||
/* the function to call when the recorder changes state, either because
|
||||
the recording process encountered an error, or because one of the
|
||||
recording limits (see CameraStartRecordingOptions) was reached. */
|
||||
[Throws]
|
||||
attribute CameraRecorderStateChange? onRecorderStateChange;
|
||||
attribute CameraPreviewStateChange? onPreviewStateChange;
|
||||
|
||||
/* tell the camera to attempt to focus the image */
|
||||
[Throws]
|
||||
void autoFocus(CameraAutoFocusCallback onSuccess, optional CameraErrorCallback onError);
|
||||
|
||||
/* capture an image and return it as a blob to the 'onSuccess' callback;
|
||||
if the camera supports it, this may be invoked while the camera is
|
||||
already recording video.
|
||||
|
||||
invoking this function will stop the preview stream, which must be
|
||||
manually restarted (e.g. by calling .play() on it). */
|
||||
[Throws]
|
||||
void takePicture(CameraPictureOptions aOptions,
|
||||
CameraTakePictureCallback onSuccess,
|
||||
optional CameraErrorCallback onError);
|
||||
|
||||
/* get a media stream to be used as a camera viewfinder in video mode;
|
||||
'aOptions' is an CameraRecorderOptions object. */
|
||||
[Throws]
|
||||
void getPreviewStreamVideoMode(any aOptions, CameraPreviewStreamCallback onSuccess, optional CameraErrorCallback onError);
|
||||
|
||||
/* start recording video; 'aOptions' is a
|
||||
CameraStartRecordingOptions object. */
|
||||
[Throws]
|
||||
void startRecording(any aOptions, DeviceStorage storageArea, DOMString filename, CameraStartRecordingCallback onSuccess, optional CameraErrorCallback onError);
|
||||
|
||||
/* stop precording video. */
|
||||
[Throws]
|
||||
void stopRecording();
|
||||
|
||||
/* get a media stream to be used as a camera viewfinder; the options
|
||||
define the desired frame size of the preview, chosen from
|
||||
capabilities.previewSizes, e.g.:
|
||||
{
|
||||
height: 640,
|
||||
width: 480,
|
||||
}
|
||||
*/
|
||||
[Throws]
|
||||
void getPreviewStream(any aOptions, CameraPreviewStreamCallback onSuccess, optional CameraErrorCallback onError);
|
||||
|
||||
/* call in or after the takePicture() onSuccess callback to
|
||||
resume the camera preview stream. */
|
||||
[Throws]
|
||||
void resumePreview();
|
||||
|
||||
/* release the camera so that other applications can use it; you should
|
||||
probably call this whenever the camera is not longer in the foreground
|
||||
(depending on your usage model).
|
||||
|
||||
the callbacks are optional, unless you really need to know when
|
||||
the hardware is ultimately released.
|
||||
|
||||
once this is called, the camera control object is to be considered
|
||||
defunct; a new instance will need to be created to access the camera. */
|
||||
[Throws]
|
||||
void release(optional CameraReleaseCallback onSuccess, optional CameraErrorCallback onError);
|
||||
};
|
@ -207,6 +207,12 @@ interface CanvasRenderingContext2D {
|
||||
void asyncDrawXULElement(XULElement elem, double x, double y, double w,
|
||||
double h, DOMString bgColor,
|
||||
optional unsigned long flags = 0);
|
||||
/**
|
||||
* This causes a context that is currently using a hardware-accelerated
|
||||
* backend to fallback to a software one. All state should be preserved.
|
||||
*/
|
||||
[ChromeOnly]
|
||||
void demote();
|
||||
};
|
||||
CanvasRenderingContext2D implements CanvasDrawingStyles;
|
||||
CanvasRenderingContext2D implements CanvasPathMethods;
|
||||
|
@ -19,7 +19,6 @@ interface DummyInterface {
|
||||
void funcDNSLookupDict(optional DNSLookupDict arg);
|
||||
void funcConnStatusDict(optional ConnStatusDict arg);
|
||||
void frameRequestCallback(FrameRequestCallback arg);
|
||||
void CameraPictureOptions(optional CameraPictureOptions arg);
|
||||
void MmsParameters(optional MmsParameters arg);
|
||||
void MmsAttachment(optional MmsAttachment arg);
|
||||
void AsyncScrollEventDetail(optional AsyncScrollEventDetail arg);
|
||||
|
@ -13,6 +13,10 @@ interface WebGLQuery {
|
||||
[Pref="webgl.enable-prototype-webgl2"]
|
||||
interface WebGL2RenderingContext : WebGLRenderingContext {
|
||||
|
||||
/* depth textures */
|
||||
const GLenum UNSIGNED_INT_24_8 = 0x84FA;
|
||||
|
||||
|
||||
/* draw buffers */
|
||||
const GLenum COLOR_ATTACHMENT1 = 0x8CE1;
|
||||
const GLenum COLOR_ATTACHMENT2 = 0x8CE2;
|
||||
@ -107,6 +111,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext {
|
||||
GLintptr offset, GLsizeiptr size);
|
||||
|
||||
|
||||
/* standart derivatives */
|
||||
const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT = 0x8B8B;
|
||||
|
||||
|
||||
/* state requests */
|
||||
any getParameterIndexed(GLenum pname, GLuint index);
|
||||
|
||||
|
@ -34,6 +34,7 @@ webidl_files = \
|
||||
BiquadFilterNode.webidl \
|
||||
Blob.webidl \
|
||||
BrowserElementDictionaries.webidl \
|
||||
CameraControl.webidl \
|
||||
CameraManager.webidl \
|
||||
CanvasRenderingContext2D.webidl \
|
||||
CaretPosition.webidl \
|
||||
|
@ -90,6 +90,7 @@ namespace gl {
|
||||
namespace GLFeature {
|
||||
enum Enum {
|
||||
bind_buffer_offset,
|
||||
blend_minmax,
|
||||
depth_texture,
|
||||
draw_buffers,
|
||||
draw_instanced,
|
||||
|
@ -37,6 +37,15 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
||||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"blend_minmax",
|
||||
200, // OpenGL version
|
||||
300, // OpenGL ES version
|
||||
{
|
||||
GLContext::EXT_blend_minmax,
|
||||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"depth_texture",
|
||||
200, // OpenGL version
|
||||
|
@ -183,7 +183,7 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
|
||||
tmpCtx->DrawSurface(aSurface, gfxSize(serializer.GetSize().width,
|
||||
serializer.GetSize().height));
|
||||
|
||||
if (TextureRequiresLocking(mFlags)) {
|
||||
if (TextureRequiresLocking(mFlags) && !ImplementsLocking()) {
|
||||
// We don't have support for proper locking yet, so we'll
|
||||
// have to be immutable instead.
|
||||
MarkImmutable();
|
||||
|
@ -111,6 +111,16 @@ public:
|
||||
|
||||
virtual void Unlock() {}
|
||||
|
||||
/**
|
||||
* Returns true if this texture has a lock/unlock mechanism.
|
||||
* Textures that do not implement locking should be immutable or should
|
||||
* use immediate uploads (see TextureFlags in CompositorTypes.h)
|
||||
*/
|
||||
virtual bool ImplementsLocking() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetID(uint64_t aID)
|
||||
{
|
||||
MOZ_ASSERT(mID == 0 || aID == 0);
|
||||
|
@ -200,7 +200,7 @@ class FileKind(object):
|
||||
if filename.endswith('.cpp'):
|
||||
return FileKind.CPP
|
||||
|
||||
if filename.endswith(('inlines.h', '-inl.h')):
|
||||
if filename.endswith(('inlines.h', '-inl.h', 'Inlines.h')):
|
||||
return FileKind.INL_H
|
||||
|
||||
if filename.endswith('.h'):
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "jit/CompileInfo.h"
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
namespace js {
|
||||
namespace ion {
|
||||
|
||||
|
@ -279,66 +279,8 @@ struct JSCompartment
|
||||
void markCrossCompartmentWrappers(JSTracer *trc);
|
||||
void markAllCrossCompartmentWrappers(JSTracer *trc);
|
||||
|
||||
bool wrap(JSContext *cx, JS::MutableHandleValue vp,
|
||||
JS::HandleObject existing = js::NullPtr())
|
||||
{
|
||||
JS_ASSERT_IF(existing, vp.isObject());
|
||||
|
||||
/* Only GC things have to be wrapped or copied. */
|
||||
if (!vp.isMarkable())
|
||||
return true;
|
||||
|
||||
/* Handle strings. */
|
||||
if (vp.isString()) {
|
||||
JSString *str = vp.toString();
|
||||
if (!wrap(cx, &str))
|
||||
return false;
|
||||
vp.setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_ASSERT(vp.isObject());
|
||||
|
||||
/*
|
||||
* All that's left are objects.
|
||||
*
|
||||
* Object wrapping isn't the fastest thing in the world, in part because
|
||||
* we have to unwrap and invoke the prewrap hook to find the identity
|
||||
* object before we even start checking the cache. Neither of these
|
||||
* operations are needed in the common case, where we're just wrapping
|
||||
* a plain JS object from the wrappee's side of the membrane to the
|
||||
* wrapper's side.
|
||||
*
|
||||
* To optimize this, we note that the cache should only ever contain
|
||||
* identity objects - that is to say, objects that serve as the
|
||||
* canonical representation for a unique object identity observable by
|
||||
* script. Unwrap and prewrap are both steps that we take to get to the
|
||||
* identity of an incoming objects, and as such, they shuld never map
|
||||
* one identity object to another object. This means that we can safely
|
||||
* check the cache immediately, and only risk false negatives. Do this
|
||||
* in opt builds, and do both in debug builds so that we can assert
|
||||
* that we get the same answer.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
JS::RootedObject cacheResult(cx);
|
||||
#endif
|
||||
JS::RootedValue v(cx, vp);
|
||||
if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(v)) {
|
||||
#ifdef DEBUG
|
||||
cacheResult = &p->value.get().toObject();
|
||||
#else
|
||||
vp.set(p->value);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
JS::RootedObject obj(cx, &vp.toObject());
|
||||
if (!wrap(cx, &obj, existing))
|
||||
return false;
|
||||
vp.setObject(*obj);
|
||||
JS_ASSERT_IF(cacheResult, obj == cacheResult);
|
||||
return true;
|
||||
}
|
||||
inline bool wrap(JSContext *cx, JS::MutableHandleValue vp,
|
||||
JS::HandleObject existing = js::NullPtr());
|
||||
|
||||
bool wrap(JSContext *cx, JSString **strp);
|
||||
bool wrap(JSContext *cx, js::HeapPtrString *strp);
|
||||
|
@ -43,4 +43,65 @@ js::AutoCompartment::~AutoCompartment()
|
||||
cx_->leaveCompartment(origin_);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp, JS::HandleObject existing)
|
||||
{
|
||||
JS_ASSERT_IF(existing, vp.isObject());
|
||||
|
||||
/* Only GC things have to be wrapped or copied. */
|
||||
if (!vp.isMarkable())
|
||||
return true;
|
||||
|
||||
/* Handle strings. */
|
||||
if (vp.isString()) {
|
||||
JSString *str = vp.toString();
|
||||
if (!wrap(cx, &str))
|
||||
return false;
|
||||
vp.setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_ASSERT(vp.isObject());
|
||||
|
||||
/*
|
||||
* All that's left are objects.
|
||||
*
|
||||
* Object wrapping isn't the fastest thing in the world, in part because
|
||||
* we have to unwrap and invoke the prewrap hook to find the identity
|
||||
* object before we even start checking the cache. Neither of these
|
||||
* operations are needed in the common case, where we're just wrapping
|
||||
* a plain JS object from the wrappee's side of the membrane to the
|
||||
* wrapper's side.
|
||||
*
|
||||
* To optimize this, we note that the cache should only ever contain
|
||||
* identity objects - that is to say, objects that serve as the
|
||||
* canonical representation for a unique object identity observable by
|
||||
* script. Unwrap and prewrap are both steps that we take to get to the
|
||||
* identity of an incoming objects, and as such, they shuld never map
|
||||
* one identity object to another object. This means that we can safely
|
||||
* check the cache immediately, and only risk false negatives. Do this
|
||||
* in opt builds, and do both in debug builds so that we can assert
|
||||
* that we get the same answer.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
JS::RootedObject cacheResult(cx);
|
||||
#endif
|
||||
JS::RootedValue v(cx, vp);
|
||||
if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(v)) {
|
||||
#ifdef DEBUG
|
||||
cacheResult = &p->value.get().toObject();
|
||||
#else
|
||||
vp.set(p->value);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
JS::RootedObject obj(cx, &vp.toObject());
|
||||
if (!wrap(cx, &obj, existing))
|
||||
return false;
|
||||
vp.setObject(*obj);
|
||||
JS_ASSERT_IF(cacheResult, obj == cacheResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* jscompartmentinlines_h */
|
||||
|
@ -3909,11 +3909,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
|
||||
" Read filename into returned string. Filename is relative to the directory\n"
|
||||
" containing the current script."),
|
||||
|
||||
JS_FN_HELP("redirect", RedirectOutput, 2, 0,
|
||||
"redirect(stdoutFilename[, stderrFilename])",
|
||||
" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n"
|
||||
" redirecting. Filenames are relative to the current working directory."),
|
||||
|
||||
JS_FN_HELP("compile", Compile, 1, 0,
|
||||
"compile(code)",
|
||||
" Compiles a string to bytecode, potentially throwing."),
|
||||
@ -4018,6 +4013,11 @@ static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
|
||||
"pc2line(fun[, pc])",
|
||||
" Map PC to line number."),
|
||||
|
||||
JS_FN_HELP("redirect", RedirectOutput, 2, 0,
|
||||
"redirect(stdoutFilename[, stderrFilename])",
|
||||
" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n"
|
||||
" redirecting. Filenames are relative to the current working directory."),
|
||||
|
||||
JS_FN_HELP("setThrowHook", SetThrowHook, 1, 0,
|
||||
"setThrowHook(f)",
|
||||
" Set throw hook to f."),
|
||||
|
@ -1165,7 +1165,7 @@ GetPropFromOptions(JSContext *cx, HandleObject from, const char *name, MutableHa
|
||||
if (!JS_HasProperty(cx, from, name, found))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
if (found && !JS_GetProperty(cx, from, name, prop))
|
||||
if (*found && !JS_GetProperty(cx, from, name, prop))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US" class="reftest-print">
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
p { height: 1in; width: 1in; margin:0; background-color:blue; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table cellspacing="0" cellpadding="0"><caption><p>1</p></caption><tr><td><p>1</p><p>2</p></td></tr></table>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US" class="reftest-print">
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
p { height: 1in; width: 1in; margin:0; background-color:blue; }
|
||||
.test { page-break-inside:avoid; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table cellspacing="0" cellpadding="0" class="test"><caption><p>1</p></caption><tr><td><p>1</p><p>2</p></td></tr></table>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US" class="reftest-print">
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
p { height: 1in; width: 1in; margin:0; background-color:blue; }
|
||||
div { page-break-after: always; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>Text</div>
|
||||
<table cellspacing="0" cellpadding="0"><caption><p>1</p></caption><tr><td><p>1</p><p>2</p></td></tr></table>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US" class="reftest-print">
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
p { height: 1in; width: 1in; margin:0; background-color:blue; }
|
||||
.test { page-break-inside:avoid; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>Text</div>
|
||||
<table cellspacing="0" cellpadding="0" class="test"><caption><p>1</p></caption><tr><td><p>1</p><p>2</p></td></tr></table>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US" class="reftest-print">
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
p { height: 1in; width: 1in; margin:0; background-color:blue; }
|
||||
.test { page-break-inside:avoid; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table cellspacing="0" cellpadding="0"><caption><p>1</p></caption><tbody class="test"><tr><td><p>1</p><p>2</p></td></tr></tbody></table>
|
||||
</body>
|
||||
</html>
|
@ -18,6 +18,9 @@
|
||||
== moz-css21-table-page-break-inside-avoid-3.html moz-css21-table-page-break-inside-avoid-3-ref.html
|
||||
== moz-css21-table-page-break-inside-avoid-4.html moz-css21-table-page-break-inside-avoid-4-ref.html
|
||||
== moz-css21-table-page-break-inside-avoid-5.html moz-css21-table-page-break-inside-avoid-5-ref.html
|
||||
== moz-css21-table-page-break-inside-avoid-6.html moz-css21-table-page-break-inside-avoid-6-ref.html
|
||||
== moz-css21-table-page-break-inside-avoid-7.html moz-css21-table-page-break-inside-avoid-7-ref.html
|
||||
== moz-css21-table-page-break-inside-avoid-8.html moz-css21-table-page-break-inside-avoid-6-ref.html
|
||||
== moz-css21-float-page-break-inside-avoid-1.html moz-css21-table-page-break-inside-avoid-ref.html
|
||||
== moz-css21-float-page-break-inside-avoid-2.html moz-css21-float-page-break-inside-avoid-2-ref.html
|
||||
== moz-css21-float-page-break-inside-avoid-3.html moz-css21-block-page-break-inside-avoid-ref.html
|
||||
|
@ -827,15 +827,12 @@ nsTableOuterFrame::OuterBeginReflowChild(nsPresContext* aPresContext,
|
||||
-1, -1, false);
|
||||
InitChildReflowState(*aPresContext, childRS);
|
||||
|
||||
// see if we need to reset top of page due to a caption
|
||||
if (mCaptionFrames.NotEmpty()) {
|
||||
// see if we need to reset top-of-page due to a caption
|
||||
if (childRS.mFlags.mIsTopOfPage &&
|
||||
mCaptionFrames.FirstChild() == aChildFrame) {
|
||||
uint8_t captionSide = GetCaptionSide();
|
||||
if (((captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
|
||||
captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) &&
|
||||
mCaptionFrames.FirstChild() == aChildFrame) ||
|
||||
((captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
|
||||
captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE) &&
|
||||
InnerTableFrame() == aChildFrame)) {
|
||||
if (captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
|
||||
captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) {
|
||||
childRS.mFlags.mIsTopOfPage = false;
|
||||
}
|
||||
}
|
||||
|
@ -5515,7 +5515,7 @@ malloc_print_stats(void)
|
||||
|
||||
#ifdef MALLOC_STATS
|
||||
{
|
||||
size_t allocated, mapped;
|
||||
size_t allocated, mapped = 0;
|
||||
#ifdef MALLOC_BALANCE
|
||||
uint64_t nbalance = 0;
|
||||
#endif
|
||||
|
@ -67,9 +67,7 @@ public class GeckoEvent {
|
||||
REMOVE_OBSERVER(34),
|
||||
LOW_MEMORY(35),
|
||||
NETWORK_LINK_CHANGE(36),
|
||||
TELEMETRY_HISTOGRAM_ADD(37),
|
||||
PREFERENCES_OBSERVE(38),
|
||||
PREFERENCES_GET(39);
|
||||
TELEMETRY_HISTOGRAM_ADD(37);
|
||||
|
||||
public final int value;
|
||||
|
||||
@ -188,8 +186,6 @@ public class GeckoEvent {
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
|
||||
private String[] mPrefNames;
|
||||
|
||||
private GeckoEvent(NativeGeckoEvent event) {
|
||||
mType = event.value;
|
||||
}
|
||||
@ -693,20 +689,6 @@ public class GeckoEvent {
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createPreferencesObserveEvent(int requestId, String[] prefNames) {
|
||||
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.PREFERENCES_OBSERVE);
|
||||
event.mCount = requestId;
|
||||
event.mPrefNames = prefNames;
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createPreferencesGetEvent(int requestId, String[] prefNames) {
|
||||
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.PREFERENCES_GET);
|
||||
event.mCount = requestId;
|
||||
event.mPrefNames = prefNames;
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createLowMemoryEvent(int level) {
|
||||
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.LOW_MEMORY);
|
||||
event.mMetaState = level;
|
||||
|
@ -664,7 +664,9 @@ public class GeckoPreferences
|
||||
|
||||
// Initialize preferences by requesting the preference values from Gecko
|
||||
private int getGeckoPreferences(final PreferenceGroup screen, ArrayList<String> prefs) {
|
||||
return PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
|
||||
JSONArray jsonPrefs = new JSONArray(prefs);
|
||||
|
||||
return PrefsHelper.getPrefs(jsonPrefs, new PrefsHelper.PrefHandlerBase() {
|
||||
private Preference getField(String prefName) {
|
||||
return screen.findPreference(prefName);
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import org.json.JSONObject;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -28,18 +27,20 @@ public final class PrefsHelper {
|
||||
private static int sUniqueRequestId = 1;
|
||||
|
||||
public static int getPref(String prefName, PrefHandler callback) {
|
||||
return getPrefsInternal(new String[] { prefName }, callback);
|
||||
JSONArray prefs = new JSONArray();
|
||||
prefs.put(prefName);
|
||||
return getPrefs(prefs, callback);
|
||||
}
|
||||
|
||||
public static int getPrefs(String[] prefNames, PrefHandler callback) {
|
||||
return getPrefsInternal(prefNames, callback);
|
||||
JSONArray prefs = new JSONArray();
|
||||
for (String p : prefNames) {
|
||||
prefs.put(p);
|
||||
}
|
||||
return getPrefs(prefs, callback);
|
||||
}
|
||||
|
||||
public static int getPrefs(ArrayList<String> prefNames, PrefHandler callback) {
|
||||
return getPrefsInternal(prefNames.toArray(new String[prefNames.size()]), callback);
|
||||
}
|
||||
|
||||
private static int getPrefsInternal(String[] prefNames, PrefHandler callback) {
|
||||
public static int getPrefs(JSONArray prefNames, PrefHandler callback) {
|
||||
int requestId;
|
||||
synchronized (PrefsHelper.class) {
|
||||
ensureRegistered();
|
||||
@ -49,12 +50,25 @@ public final class PrefsHelper {
|
||||
}
|
||||
|
||||
GeckoEvent event;
|
||||
if (callback.isObserver()) {
|
||||
event = GeckoEvent.createPreferencesObserveEvent(requestId, prefNames);
|
||||
} else {
|
||||
event = GeckoEvent.createPreferencesGetEvent(requestId, prefNames);
|
||||
try {
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", Integer.toString(requestId));
|
||||
message.put("preferences", prefNames);
|
||||
event = GeckoEvent.createBroadcastEvent(callback.isObserver() ?
|
||||
"Preferences:Observe" : "Preferences:Get", message.toString());
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Error while composing Preferences:" +
|
||||
(callback.isObserver() ? "Observe" : "Get") + " message", e);
|
||||
|
||||
// if we failed to send the message, drop our reference to the callback because
|
||||
// otherwise it will leak since we will never get the response
|
||||
synchronized (PrefsHelper.class) {
|
||||
sCallbacks.remove(requestId);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
@ -35,14 +35,6 @@ public class RobocopAPI {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(subject, data));
|
||||
}
|
||||
|
||||
public void preferencesGetEvent(int requestId, String[] prefNames) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesGetEvent(requestId, prefNames));
|
||||
}
|
||||
|
||||
public void preferencesObserveEvent(int requestId, String[] prefNames) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesObserveEvent(requestId, prefNames));
|
||||
}
|
||||
|
||||
public void setDrawListener(GeckoLayerClient.DrawListener listener) {
|
||||
GeckoAppShell.getLayerView().getLayerClient().setDrawListener(listener);
|
||||
}
|
||||
|
@ -64,12 +64,13 @@ abstract class Axis {
|
||||
}
|
||||
|
||||
static void initPrefs() {
|
||||
final String[] prefs = { PREF_SCROLLING_FRICTION_FAST,
|
||||
PREF_SCROLLING_FRICTION_SLOW,
|
||||
PREF_SCROLLING_MAX_EVENT_ACCELERATION,
|
||||
PREF_SCROLLING_OVERSCROLL_DECEL_RATE,
|
||||
PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT,
|
||||
PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE };
|
||||
JSONArray prefs = new JSONArray();
|
||||
prefs.put(PREF_SCROLLING_FRICTION_FAST);
|
||||
prefs.put(PREF_SCROLLING_FRICTION_SLOW);
|
||||
prefs.put(PREF_SCROLLING_MAX_EVENT_ACCELERATION);
|
||||
prefs.put(PREF_SCROLLING_OVERSCROLL_DECEL_RATE);
|
||||
prefs.put(PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT);
|
||||
prefs.put(PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE);
|
||||
|
||||
PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
|
||||
Map<String, Integer> mPrefs = new HashMap<String, Integer>();
|
||||
|
@ -61,18 +61,19 @@ final class DisplayPortCalculator {
|
||||
}
|
||||
|
||||
static void initPrefs() {
|
||||
final String[] prefs = { PREF_DISPLAYPORT_STRATEGY,
|
||||
PREF_DISPLAYPORT_FM_MULTIPLIER,
|
||||
PREF_DISPLAYPORT_FM_DANGER_X,
|
||||
PREF_DISPLAYPORT_FM_DANGER_Y,
|
||||
PREF_DISPLAYPORT_VB_MULTIPLIER,
|
||||
PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD,
|
||||
PREF_DISPLAYPORT_VB_REVERSE_BUFFER,
|
||||
PREF_DISPLAYPORT_VB_DANGER_X_BASE,
|
||||
PREF_DISPLAYPORT_VB_DANGER_Y_BASE,
|
||||
PREF_DISPLAYPORT_VB_DANGER_X_INCR,
|
||||
PREF_DISPLAYPORT_VB_DANGER_Y_INCR,
|
||||
PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD };
|
||||
JSONArray prefs = new JSONArray();
|
||||
prefs.put(PREF_DISPLAYPORT_STRATEGY);
|
||||
prefs.put(PREF_DISPLAYPORT_FM_MULTIPLIER);
|
||||
prefs.put(PREF_DISPLAYPORT_FM_DANGER_X);
|
||||
prefs.put(PREF_DISPLAYPORT_FM_DANGER_Y);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_MULTIPLIER);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_REVERSE_BUFFER);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_BASE);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_BASE);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_INCR);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_INCR);
|
||||
prefs.put(PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD);
|
||||
|
||||
PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
|
||||
private Map<String, Integer> mValues = new HashMap<String, Integer>();
|
||||
|
@ -59,18 +59,21 @@ public class testAddonManager extends PixelTest {
|
||||
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
|
||||
|
||||
// Wait for confirmation of the pref change before proceeding with the test.
|
||||
final String[] prefNames = { "extensions.getAddons.browseAddons" };
|
||||
final int ourRequestId = 0x7357;
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put("extensions.getAddons.browseAddons");
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", "testAddonManager");
|
||||
message.put("preferences", getPrefData);
|
||||
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
|
||||
mActions.sendGeckoEvent("Preferences:Get", message.toString());
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
// Wait until we get the correct "Preferences:Data" event
|
||||
while (requestId != ourRequestId) {
|
||||
while (!requestId.equals("testAddonManager")) {
|
||||
data = new JSONObject(eventExpecter.blockForEventData());
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
eventExpecter.unregisterListener();
|
||||
|
||||
|
@ -29,7 +29,7 @@ import org.json.JSONObject;
|
||||
*/
|
||||
public class testDistribution extends ContentProviderTest {
|
||||
private static final String MOCK_PACKAGE = "mock-package.zip";
|
||||
private static final int PREF_REQUEST_ID = 0x7357;
|
||||
private static final String PREF_REQUEST_ID = "testDistribution";
|
||||
|
||||
private Activity mActivity;
|
||||
|
||||
@ -86,23 +86,28 @@ public class testDistribution extends ContentProviderTest {
|
||||
String prefTestInt = "distribution.test.int";
|
||||
|
||||
try {
|
||||
final String[] prefNames = { prefID,
|
||||
prefAbout,
|
||||
prefVersion,
|
||||
prefTestBoolean,
|
||||
prefTestString,
|
||||
prefTestInt };
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put(prefID);
|
||||
getPrefData.put(prefAbout);
|
||||
getPrefData.put(prefVersion);
|
||||
getPrefData.put(prefTestBoolean);
|
||||
getPrefData.put(prefTestString);
|
||||
getPrefData.put(prefTestInt);
|
||||
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", PREF_REQUEST_ID);
|
||||
message.put("preferences", getPrefData);
|
||||
|
||||
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
|
||||
mActions.sendGeckoEvent("Preferences:Get", message.toString());
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
// Wait until we get the correct "Preferences:Data" event
|
||||
while (requestId != PREF_REQUEST_ID) {
|
||||
while (!requestId.equals(PREF_REQUEST_ID)) {
|
||||
data = new JSONObject(eventExpecter.blockForEventData());
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
eventExpecter.unregisterListener();
|
||||
|
||||
@ -167,18 +172,23 @@ public class testDistribution extends ContentProviderTest {
|
||||
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
|
||||
|
||||
// Wait for confirmation of the pref change.
|
||||
final String[] prefNames = { prefUseragentLocale };
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put(prefUseragentLocale);
|
||||
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", PREF_REQUEST_ID);
|
||||
message.put("preferences", getPrefData);
|
||||
|
||||
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
|
||||
mActions.sendGeckoEvent("Preferences:Get", message.toString());
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
// Wait until we get the correct "Preferences:Data" event
|
||||
while (requestId != PREF_REQUEST_ID) {
|
||||
while (!requestId.equals(PREF_REQUEST_ID)) {
|
||||
data = new JSONObject(eventExpecter.blockForEventData());
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
eventExpecter.unregisterListener();
|
||||
|
||||
@ -194,18 +204,25 @@ public class testDistribution extends ContentProviderTest {
|
||||
String prefLocalizeableOverride = "distribution.test.localizeable-override";
|
||||
|
||||
try {
|
||||
final String[] prefNames = { prefAbout, prefLocalizeable, prefLocalizeableOverride };
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put(prefAbout);
|
||||
getPrefData.put(prefLocalizeable);
|
||||
getPrefData.put(prefLocalizeableOverride);
|
||||
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", PREF_REQUEST_ID);
|
||||
message.put("preferences", getPrefData);
|
||||
|
||||
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
|
||||
mActions.sendGeckoEvent("Preferences:Get", message.toString());
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
// Wait until we get the correct "Preferences:Data" event
|
||||
while (requestId != PREF_REQUEST_ID) {
|
||||
while (!requestId.equals(PREF_REQUEST_ID)) {
|
||||
data = new JSONObject(eventExpecter.blockForEventData());
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
eventExpecter.unregisterListener();
|
||||
|
||||
|
@ -81,19 +81,22 @@ public class testDoorHanger extends BaseTest {
|
||||
boolean offlineAllowedByDefault = true;
|
||||
try {
|
||||
// Save offline-allow-by-default preferences first
|
||||
final String[] prefNames = { "offline-apps.allow_by_default" };
|
||||
final int ourRequestId = 0x7357;
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put("offline-apps.allow_by_default");
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", "testDoorHanger");
|
||||
message.put("preferences", getPrefData);
|
||||
|
||||
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
|
||||
mActions.sendGeckoEvent("Preferences:Get", message.toString());
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
// Wait until we get the correct "Preferences:Data" event
|
||||
while (requestId != ourRequestId) {
|
||||
while (!requestId.equals("testDoorHanger")) {
|
||||
data = new JSONObject(eventExpecter.blockForEventData());
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
eventExpecter.unregisterListener();
|
||||
|
||||
|
@ -126,18 +126,21 @@ public class testPasswordEncrypt extends BaseTest {
|
||||
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
|
||||
|
||||
// Wait for confirmation of the pref change before proceeding with the test.
|
||||
final String[] prefNames = { "privacy.masterpassword.enabled" };
|
||||
final int ourRequestId = 0x73577;
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put("privacy.masterpassword.enabled");
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", "testPasswordEncrypt");
|
||||
message.put("preferences", getPrefData);
|
||||
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
|
||||
mActions.sendGeckoEvent("Preferences:Get", message.toString());
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
// Wait until we get the correct "Preferences:Data" event
|
||||
while (requestId != ourRequestId) {
|
||||
while (!requestId.equals("testPasswordEncrypt")) {
|
||||
data = new JSONObject(eventExpecter.blockForEventData());
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
mAsserter.ok(false, "exception in toggleMasterPassword", ex.toString());
|
||||
|
@ -16,7 +16,6 @@ import org.json.JSONObject;
|
||||
*/
|
||||
public class testPrefsObserver extends BaseTest {
|
||||
private static final String PREF_TEST_PREF = "robocop.tests.dummy";
|
||||
private static final int PREF_OBSERVE_REQUEST_ID = 0x7357;
|
||||
private static final String PREF_REQUEST_ID = "testPrefsObserver";
|
||||
private static final long PREF_TIMEOUT = 10000;
|
||||
|
||||
@ -41,15 +40,15 @@ public class testPrefsObserver extends BaseTest {
|
||||
mAsserter.dumpLog("Waiting to check pref");
|
||||
|
||||
JSONObject data = null;
|
||||
int requestId = -1;
|
||||
String requestId = "";
|
||||
|
||||
while (requestId != PREF_OBSERVE_REQUEST_ID) {
|
||||
while (!requestId.equals(PREF_REQUEST_ID)) {
|
||||
data = new JSONObject(mExpecter.blockForEventData());
|
||||
if (!mExpecter.eventReceived()) {
|
||||
mAsserter.ok(false, "Checking pref is correct value", "Didn't receive pref");
|
||||
return;
|
||||
}
|
||||
requestId = data.getInt("requestId");
|
||||
requestId = data.getString("requestId");
|
||||
}
|
||||
|
||||
JSONObject pref = data.getJSONArray("preferences").getJSONObject(0);
|
||||
@ -81,14 +80,19 @@ public class testPrefsObserver extends BaseTest {
|
||||
mAsserter.dumpLog("Setting up pref observer");
|
||||
|
||||
// Setup the pref observer
|
||||
JSONArray getPrefData = new JSONArray();
|
||||
getPrefData.put(PREF_TEST_PREF);
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("requestId", PREF_REQUEST_ID);
|
||||
message.put("preferences", getPrefData);
|
||||
mExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
||||
mActions.sendPreferencesObserveEvent(PREF_OBSERVE_REQUEST_ID, new String[] { PREF_TEST_PREF });
|
||||
mActions.sendGeckoEvent("Preferences:Observe", message.toString());
|
||||
}
|
||||
|
||||
public void removePrefObserver() {
|
||||
mAsserter.dumpLog("Removing pref observer");
|
||||
|
||||
mActions.sendGeckoEvent("Preferences:RemoveObservers", Integer.toString(PREF_OBSERVE_REQUEST_ID));
|
||||
mActions.sendGeckoEvent("Preferences:RemoveObservers", PREF_REQUEST_ID);
|
||||
}
|
||||
|
||||
public void testPrefsObserver() {
|
||||
|
@ -278,7 +278,9 @@ var BrowserApp = {
|
||||
Services.obs.addObserver(this, "Session:Stop", false);
|
||||
Services.obs.addObserver(this, "SaveAs:PDF", false);
|
||||
Services.obs.addObserver(this, "Browser:Quit", false);
|
||||
Services.obs.addObserver(this, "Preferences:Get", false);
|
||||
Services.obs.addObserver(this, "Preferences:Set", false);
|
||||
Services.obs.addObserver(this, "Preferences:Observe", false);
|
||||
Services.obs.addObserver(this, "Preferences:RemoveObservers", false);
|
||||
Services.obs.addObserver(this, "ScrollTo:FocusedInput", false);
|
||||
Services.obs.addObserver(this, "Sanitize:ClearData", false);
|
||||
@ -986,17 +988,16 @@ var BrowserApp = {
|
||||
|
||||
notifyPrefObservers: function(aPref) {
|
||||
this._prefObservers[aPref].forEach(function(aRequestId) {
|
||||
this.getPreferences(aRequestId, [aPref], 1);
|
||||
let request = { requestId : aRequestId,
|
||||
preferences : [aPref] };
|
||||
this.getPreferences(request);
|
||||
}, this);
|
||||
},
|
||||
|
||||
handlePreferencesRequest: function handlePreferencesRequest(aRequestId,
|
||||
aPrefNames,
|
||||
aListen) {
|
||||
|
||||
getPreferences: function getPreferences(aPrefsRequest, aListen) {
|
||||
let prefs = [];
|
||||
|
||||
for (let prefName of aPrefNames) {
|
||||
for (let prefName of aPrefsRequest.preferences) {
|
||||
let pref = {
|
||||
name: prefName,
|
||||
type: "",
|
||||
@ -1005,9 +1006,9 @@ var BrowserApp = {
|
||||
|
||||
if (aListen) {
|
||||
if (this._prefObservers[prefName])
|
||||
this._prefObservers[prefName].push(aRequestId);
|
||||
this._prefObservers[prefName].push(aPrefsRequest.requestId);
|
||||
else
|
||||
this._prefObservers[prefName] = [ aRequestId ];
|
||||
this._prefObservers[prefName] = [ aPrefsRequest.requestId ];
|
||||
Services.prefs.addObserver(prefName, this, false);
|
||||
}
|
||||
|
||||
@ -1114,7 +1115,7 @@ var BrowserApp = {
|
||||
|
||||
sendMessageToJava({
|
||||
type: "Preferences:Data",
|
||||
requestId: aRequestId, // opaque request identifier, can be any string/int/whatever
|
||||
requestId: aPrefsRequest.requestId, // opaque request identifier, can be any string/int/whatever
|
||||
preferences: prefs
|
||||
});
|
||||
},
|
||||
@ -1437,10 +1438,18 @@ var BrowserApp = {
|
||||
this.saveAsPDF(browser);
|
||||
break;
|
||||
|
||||
case "Preferences:Get":
|
||||
this.getPreferences(JSON.parse(aData));
|
||||
break;
|
||||
|
||||
case "Preferences:Set":
|
||||
this.setPreferences(aData);
|
||||
break;
|
||||
|
||||
case "Preferences:Observe":
|
||||
this.getPreferences(JSON.parse(aData), true);
|
||||
break;
|
||||
|
||||
case "Preferences:RemoveObservers":
|
||||
this.removePreferenceObservers(aData);
|
||||
break;
|
||||
@ -1518,14 +1527,6 @@ var BrowserApp = {
|
||||
return this.getTabForId(tabId);
|
||||
},
|
||||
|
||||
getPreferences: function getPreferences(requestId, prefNames, count) {
|
||||
this.handlePreferencesRequest(requestId, prefNames, false);
|
||||
},
|
||||
|
||||
observePreferences: function observePreferences(requestId, prefNames, count) {
|
||||
this.handlePreferencesRequest(requestId, prefNames, true);
|
||||
},
|
||||
|
||||
// This method will print a list from fromIndex to toIndex, optionally
|
||||
// selecting selIndex(if fromIndex<=selIndex<=toIndex)
|
||||
showHistory: function(fromIndex, toIndex, selIndex) {
|
||||
|
@ -16,11 +16,9 @@ EXPORTS += [
|
||||
'nsHTMLTags.h',
|
||||
'nsIContentSink.h',
|
||||
'nsIDTD.h',
|
||||
'nsIElementObserver.h',
|
||||
'nsIFragmentContentSink.h',
|
||||
'nsIHTMLContentSink.h',
|
||||
'nsIParser.h',
|
||||
'nsIParserNode.h',
|
||||
'nsIParserService.h',
|
||||
'nsITokenizer.h',
|
||||
'nsParserBase.h',
|
||||
|
@ -1,46 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
|
||||
/**
|
||||
* MODULE NOTES:
|
||||
* @update rickg 03.23.2000 //removed unused NS_PARSER_SUBJECT and predecl of nsString
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsIElementObserver_h__
|
||||
#define nsIElementObserver_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
|
||||
// {4672AA04-F6AE-11d2-B3B7-00805F8A6670}
|
||||
#define NS_IELEMENTOBSERVER_IID \
|
||||
{ 0x4672aa04, 0xf6ae, 0x11d2, { 0xb3, 0xb7, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } }
|
||||
|
||||
|
||||
class nsIElementObserver : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IELEMENTOBSERVER_IID)
|
||||
|
||||
enum { IS_DOCUMENT_WRITE = 1U };
|
||||
|
||||
/* Subject call observer when the parser hit the tag */
|
||||
NS_IMETHOD Notify(nsISupports* aDocShell,
|
||||
nsISupports* aChannel,
|
||||
const PRUnichar* aTag,
|
||||
const nsTArray<nsString>* aKeys,
|
||||
const nsTArray<nsString>* aValues,
|
||||
const uint32_t aFlags) = 0;
|
||||
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIElementObserver, NS_IELEMENTOBSERVER_IID)
|
||||
|
||||
#endif /* nsIElementObserver_h__ */
|
||||
|
@ -49,13 +49,11 @@
|
||||
* NOTE: I haven't figured out how sub-documents (non-frames)
|
||||
* are going to be handled. Stay tuned.
|
||||
*/
|
||||
#include "nsIParserNode.h"
|
||||
#include "nsIContentSink.h"
|
||||
#include "nsHTMLTags.h"
|
||||
|
||||
#define NS_IHTML_CONTENT_SINK_IID \
|
||||
{ 0xb6d6ae00, 0x0884, 0x4a30, \
|
||||
{ 0xa8, 0xb4, 0xce, 0xca, 0x57, 0x27, 0x1a, 0x3e } }
|
||||
{0xefc5af86, 0x5cfd, 0x4918, {0x9d, 0xd3, 0x5f, 0x7a, 0xb2, 0x88, 0xb2, 0x68}}
|
||||
|
||||
/**
|
||||
* This interface is OBSOLETE and in the process of being REMOVED.
|
||||
@ -67,66 +65,14 @@ public:
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID)
|
||||
|
||||
/**
|
||||
* This method is used to open the HEAD container. It is useful if a tag
|
||||
* is forcing us to open the head (probably again), like if we find a <meta>
|
||||
* tag in the body.
|
||||
*/
|
||||
NS_IMETHOD OpenHead() = 0;
|
||||
|
||||
/**
|
||||
* This gets called when handling illegal contents, especially
|
||||
* in dealing with tables. This method creates a new context.
|
||||
*
|
||||
* @update 04/04/99 harishd
|
||||
* @param aPosition - The position from where the new context begins.
|
||||
*/
|
||||
NS_IMETHOD BeginContext(int32_t aPosition) = 0;
|
||||
|
||||
/**
|
||||
* This method terminates any new context that got created by
|
||||
* BeginContext and switches back to the main context.
|
||||
*
|
||||
* @update 04/04/99 harishd
|
||||
* @param aPosition - Validates the end of a context.
|
||||
*/
|
||||
NS_IMETHOD EndContext(int32_t aPosition) = 0;
|
||||
|
||||
/**
|
||||
* @update 01/09/2003 harishd
|
||||
* @param aTag - Check if this tag is enabled or not.
|
||||
*/
|
||||
NS_IMETHOD IsEnabled(int32_t aTag, bool* aReturn) = 0;
|
||||
|
||||
/**
|
||||
* This method is called when parser has
|
||||
* completed processing a chunk of tokens. The processing of the
|
||||
* tokens may be interrupted by returning NS_ERROR_HTMLPARSER_INTERRUPTED from
|
||||
* DidProcessAToken.
|
||||
*/
|
||||
NS_IMETHOD DidProcessTokens() = 0;
|
||||
|
||||
/**
|
||||
* This method is called when parser is about to
|
||||
* process a single token
|
||||
*/
|
||||
NS_IMETHOD WillProcessAToken(void) = 0;
|
||||
|
||||
/**
|
||||
* This method is called when parser has completed
|
||||
* the processing for a single token.
|
||||
* @return NS_OK if processing should not be interrupted
|
||||
* NS_ERROR_HTMLPARSER_INTERRUPTED if the parsing should be interrupted
|
||||
*/
|
||||
NS_IMETHOD DidProcessAToken(void) = 0;
|
||||
enum ElementType { eHTML, eBody };
|
||||
|
||||
/**
|
||||
* This method is used to open a generic container in the sink.
|
||||
*
|
||||
* @update 4/1/98 gess
|
||||
* @param nsIParserNode reference to parser node interface
|
||||
*/
|
||||
NS_IMETHOD OpenContainer(const nsIParserNode& aNode) = 0;
|
||||
NS_IMETHOD OpenContainer(ElementType aNodeType) = 0;
|
||||
|
||||
/**
|
||||
* This method gets called by the parser when a close
|
||||
@ -134,29 +80,7 @@ public:
|
||||
*
|
||||
* @param aTag - The tag to be closed.
|
||||
*/
|
||||
NS_IMETHOD CloseContainer(const nsHTMLTag aTag) = 0;
|
||||
|
||||
/**
|
||||
* This method is used when we're closing a tag that was malformed
|
||||
* in some way. This way, the content sink can do special processing
|
||||
* (e.g., not execute a malformed script tag).
|
||||
*
|
||||
* @param aTag The tag to be closed.
|
||||
*/
|
||||
NS_IMETHOD CloseMalformedContainer(const nsHTMLTag aTag)
|
||||
{
|
||||
return CloseContainer(aTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called by the parser when you want to add
|
||||
* a leaf node to the current container in the content
|
||||
* model.
|
||||
*
|
||||
* @update 4/1/98 gess
|
||||
* @param nsIParserNode reference to parser node interface
|
||||
*/
|
||||
NS_IMETHOD AddLeaf(const nsIParserNode& aNode) = 0;
|
||||
NS_IMETHOD CloseContainer(ElementType aTag) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLContentSink, NS_IHTML_CONTENT_SINK_IID)
|
||||
|
@ -58,23 +58,6 @@ enum eParserDocType {
|
||||
|
||||
enum eStreamState {eNone,eOnStart,eOnDataAvail,eOnStop};
|
||||
|
||||
/**
|
||||
* FOR DEBUG PURPOSE ONLY
|
||||
*
|
||||
* Use this interface to query objects that contain content information.
|
||||
* Ex. Parser can trigger dump content by querying the sink that has
|
||||
* access to the content.
|
||||
*
|
||||
* @update harishd 05/25/00
|
||||
*/
|
||||
class nsIDebugDumpContent : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDEBUG_DUMP_CONTENT_IID)
|
||||
NS_IMETHOD DumpContentModel()=0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDebugDumpContent, NS_IDEBUG_DUMP_CONTENT_IID)
|
||||
|
||||
/**
|
||||
* This GECKO-INTERNAL interface is on track to being REMOVED (or refactored
|
||||
* to the point of being near-unrecognizable).
|
||||
|
@ -1,78 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
|
||||
/**
|
||||
* MODULE NOTES:
|
||||
* @update gess 4/1/98
|
||||
*
|
||||
* This class is defines the basic interface between the
|
||||
* parser and the content sink. The parser will iterate
|
||||
* over the collection of tokens that it sees from the
|
||||
* tokenizer, coverting each related "group" into one of
|
||||
* these. This object gets passed to the sink, and is
|
||||
* then immediately reused.
|
||||
*
|
||||
* If you want to hang onto one of these, you should
|
||||
* make your own copy.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NS_IPARSERNODE__
|
||||
#define NS_IPARSERNODE__
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIAtom;
|
||||
|
||||
/**
|
||||
* Parser nodes are the unit of exchange between the
|
||||
* parser and the content sink. Nodes offer access to
|
||||
* the current token, its attributes, and its skipped-
|
||||
* content if applicable.
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
*/
|
||||
class nsIParserNode {
|
||||
public:
|
||||
/**
|
||||
* Retrieve the type of the parser node.
|
||||
* @update gess5/11/98
|
||||
* @return node type.
|
||||
*/
|
||||
virtual int32_t GetNodeType() const =0;
|
||||
|
||||
/**
|
||||
* Retrieve token type of parser node
|
||||
* @update gess5/11/98
|
||||
* @return token type
|
||||
*/
|
||||
virtual int32_t GetTokenType() const =0;
|
||||
|
||||
/**
|
||||
* Retrieve the number of attributes in this node.
|
||||
* @update gess5/11/98
|
||||
* @return count of attributes (may be 0)
|
||||
*/
|
||||
virtual int32_t GetAttributeCount() const =0;
|
||||
|
||||
/**
|
||||
* Retrieve the key (of key/value pair) at given index
|
||||
* @update gess5/11/98
|
||||
* @param anIndex is the index of the key you want
|
||||
* @return string containing key.
|
||||
*/
|
||||
virtual const nsAString& GetKeyAt(uint32_t anIndex) const = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the value (of key/value pair) at given index
|
||||
* @update gess5/11/98
|
||||
* @param anIndex is the index of the value you want
|
||||
* @return string containing value.
|
||||
*/
|
||||
virtual const nsAString& GetValueAt(uint32_t anIndex) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -9,10 +9,8 @@
|
||||
#include "nsISupports.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsIElementObserver.h"
|
||||
|
||||
class nsIParser;
|
||||
class nsIParserNode;
|
||||
|
||||
#define NS_PARSERSERVICE_CONTRACTID "@mozilla.org/parser/parser-service;1"
|
||||
|
||||
|
@ -6,13 +6,6 @@
|
||||
#ifndef CTOKEN__
|
||||
#define CTOKEN__
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "nsString.h"
|
||||
#include "nsError.h"
|
||||
|
||||
class nsScanner;
|
||||
class nsTokenAllocator;
|
||||
|
||||
enum eHTMLTokenTypes {
|
||||
eToken_unknown=0,
|
||||
eToken_start=1, eToken_end, eToken_comment, eToken_entity,
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "nsIParser.h"
|
||||
#include "CNavDTD.h"
|
||||
#include "nsIHTMLContentSink.h"
|
||||
#include "nsParserNode.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CNavDTD, nsIDTD);
|
||||
|
||||
@ -42,17 +41,14 @@ CNavDTD::BuildModel(nsITokenizer* aTokenizer,
|
||||
return NS_ERROR_HTMLPARSER_STOPPARSING;
|
||||
}
|
||||
|
||||
nsParserNode html(eHTMLTag_html);
|
||||
nsParserNode body(eHTMLTag_body);
|
||||
|
||||
nsresult rv = sink->OpenContainer(html);
|
||||
nsresult rv = sink->OpenContainer(nsIHTMLContentSink::eHTML);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = sink->OpenContainer(body);
|
||||
rv = sink->OpenContainer(nsIHTMLContentSink::eBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = sink->CloseContainer(eHTMLTag_body);
|
||||
rv = sink->CloseContainer(nsIHTMLContentSink::eBody);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
rv = sink->CloseContainer(eHTMLTag_html);
|
||||
rv = sink->CloseContainer(nsIHTMLContentSink::eHTML);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -73,12 +73,7 @@ CParserContext::GetTokenizer(nsIDTD* aDTD,
|
||||
|
||||
if (!mTokenizer) {
|
||||
if (type == NS_IPARSER_FLAG_HTML || mParserCommand == eViewSource) {
|
||||
nsCOMPtr<nsIHTMLContentSink> theSink = do_QueryInterface(aSink);
|
||||
mTokenizer = new nsHTMLTokenizer(mDTDMode, mDocType, mParserCommand,
|
||||
nsHTMLTokenizer::GetFlags(aSink));
|
||||
if (!mTokenizer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mTokenizer = new nsHTMLTokenizer;
|
||||
}
|
||||
else if (type == NS_IPARSER_FLAG_XML) {
|
||||
mTokenizer = do_QueryInterface(aDTD, &result);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user