Merge inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2013-08-26 20:19:26 -04:00
commit 9fa9f53229
138 changed files with 2546 additions and 2600 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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() {

View File

@ -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

View 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();
}

View File

@ -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

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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>

View File

@ -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":

View File

@ -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

View File

@ -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;

View File

@ -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'):

View File

@ -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(

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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
//

View File

@ -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();

View File

@ -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();

View 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"));
}

View File

@ -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;
}

View File

@ -38,6 +38,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLContextReporter.cpp',
'WebGLContextState.cpp',
'WebGLContextValidate.cpp',
'WebGLContextExtensions.cpp',
'WebGLContextFramebufferOperations.cpp',
'WebGLContextVertexArray.cpp',
'WebGLContextVertices.cpp',

View File

@ -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

View 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

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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; }

View File

@ -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());

View File

@ -6,7 +6,6 @@
#define nsIXMLContentSink_h___
#include "nsIContentSink.h"
#include "nsIParserNode.h"
#include "nsISupports.h"
class nsIDocument;

View File

@ -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,

View File

@ -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;
}

View File

@ -140,7 +140,6 @@ DOMCI_CLASS(FMRadio)
DOMCI_CLASS(BluetoothDevice)
#endif
DOMCI_CLASS(CameraControl)
DOMCI_CLASS(CameraCapabilities)
DOMCI_CLASS(LockedFile)

View File

@ -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)
{

View File

@ -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);

View File

@ -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')

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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!");
}
/**

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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";

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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

View 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);
};

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -34,6 +34,7 @@ webidl_files = \
BiquadFilterNode.webidl \
Blob.webidl \
BrowserElementDictionaries.webidl \
CameraControl.webidl \
CameraManager.webidl \
CanvasRenderingContext2D.webidl \
CaretPosition.webidl \

View File

@ -90,6 +90,7 @@ namespace gl {
namespace GLFeature {
enum Enum {
bind_buffer_offset,
blend_minmax,
depth_texture,
draw_buffers,
draw_instanced,

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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'):

View File

@ -11,6 +11,8 @@
#include "jit/CompileInfo.h"
#include "jsscriptinlines.h"
namespace js {
namespace ion {

View File

@ -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);

View File

@ -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 */

View File

@ -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."),

View File

@ -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;

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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>();

View File

@ -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>();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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());

View File

@ -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() {

View File

@ -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) {

View File

@ -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',

View File

@ -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__ */

View File

@ -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)

View File

@ -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).

View File

@ -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

View File

@ -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"

View File

@ -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,

View File

@ -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;

View File

@ -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