mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Merge the last PGO-green inbound changeset to m-c.
This commit is contained in:
commit
292a5ce0ff
@ -32,7 +32,7 @@ nsTextEquivUtils::GetNameFromSubtree(Accessible* aAccessible,
|
||||
return NS_OK;
|
||||
|
||||
gInitiatorAcc = aAccessible;
|
||||
if (GetRoleRule(aAccessible->Role()) == eFromSubtree) {
|
||||
if (IsNameFromSubtreeAllowed(aAccessible)) {
|
||||
//XXX: is it necessary to care the accessible is not a document?
|
||||
if (aAccessible->IsContent()) {
|
||||
nsAutoString name;
|
||||
|
@ -89,6 +89,14 @@ public:
|
||||
static nsresult AppendTextEquivFromTextContent(nsIContent *aContent,
|
||||
nsAString *aString);
|
||||
|
||||
/**
|
||||
* Return true if the given accessible allows name from subtree.
|
||||
*/
|
||||
static bool IsNameFromSubtreeAllowed(Accessible* aAccessible)
|
||||
{
|
||||
return GetRoleRule(aAccessible->Role()) == eFromSubtree;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Iterates accessible children and calculates text equivalent from each
|
||||
|
@ -275,7 +275,7 @@ Accessible::Name(nsString& aName)
|
||||
|
||||
ENameValueFlag nameFlag = NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
// In the end get the name from tooltip.
|
||||
if (mContent->IsHTML()) {
|
||||
@ -288,14 +288,12 @@ Accessible::Name(nsString& aName)
|
||||
aName.CompressWhitespace();
|
||||
return eNameFromTooltip;
|
||||
}
|
||||
} else {
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
if (nameFlag != eNoNameOnPurpose)
|
||||
aName.SetIsVoid(true);
|
||||
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1055,7 +1053,7 @@ Accessible::TakeFocus()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ENameValueFlag
|
||||
Accessible::GetHTMLName(nsString& aLabel)
|
||||
{
|
||||
Accessible* labelAcc = nullptr;
|
||||
@ -1066,8 +1064,11 @@ Accessible::GetHTMLName(nsString& aLabel)
|
||||
aLabel.CompressWhitespace();
|
||||
}
|
||||
|
||||
if (aLabel.IsEmpty())
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
|
||||
if (!aLabel.IsEmpty())
|
||||
return eNameOK;
|
||||
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
|
||||
return aLabel.IsEmpty() ? eNameOK : eNameFromSubtree;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1082,7 +1083,7 @@ Accessible::GetHTMLName(nsString& aLabel)
|
||||
* the control that uses the control="controlID" syntax will use
|
||||
* the child label for its Name.
|
||||
*/
|
||||
void
|
||||
ENameValueFlag
|
||||
Accessible::GetXULName(nsString& aName)
|
||||
{
|
||||
// CASE #1 (via label attribute) -- great majority of the cases
|
||||
@ -1125,10 +1126,9 @@ Accessible::GetXULName(nsString& aName)
|
||||
}
|
||||
}
|
||||
|
||||
// XXX If CompressWhiteSpace worked on nsAString we could avoid a copy
|
||||
aName.CompressWhitespace();
|
||||
if (!aName.IsEmpty())
|
||||
return;
|
||||
return eNameOK;
|
||||
|
||||
// Can get text from title of <toolbaritem> if we're a child of a <toolbaritem>
|
||||
nsIContent *bindingParent = mContent->GetBindingParent();
|
||||
@ -1138,12 +1138,13 @@ Accessible::GetXULName(nsString& aName)
|
||||
if (parent->Tag() == nsGkAtoms::toolbaritem &&
|
||||
parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
|
||||
aName.CompressWhitespace();
|
||||
return;
|
||||
return eNameOK;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1229,6 +1230,13 @@ Accessible::GetAttributes(nsIPersistentProperties **aAttributes)
|
||||
if (State() & states::CHECKABLE)
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::checkable, NS_LITERAL_STRING("true"));
|
||||
|
||||
// Expose 'explicit-name' attribute.
|
||||
if (!nsTextEquivUtils::IsNameFromSubtreeAllowed(this) ||
|
||||
Name(oldValueUnused) != eNameFromSubtree) {
|
||||
attributes->SetStringProperty(NS_LITERAL_CSTRING("explicit-name"),
|
||||
NS_LITERAL_STRING("true"), oldValueUnused);
|
||||
}
|
||||
|
||||
// Group attributes (level/setsize/posinset)
|
||||
GroupPos groupPos = GroupPosition();
|
||||
nsAccUtils::SetAccGroupAttrs(attributes, groupPos.level,
|
||||
@ -2420,23 +2428,18 @@ Accessible::Shutdown()
|
||||
|
||||
// Accessible protected
|
||||
void
|
||||
Accessible::ARIAName(nsAString& aName)
|
||||
Accessible::ARIAName(nsString& aName)
|
||||
{
|
||||
nsAutoString label;
|
||||
|
||||
// aria-labelledby now takes precedence over aria-label
|
||||
nsresult rv = nsTextEquivUtils::
|
||||
GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, label);
|
||||
GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, aName);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
label.CompressWhitespace();
|
||||
aName = label;
|
||||
aName.CompressWhitespace();
|
||||
}
|
||||
|
||||
if (label.IsEmpty() &&
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label,
|
||||
label)) {
|
||||
label.CompressWhitespace();
|
||||
aName = label;
|
||||
if (aName.IsEmpty() &&
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label, aName)) {
|
||||
aName.CompressWhitespace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2445,9 +2448,10 @@ ENameValueFlag
|
||||
Accessible::NativeName(nsString& aName)
|
||||
{
|
||||
if (mContent->IsHTML())
|
||||
GetHTMLName(aName);
|
||||
else if (mContent->IsXUL())
|
||||
GetXULName(aName);
|
||||
return GetHTMLName(aName);
|
||||
|
||||
if (mContent->IsXUL())
|
||||
return GetXULName(aName);
|
||||
|
||||
return eNameOK;
|
||||
}
|
||||
|
@ -58,6 +58,11 @@ enum ENameValueFlag {
|
||||
*/
|
||||
eNoNameOnPurpose,
|
||||
|
||||
/**
|
||||
* Name was computed from the subtree.
|
||||
*/
|
||||
eNameFromSubtree,
|
||||
|
||||
/**
|
||||
* Tooltip was used as a name.
|
||||
*/
|
||||
@ -805,13 +810,13 @@ protected:
|
||||
/**
|
||||
* Returns the accessible name specified by ARIA.
|
||||
*/
|
||||
void ARIAName(nsAString& aName);
|
||||
void ARIAName(nsString& aName);
|
||||
|
||||
/**
|
||||
* Compute the name of HTML/XUL node.
|
||||
*/
|
||||
void GetHTMLName(nsString& aName);
|
||||
void GetXULName(nsString& aName);
|
||||
mozilla::a11y::ENameValueFlag GetHTMLName(nsString& aName);
|
||||
mozilla::a11y::ENameValueFlag GetXULName(nsString& aName);
|
||||
|
||||
// helper method to verify frames
|
||||
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
|
||||
|
@ -1953,12 +1953,14 @@ HyperTextAccessible::ScrollSubstringToPoint(int32_t aStartIndex,
|
||||
ENameValueFlag
|
||||
HyperTextAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
AccessibleWrap::NativeName(aName);
|
||||
ENameValueFlag nameFlag = AccessibleWrap::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return nameFlag;
|
||||
|
||||
// Get name from title attribute for HTML abbr and acronym elements making it
|
||||
// a valid name from markup. Otherwise their name isn't picked up by recursive
|
||||
// name computation algorithm. See NS_OK_NAME_FROM_TOOLTIP.
|
||||
if (aName.IsEmpty() && IsAbbreviation() &&
|
||||
if (IsAbbreviation() &&
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
|
||||
aName.CompressWhitespace();
|
||||
|
||||
|
@ -77,16 +77,15 @@ ImageAccessible::NativeName(nsString& aName)
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
|
||||
Accessible::NativeName(aName);
|
||||
if (aName.IsEmpty() && hasAltAttrib) {
|
||||
// No accessible name but empty 'alt' attribute is present. If further name
|
||||
// computation algorithm doesn't provide non empty name then it means
|
||||
// an empty 'alt' attribute was used to indicate a decorative image (see
|
||||
// nsIAccessible::name attribute for details).
|
||||
return eNoNameOnPurpose;
|
||||
}
|
||||
ENameValueFlag nameFlag = Accessible::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return nameFlag;
|
||||
|
||||
return eNameOK;
|
||||
// No accessible name but empty 'alt' attribute is present. If further name
|
||||
// computation algorithm doesn't provide non empty name then it means
|
||||
// an empty 'alt' attribute was used to indicate a decorative image (see
|
||||
// Accessible::Name() method for details).
|
||||
return hasAltAttrib ? eNoNameOnPurpose : eNameOK;
|
||||
}
|
||||
|
||||
role
|
||||
|
@ -58,7 +58,7 @@ ENameValueFlag
|
||||
HTMLLabelAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||
return eNameOK;
|
||||
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
|
||||
}
|
||||
|
||||
role
|
||||
|
@ -259,13 +259,13 @@ HTMLButtonAccessible::NativeRole()
|
||||
ENameValueFlag
|
||||
HTMLButtonAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
Accessible::NativeName(aName);
|
||||
ENameValueFlag nameFlag = Accessible::NativeName(aName);
|
||||
if (!aName.IsEmpty() || mContent->Tag() != nsGkAtoms::input)
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
// No name from HTML or ARIA
|
||||
if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName) &&
|
||||
!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) {
|
||||
// Note: No need to check @value attribute since it results in anonymous text
|
||||
// node. The name is calculated from subtree in this case.
|
||||
if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) {
|
||||
// Use the button's (default) label if nothing else works
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (frame) {
|
||||
@ -323,9 +323,9 @@ HTMLTextFieldAccessible::NativeRole()
|
||||
ENameValueFlag
|
||||
HTMLTextFieldAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
Accessible::NativeName(aName);
|
||||
ENameValueFlag nameFlag = Accessible::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
if (mContent->GetBindingParent()) {
|
||||
// XXX: bug 459640
|
||||
@ -613,9 +613,9 @@ HTMLGroupboxAccessible::GetLegend()
|
||||
ENameValueFlag
|
||||
HTMLGroupboxAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
Accessible::NativeName(aName);
|
||||
ENameValueFlag nameFlag = Accessible::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
nsIContent* legendContent = GetLegend();
|
||||
if (legendContent)
|
||||
@ -696,9 +696,9 @@ HTMLFigureAccessible::NativeRole()
|
||||
ENameValueFlag
|
||||
HTMLFigureAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
HyperTextAccessibleWrap::NativeName(aName);
|
||||
ENameValueFlag nameFlag = HyperTextAccessibleWrap::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
nsIContent* captionContent = Caption();
|
||||
if (captionContent)
|
||||
|
@ -163,9 +163,9 @@ HTMLAreaAccessible::
|
||||
ENameValueFlag
|
||||
HTMLAreaAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
Accessible::NativeName(aName);
|
||||
ENameValueFlag nameFlag = Accessible::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
|
||||
GetValue(aName);
|
||||
|
@ -200,6 +200,7 @@ HTMLSelectOptionAccessible::NativeName(nsString& aName)
|
||||
if (text && text->IsNodeOfType(nsINode::eTEXT)) {
|
||||
nsTextEquivUtils::AppendTextEquivFromTextContent(text, &aName);
|
||||
aName.CompressWhitespace();
|
||||
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
|
||||
}
|
||||
|
||||
return eNameOK;
|
||||
|
@ -388,9 +388,9 @@ HTMLTableAccessible::NativeState()
|
||||
ENameValueFlag
|
||||
HTMLTableAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
Accessible::NativeName(aName);
|
||||
ENameValueFlag nameFlag = Accessible::NativeName(aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
return nameFlag;
|
||||
|
||||
// Use table caption as a name.
|
||||
Accessible* caption = Caption();
|
||||
|
@ -125,10 +125,11 @@ ENameValueFlag
|
||||
XULLinkAccessible::NativeName(nsString& aName)
|
||||
{
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
|
||||
if (aName.IsEmpty())
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||
if (!aName.IsEmpty())
|
||||
return eNameOK;
|
||||
|
||||
return eNameOK;
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
|
||||
}
|
||||
|
||||
role
|
||||
|
@ -634,8 +634,7 @@ XULListitemAccessible::NativeName(nsString& aName)
|
||||
}
|
||||
}
|
||||
|
||||
GetXULName(aName);
|
||||
return eNameOK;
|
||||
return GetXULName(aName);
|
||||
}
|
||||
|
||||
role
|
||||
|
@ -188,6 +188,11 @@ function testNameForAttrRule(aElm, aRule)
|
||||
|
||||
var msg = "Attribute '" + attr + "' test. ";
|
||||
testName(aElm, name, msg);
|
||||
if (aRule.getAttribute("explict-name") != "false")
|
||||
testAttrs(aElm, {"explicit-name" : "true"}, true);
|
||||
else
|
||||
testAbsentAttrs(aElm, {"explicit-name" : "true"});
|
||||
|
||||
aElm.removeAttribute(attr);
|
||||
|
||||
gTestIterator.iterateNext();
|
||||
@ -235,6 +240,7 @@ function testNameForElmRule(aElm, aRule)
|
||||
|
||||
var msg = "Element '" + tagname + "' test.";
|
||||
testName(aElm, labelElm.getAttribute("a11yname"), msg);
|
||||
testAttrs(aElm, {"explicit-name" : "true"}, true);
|
||||
|
||||
var parentNode = labelElm.parentNode;
|
||||
|
||||
@ -252,6 +258,7 @@ function testNameForSubtreeRule(aElm, aRule)
|
||||
{
|
||||
var msg = "From subtree test.";
|
||||
testName(aElm, aElm.getAttribute("a11yname"), msg);
|
||||
testAbsentAttrs(aElm, {"explicit-name" : "true"});
|
||||
|
||||
if (gDumpToConsole) {
|
||||
dump("\nProcessed from subtree rule. Wait for reorder event on " +
|
||||
|
@ -125,7 +125,7 @@
|
||||
<!-- specific -->
|
||||
<ruleset id="htmlinputbutton">
|
||||
<ruleset ref="htmlelm_start"/>
|
||||
<rule attr="value" type="string"/>
|
||||
<rule attr="value" type="string" explict-name="false"/>
|
||||
<rule attr="alt" type="string"/>
|
||||
<rule attr="src" type="string"/>
|
||||
<rule attr="data" type="string"/>
|
||||
|
@ -13,6 +13,8 @@
|
||||
src="../events.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../name.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../attributes.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="markup.js"></script>
|
||||
|
@ -26,16 +26,24 @@ const SELF_DESTRUCT_TIMEOUT =
|
||||
Services.prefs.getIntPref("b2g.update.self-destruct-timeout");
|
||||
|
||||
const APPLY_IDLE_TIMEOUT_SECONDS = APPLY_IDLE_TIMEOUT / 1000;
|
||||
|
||||
const NETWORK_ERROR_OFFLINE = 111;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "aus",
|
||||
"@mozilla.org/updates/update-service;1",
|
||||
"nsIApplicationUpdateService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "um",
|
||||
"@mozilla.org/updates/update-manager;1",
|
||||
"nsIUpdateManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "idle",
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
"nsIIdleService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "settings",
|
||||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
function UpdatePrompt() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
@ -43,6 +51,7 @@ function UpdatePrompt() {
|
||||
UpdatePrompt.prototype = {
|
||||
classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
|
||||
Ci.nsIUpdateCheckListener,
|
||||
Ci.nsIRequestObserver,
|
||||
Ci.nsIProgressEventSink,
|
||||
Ci.nsIObserver]),
|
||||
@ -88,14 +97,52 @@ UpdatePrompt.prototype = {
|
||||
},
|
||||
|
||||
showUpdateError: function UP_showUpdateError(aUpdate) {
|
||||
if (aUpdate.state == "failed") {
|
||||
log("Failed to download update, errorCode: " + aUpdate.errorCode);
|
||||
}
|
||||
log("Update error, state: " + aUpdate.state + ", errorCode: " +
|
||||
aUpdate.errorCode);
|
||||
|
||||
this.sendUpdateEvent("update-error", aUpdate);
|
||||
this.setUpdateStatus(aUpdate.statusText);
|
||||
},
|
||||
|
||||
showUpdateHistory: function UP_showUpdateHistory(aParent) { },
|
||||
showUpdateInstalled: function UP_showUpdateInstalled() { },
|
||||
|
||||
// nsIUpdateCheckListener
|
||||
|
||||
onCheckComplete: function UP_onCheckComplete(request, updates, updateCount) {
|
||||
if (Services.um.activeUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateCount == 0) {
|
||||
this.setUpdateStatus("no-updates");
|
||||
return;
|
||||
}
|
||||
|
||||
let update = Services.aus.selectUpdate(updates, updateCount);
|
||||
if (!update) {
|
||||
this.setUpdateStatus("already-latest-version");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setUpdateStatus("check-complete");
|
||||
this.showUpdateAvailable(update);
|
||||
},
|
||||
|
||||
onError: function UP_onError(request, update) {
|
||||
if (update.errorCode == NETWORK_ERROR_OFFLINE) {
|
||||
this.setUpdateStatus("retry-when-online");
|
||||
}
|
||||
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onError(request, update);
|
||||
},
|
||||
|
||||
onProgress: function UP_onProgress(request, position, totalSize) {
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onProgress(request, position, totalSize);
|
||||
},
|
||||
|
||||
// Custom functions
|
||||
|
||||
waitForIdle: function UP_waitForIdle() {
|
||||
@ -108,6 +155,13 @@ UpdatePrompt.prototype = {
|
||||
Services.obs.addObserver(this, "quit-application", false);
|
||||
},
|
||||
|
||||
setUpdateStatus: function UP_setUpdateStatus(aStatus) {
|
||||
log("Setting gecko.updateStatus: " + aStatus);
|
||||
|
||||
let lock = Services.settings.createLock();
|
||||
lock.set("gecko.updateStatus", aStatus, null);
|
||||
},
|
||||
|
||||
showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
|
||||
if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
|
||||
log("Unable to prompt, forcing restart");
|
||||
@ -123,22 +177,26 @@ UpdatePrompt.prototype = {
|
||||
sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
|
||||
let detail = {
|
||||
displayVersion: aUpdate.displayVersion,
|
||||
detailsURL: aUpdate.detailsURL
|
||||
detailsURL: aUpdate.detailsURL,
|
||||
statusText: aUpdate.statusText,
|
||||
state: aUpdate.state,
|
||||
errorCode: aUpdate.errorCode,
|
||||
isOSUpdate: aUpdate.isOSUpdate
|
||||
};
|
||||
|
||||
let patch = aUpdate.selectedPatch;
|
||||
if (!patch) {
|
||||
if (!patch && aUpdate.patchCount > 0) {
|
||||
// For now we just check the first patch to get size information if a
|
||||
// patch hasn't been selected yet.
|
||||
if (aUpdate.patchCount == 0) {
|
||||
log("Warning: no patches available in update");
|
||||
return false;
|
||||
}
|
||||
patch = aUpdate.getPatchAt(0);
|
||||
}
|
||||
|
||||
detail.size = patch.size;
|
||||
detail.updateType = patch.type;
|
||||
if (patch) {
|
||||
detail.size = patch.size;
|
||||
detail.updateType = patch.type;
|
||||
} else {
|
||||
log("Warning: no patches available in update");
|
||||
}
|
||||
|
||||
this._update = aUpdate;
|
||||
return this.sendChromeEvent(aType, detail);
|
||||
@ -252,11 +310,17 @@ UpdatePrompt.prototype = {
|
||||
forceUpdateCheck: function UP_forceUpdateCheck() {
|
||||
log("Forcing update check");
|
||||
|
||||
// If we already have an active update available, don't try to
|
||||
// download again, just prompt for install.
|
||||
if (Services.um.activeUpdate) {
|
||||
this.setUpdateStatus("check-complete");
|
||||
this.showApplyPrompt(Services.um.activeUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
let checker = Cc["@mozilla.org/updates/update-checker;1"]
|
||||
.createInstance(Ci.nsIUpdateChecker);
|
||||
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
checker.checkForUpdates(Services.aus, true);
|
||||
checker.checkForUpdates(this, true);
|
||||
},
|
||||
|
||||
handleEvent: function UP_handleEvent(evt) {
|
||||
|
@ -178,6 +178,24 @@ let SocialUI = {
|
||||
|
||||
haveLoggedInUser: function SocialUI_haveLoggedInUser() {
|
||||
return !!(Social.provider && Social.provider.profile && Social.provider.profile.userName);
|
||||
},
|
||||
|
||||
closeSocialPanelForLinkTraversal: function (target, linkNode) {
|
||||
// No need to close the panel if this traversal was not retargeted
|
||||
if (target == "" || target == "_self")
|
||||
return;
|
||||
|
||||
// Check to see whether this link traversal was in a social panel
|
||||
let win = linkNode.ownerDocument.defaultView;
|
||||
let container = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
let containerParent = container.parentNode;
|
||||
if (containerParent.classList.contains("social-panel") &&
|
||||
containerParent instanceof Ci.nsIDOMXULPopupElement) {
|
||||
containerParent.hidePopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,7 +645,7 @@ var SocialToolbar = {
|
||||
let tbi = document.getElementById("social-toolbar-item");
|
||||
tbi.hidden = !Social.uiVisible;
|
||||
if (!SocialUI.haveLoggedInUser()) {
|
||||
let parent = document.getElementById("social-notification-box");
|
||||
let parent = document.getElementById("social-notification-panel");
|
||||
while (parent.hasChildNodes())
|
||||
parent.removeChild(parent.firstChild);
|
||||
|
||||
@ -662,7 +680,6 @@ var SocialToolbar = {
|
||||
let icons = provider.ambientNotificationIcons;
|
||||
let iconNames = Object.keys(icons);
|
||||
let iconBox = document.getElementById("social-toolbar-item");
|
||||
let notifBox = document.getElementById("social-notification-box");
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.hidden = false;
|
||||
|
||||
@ -780,7 +797,7 @@ var SocialToolbar = {
|
||||
if (image.getAttribute("src") != icon.iconURL)
|
||||
image.setAttribute("src", icon.iconURL);
|
||||
}
|
||||
notifBox.appendChild(notificationFrames);
|
||||
panel.appendChild(notificationFrames);
|
||||
iconBox.appendChild(iconContainers);
|
||||
|
||||
for (let frame of createdFrames) {
|
||||
@ -797,13 +814,12 @@ var SocialToolbar = {
|
||||
|
||||
showAmbientPopup: function SocialToolbar_showAmbientPopup(aToolbarButtonBox) {
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
let notifBox = document.getElementById("social-notification-box");
|
||||
let notificationFrameId = aToolbarButtonBox.getAttribute("notificationFrameId");
|
||||
let notificationFrame = document.getElementById(notificationFrameId);
|
||||
|
||||
// Clear dimensions on all browsers so the panel size will
|
||||
// only use the selected browser.
|
||||
let frameIter = notifBox.firstElementChild;
|
||||
let frameIter = panel.firstElementChild;
|
||||
while (frameIter) {
|
||||
frameIter.collapsed = (frameIter != notificationFrame);
|
||||
frameIter = frameIter.nextElementSibling;
|
||||
|
@ -378,7 +378,6 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
}
|
||||
|
||||
#full-screen-warning-container {
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@ -393,10 +392,9 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
}
|
||||
|
||||
#full-screen-warning-message {
|
||||
pointer-events: auto;
|
||||
/* We must specify a max-width, otherwise word-wrap:break-word doesn't
|
||||
work in descendant <description> and <label> elements. Bug 630864. */
|
||||
max-width: 800px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
#full-screen-domain-text,
|
||||
|
@ -2549,7 +2549,7 @@ let BrowserOnClick = {
|
||||
switch (elmId) {
|
||||
case "exceptionDialogButton":
|
||||
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_CLICK_ADD_EXCEPTION);
|
||||
let params = { exceptionAdded : false, handlePrivateBrowsing : true };
|
||||
let params = { exceptionAdded : false };
|
||||
|
||||
try {
|
||||
switch (Services.prefs.getIntPref("browser.ssl_override_behavior")) {
|
||||
@ -3911,6 +3911,12 @@ var XULBrowserWindow = {
|
||||
|
||||
// Called before links are navigated to to allow us to retarget them if needed.
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
let target = this._onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
SocialUI.closeSocialPanelForLinkTraversal(target, linkNode);
|
||||
return target;
|
||||
},
|
||||
|
||||
_onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
// Don't modify non-default targets or targets that aren't in top-level app
|
||||
// tab docshells (isAppTab will be false for app tab subframes).
|
||||
if (originalTarget != "" || !isAppTab)
|
||||
|
@ -267,9 +267,7 @@
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
consumeoutsideclicks="true"
|
||||
noautofocus="true">
|
||||
<box id="social-notification-box" flex="1"></box>
|
||||
</panel>
|
||||
noautofocus="true"/>
|
||||
<panel id="social-flyout-panel"
|
||||
class="social-panel"
|
||||
onpopupshown="SocialFlyout.onShown()"
|
||||
|
@ -911,5 +911,66 @@ function test21e() {
|
||||
ok(objLoadingContent.activated, "Test 21e, Plugin with id=" + plugin.id + " should be activated");
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", true);
|
||||
prepareTest(test22, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests that a click-to-play plugin retains its activated state upon reloading
|
||||
function test22() {
|
||||
ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 22, Should have a click-to-play notification");
|
||||
|
||||
// Plugin should start as CTP
|
||||
var pluginNode = gTestBrowser.contentDocument.getElementById("test");
|
||||
ok(pluginNode, "Test 22, Found plugin in page");
|
||||
var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 22, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
|
||||
|
||||
// Activate
|
||||
objLoadingContent.playPlugin();
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, plugin should have started");
|
||||
ok(pluginNode.activated, "Test 22, plugin should be activated");
|
||||
|
||||
// Reload plugin
|
||||
var oldVal = pluginNode.getObjectValue();
|
||||
pluginNode.src = pluginNode.src;
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, Plugin should have retained activated state");
|
||||
ok(pluginNode.activated, "Test 22, plugin should have remained activated");
|
||||
// Sanity, ensure that we actually reloaded the instance, since this behavior might change in the future.
|
||||
var pluginsDiffer;
|
||||
try {
|
||||
pluginNode.checkObjectValue(oldVal);
|
||||
} catch (e) {
|
||||
pluginsDiffer = true;
|
||||
}
|
||||
ok(pluginsDiffer, "Test 22, plugin should have reloaded");
|
||||
|
||||
prepareTest(test23, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests that a click-to-play plugin resets its activated state when changing types
|
||||
function test23() {
|
||||
ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 23, Should have a click-to-play notification");
|
||||
|
||||
// Plugin should start as CTP
|
||||
var pluginNode = gTestBrowser.contentDocument.getElementById("test");
|
||||
ok(pluginNode, "Test 23, Found plugin in page");
|
||||
var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
|
||||
|
||||
// Activate
|
||||
objLoadingContent.playPlugin();
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 23, plugin should have started");
|
||||
ok(pluginNode.activated, "Test 23, plugin should be activated");
|
||||
|
||||
// Reload plugin (this may need RunSoon() in the future when plugins change state asynchronously)
|
||||
pluginNode.type = null;
|
||||
pluginNode.src = pluginNode.src; // We currently don't properly change state just on type change, bug 767631
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, plugin should be unloaded");
|
||||
pluginNode.type = "application/x-test";
|
||||
pluginNode.src = pluginNode.src;
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, Plugin should not have activated");
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, Plugin should be click-to-play");
|
||||
ok(!pluginNode.activated, "Test 23, plugin node should not be activated");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
@ -111,5 +111,40 @@ var tests = {
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
},
|
||||
|
||||
testCloseOnLinkTraversal: function(next) {
|
||||
|
||||
function onTabOpen(event) {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true);
|
||||
is(panel.state, "closed", "flyout should be closed");
|
||||
ok(true, "Link should open a new tab");
|
||||
executeSoon(function(){
|
||||
gBrowser.removeTab(event.target);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
let panel = document.getElementById("social-flyout-panel");
|
||||
let port = Social.provider.getWorkerPort();
|
||||
ok(port, "provider has a port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init-done":
|
||||
port.postMessage({topic: "test-flyout-open"});
|
||||
break;
|
||||
case "got-flyout-visibility":
|
||||
if (e.data.result == "shown") {
|
||||
// click on our test link
|
||||
is(panel.state, "open", "flyout should be open");
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true);
|
||||
let iframe = panel.firstChild;
|
||||
iframe.contentDocument.getElementById('traversal').click();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
}
|
||||
}
|
||||
|
@ -31,5 +31,7 @@
|
||||
</head>
|
||||
<body style="max-width: 250px;" onload="pingWorker();">
|
||||
<p>This is a test social flyout panel.</p>
|
||||
<a id="traversal" href="http://mochi.test">test link</a>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -25,9 +25,12 @@ _BROWSER_FILES = \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_6.js \
|
||||
browser_privacypane_7.js \
|
||||
browser_privacypane_8.js \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += browser_privacypane_7.js
|
||||
endif
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
@ -33,7 +33,7 @@ browser.jar:
|
||||
content/browser/preferences/permissions.js
|
||||
* content/browser/preferences/preferences.xul
|
||||
content/browser/preferences/privacy.xul
|
||||
content/browser/preferences/privacy.js
|
||||
* content/browser/preferences/privacy.js
|
||||
content/browser/preferences/sanitize.xul
|
||||
content/browser/preferences/security.xul
|
||||
content/browser/preferences/security.js
|
||||
|
@ -222,18 +222,22 @@ var gPrivacyPane = {
|
||||
|
||||
observe: function PPP_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Components.interfaces.nsIPrivateBrowsingService);
|
||||
|
||||
// Toggle the private browsing mode without switching the session
|
||||
let prefValue = document.getElementById("browser.privatebrowsing.autostart").value;
|
||||
let keepCurrentSession = document.getElementById("browser.privatebrowsing.keep_current_session");
|
||||
keepCurrentSession.value = true;
|
||||
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Components.interfaces.nsIPrivateBrowsingService);
|
||||
|
||||
// If activating from within the private browsing mode, reset the
|
||||
// private session
|
||||
if (prefValue && privateBrowsingService.privateBrowsingEnabled)
|
||||
privateBrowsingService.privateBrowsingEnabled = false;
|
||||
privateBrowsingService.privateBrowsingEnabled = prefValue;
|
||||
#endif
|
||||
|
||||
keepCurrentSession.reset();
|
||||
}
|
||||
},
|
||||
|
@ -23,11 +23,14 @@ _BROWSER_FILES = \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_6.js \
|
||||
browser_privacypane_7.js \
|
||||
browser_privacypane_8.js \
|
||||
browser_permissions.js \
|
||||
browser_chunk_permissions.js \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += browser_privacypane_7.js
|
||||
endif
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
@ -466,6 +466,7 @@ PrivateBrowsingService.prototype = {
|
||||
if (this._autoStarted)
|
||||
aSubject.handleFlag("private", false);
|
||||
|
||||
Services.prefs.setBoolPref("browser.privatebrowsing.autostart", true);
|
||||
this.privateBrowsingEnabled = true;
|
||||
this._autoStarted = true;
|
||||
this._lastChangedByCommandLine = true;
|
||||
|
@ -19,14 +19,13 @@ function test() {
|
||||
// enter private browsing mode
|
||||
pb.privateBrowsingEnabled = true;
|
||||
|
||||
step1();
|
||||
doTest();
|
||||
|
||||
// Test the certificate exceptions dialog as it is invoked from about:certerror
|
||||
function step1() {
|
||||
// Test the certificate exceptions dialog
|
||||
function doTest() {
|
||||
let params = {
|
||||
exceptionAdded : false,
|
||||
location: INVALID_CERT_LOCATION,
|
||||
handlePrivateBrowsing : true,
|
||||
prefetchCert: true,
|
||||
};
|
||||
function testCheckbox() {
|
||||
@ -41,32 +40,6 @@ function test() {
|
||||
ok(!checkbox.hasAttribute("checked"),
|
||||
"the permanent checkbox should not be checked when handling the private browsing mode");
|
||||
win.close();
|
||||
step2();
|
||||
}, "cert-exception-ui-ready", false);
|
||||
}
|
||||
var win = openDialog(EXCEPTIONS_DLG_URL, "", EXCEPTIONS_DLG_FEATURES, params);
|
||||
win.addEventListener("load", testCheckbox, false);
|
||||
}
|
||||
|
||||
// Test the certificate excetions dialog as it is invoked from the Preferences dialog
|
||||
function step2() {
|
||||
let params = {
|
||||
exceptionAdded : false,
|
||||
location: INVALID_CERT_LOCATION,
|
||||
prefetchCert: true,
|
||||
};
|
||||
function testCheckbox() {
|
||||
win.removeEventListener("load", testCheckbox, false);
|
||||
Services.obs.addObserver(function (aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false);
|
||||
ok(win.gCert, "The certificate information should be available now");
|
||||
|
||||
let checkbox = win.document.getElementById("permanent");
|
||||
ok(!checkbox.hasAttribute("disabled"),
|
||||
"the permanent checkbox should not be disabled when not handling the private browsing mode");
|
||||
ok(checkbox.hasAttribute("checked"),
|
||||
"the permanent checkbox should be checked when not handling the private browsing mode");
|
||||
win.close();
|
||||
cleanup();
|
||||
}, "cert-exception-ui-ready", false);
|
||||
}
|
||||
|
@ -4111,7 +4111,6 @@ html|*#gcli-output-frame {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#social-notification-box,
|
||||
.social-panel-frame {
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
@ -153,7 +153,6 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-button,
|
||||
#downloads-indicator {
|
||||
width: 35px;
|
||||
}
|
||||
|
@ -3395,7 +3395,6 @@ html|*#gcli-output-frame {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#social-notification-box,
|
||||
.social-panel-frame {
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.18
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.7.14
|
||||
SQLITE_VERSION=3.7.14.1
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
||||
|
@ -49,6 +49,8 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
const unsigned long PLUGIN_SUPPRESSED = 6;
|
||||
// Blocked by content policy
|
||||
const unsigned long PLUGIN_USER_DISABLED = 7;
|
||||
/// ** All values >= PLUGIN_CLICK_TO_PLAY are plugin placeholder types that
|
||||
/// would be replaced by a real plugin if activated (playPlugin())
|
||||
// The plugin is disabled until the user clicks on it
|
||||
const unsigned long PLUGIN_CLICK_TO_PLAY = 8;
|
||||
// The plugin is vulnerable (update available)
|
||||
@ -110,13 +112,14 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
|
||||
/**
|
||||
* This method will play a plugin that has been stopped by the
|
||||
* click-to-play plugins feature.
|
||||
* click-to-play plugins or play-preview features.
|
||||
*/
|
||||
void playPlugin();
|
||||
|
||||
/**
|
||||
* This attribute will return true if the plugin has been activated and
|
||||
* false if the plugin is still in the click-to-play or play preview state.
|
||||
* This attribute will return true if the current content type has been
|
||||
* activated, either explicitly or by passing checks that would have it be
|
||||
* click-to-play or play-preview.
|
||||
*/
|
||||
readonly attribute boolean activated;
|
||||
|
||||
|
@ -187,6 +187,7 @@ LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/dom/ipc \
|
||||
-I$(topsrcdir)/image/src \
|
||||
-I$(topsrcdir)/js/xpconnect/src \
|
||||
-I$(topsrcdir)/layout/base \
|
||||
-I$(topsrcdir)/layout/generic \
|
||||
-I$(topsrcdir)/layout/style \
|
||||
-I$(topsrcdir)/layout/svg \
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "nsIRefreshURI.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsStyleSheetService.h"
|
||||
|
||||
#include "nsNetUtil.h" // for NS_MakeAbsoluteURI
|
||||
|
||||
@ -2318,6 +2319,14 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
AppendAuthorSheet(nsIStyleSheet *aSheet, void *aData)
|
||||
{
|
||||
nsStyleSet *styleSet = static_cast<nsStyleSet*>(aData);
|
||||
styleSet->AppendStyleSheet(nsStyleSet::eDocSheet, aSheet);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::FillStyleSet(nsStyleSet* aStyleSet)
|
||||
{
|
||||
@ -2344,6 +2353,12 @@ nsDocument::FillStyleSet(nsStyleSet* aStyleSet)
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||
if (sheetService) {
|
||||
sheetService->AuthorStyleSheets()->EnumerateForwards(AppendAuthorSheet,
|
||||
aStyleSet);
|
||||
}
|
||||
|
||||
for (i = mCatalogSheets.Count() - 1; i >= 0; --i) {
|
||||
nsIStyleSheet* sheet = mCatalogSheets[i];
|
||||
if (sheet->IsApplicable()) {
|
||||
@ -3583,14 +3598,6 @@ nsDocument::GetStyleSheetAt(int32_t aIndex) const
|
||||
int32_t
|
||||
nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const
|
||||
{
|
||||
if (mAdditionalSheets[eUserSheet].IndexOf(aSheet) >= 0 ||
|
||||
mAdditionalSheets[eAgentSheet].IndexOf(aSheet) >= 0 ) {
|
||||
// Returning INT32_MAX to make sure that additional sheets are
|
||||
// in the style set of the PresShell will be always after the
|
||||
// document sheets (even if document sheets are added dynamically).
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
return mStyleSheets.IndexOf(aSheet);
|
||||
}
|
||||
|
||||
|
@ -1470,9 +1470,15 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
mURI = newURI;
|
||||
}
|
||||
|
||||
if (mContentType != newMime) {
|
||||
// We don't update content type when loading, as the type is not final and we
|
||||
// don't want to superfluously change between mOriginalContentType ->
|
||||
// mContentType when doing |obj.data = obj.data| with a channel and differing
|
||||
// type.
|
||||
if (mType != eType_Loading && mContentType != newMime) {
|
||||
retval = (ParameterUpdateFlags)(retval | eParamStateChanged);
|
||||
LOG(("OBJLC [%p]: Object effective mime type changed (%s -> %s)", this, mContentType.get(), newMime.get()));
|
||||
retval = (ParameterUpdateFlags)(retval | eParamContentTypeChanged);
|
||||
LOG(("OBJLC [%p]: Object effective mime type changed (%s -> %s)",
|
||||
this, mContentType.get(), newMime.get()));
|
||||
mContentType = newMime;
|
||||
}
|
||||
|
||||
@ -1553,6 +1559,12 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
}
|
||||
}
|
||||
|
||||
// Explicit user activation should reset if the object changes content types
|
||||
if (mActivated && (stateChange & eParamContentTypeChanged)) {
|
||||
LOG(("OBJLC [%p]: Content type changed, clearing activation state", this));
|
||||
mActivated = false;
|
||||
}
|
||||
|
||||
// We synchronously start/stop plugin instances below, which may spin the
|
||||
// event loop. Re-entering into the load is fine, but at that point the
|
||||
// original load call needs to abort when unwinding
|
||||
@ -1661,6 +1673,13 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
fallbackType = clickToPlayReason;
|
||||
}
|
||||
|
||||
if (!mActivated && mType != eType_Null) {
|
||||
// Object passed ShouldPlay and !ShouldPreview, so it should be considered
|
||||
// activated until it changes content type
|
||||
LOG(("OBJLC [%p]: Object implicitly activated", this));
|
||||
mActivated = true;
|
||||
}
|
||||
|
||||
// Sanity check: We shouldn't have any loaded resources, pending events, or
|
||||
// a final listener at this point
|
||||
if (mFrameLoader || mPendingInstantiateEvent || mInstanceOwner ||
|
||||
@ -2464,15 +2483,25 @@ nsObjectLoadingContent::PlayPlugin()
|
||||
if (!nsContentUtils::IsCallerChrome())
|
||||
return NS_OK;
|
||||
|
||||
mActivated = true;
|
||||
return LoadObject(true, true);
|
||||
if (!mActivated) {
|
||||
mActivated = true;
|
||||
LOG(("OBJLC [%p]: Activated by user", this));
|
||||
}
|
||||
|
||||
// If we're in a click-to-play or play preview state, we need to reload
|
||||
// Fallback types >= eFallbackClickToPlay are plugin-replacement types, see
|
||||
// header
|
||||
if (mType == eType_Null && mFallbackType >= eFallbackClickToPlay) {
|
||||
return LoadObject(true, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::GetActivated(bool *aActivated)
|
||||
{
|
||||
FallbackType reason;
|
||||
*aActivated = ShouldPlay(reason) && !ShouldPreview();
|
||||
*aActivated = mActivated;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2490,11 +2519,14 @@ nsObjectLoadingContent::CancelPlayPreview()
|
||||
if (!nsContentUtils::IsCallerChrome())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (mPlayPreviewCanceled || mActivated)
|
||||
return NS_OK;
|
||||
|
||||
mPlayPreviewCanceled = true;
|
||||
return LoadObject(true, true);
|
||||
|
||||
// If we're in play preview state already, reload
|
||||
if (mType == eType_Null && mFallbackType == eFallbackPlayPreview) {
|
||||
return LoadObject(true, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -77,6 +77,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
eFallbackSuppressed = nsIObjectLoadingContent::PLUGIN_SUPPRESSED,
|
||||
// Blocked by content policy
|
||||
eFallbackUserDisabled = nsIObjectLoadingContent::PLUGIN_USER_DISABLED,
|
||||
/// ** All values >= eFallbackClickToPlay are plugin placeholder types
|
||||
/// that would be replaced by a real plugin if activated (PlayPlugin())
|
||||
// The plugin is disabled until the user clicks on it
|
||||
eFallbackClickToPlay = nsIObjectLoadingContent::PLUGIN_CLICK_TO_PLAY,
|
||||
// The plugin is vulnerable (update available)
|
||||
@ -222,7 +224,14 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
eParamChannelChanged = PR_BIT(0),
|
||||
// Parameters that affect displayed content changed
|
||||
// - mURI, mContentType, mType, mBaseURI
|
||||
eParamStateChanged = PR_BIT(1)
|
||||
eParamStateChanged = PR_BIT(1),
|
||||
// The effective content type changed, independant of object type. This
|
||||
// can happen when changing from Loading -> Final type, but doesn't
|
||||
// necessarily happen when changing between object types. E.g., if a PDF
|
||||
// handler was installed between the last load of this object and now, we
|
||||
// might change from eType_Document -> eType_Plugin without changing
|
||||
// ContentType
|
||||
eParamContentTypeChanged = PR_BIT(2)
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -81,8 +81,7 @@ public:
|
||||
NS_IMETHOD GetThebesSurface(gfxASurface **surface) = 0;
|
||||
|
||||
// This gets an Azure SourceSurface for the canvas, this will be a snapshot
|
||||
// of the canvas at the time it was called. This will return null for a
|
||||
// non-azure canvas.
|
||||
// of the canvas at the time it was called.
|
||||
virtual mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot() = 0;
|
||||
|
||||
// If this context is opaque, the backing store of the canvas should
|
||||
|
@ -40,17 +40,6 @@ function IsMacOSX10_5orOlder() {
|
||||
}
|
||||
|
||||
|
||||
function IsAzureEnabled() {
|
||||
var enabled = false;
|
||||
|
||||
try {
|
||||
var backend = Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
enabled = (backend != "none");
|
||||
} catch (e) { }
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
function IsAzureSkia() {
|
||||
var enabled = false;
|
||||
|
||||
@ -3538,11 +3527,7 @@ var _thrown = undefined; try {
|
||||
ctx.drawImage(null, 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -3719,38 +3704,22 @@ var ctx = canvas.getContext('2d');
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage(undefined, 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage(0, 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage("", 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage(document.createElement('p'), 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -6151,16 +6120,9 @@ ctx.fillRect(0, 0, 100, 50);
|
||||
ctx.translate(-50, 0);
|
||||
ctx.fillRect(50, 0, 100, 50);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 25,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 25,25, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
isPixel(ctx, 25,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 75,25, 0,255,0,255, 0);
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -7348,15 +7310,9 @@ ctx.translate(50, 25);
|
||||
ctx.scale(10, 10);
|
||||
ctx.fillRect(-5, -2.5, 10, 5);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 25,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 75,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 25,25, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 75,25, 0,255,0,255, 0);
|
||||
}
|
||||
isPixel(ctx, 25,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 75,25, 0,255,0,255, 0);
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -7717,11 +7673,7 @@ var ctx = canvas.getContext('2d');
|
||||
var _thrown = undefined; try {
|
||||
ctx.createImageData(null);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
|
||||
}
|
||||
@ -9233,11 +9185,7 @@ var ctx = canvas.getContext('2d');
|
||||
var _thrown = undefined; try {
|
||||
ctx.putImageData(null, 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -9349,32 +9297,17 @@ var imgdata = { width: 1, height: 1, data: [255, 0, 0, 255] };
|
||||
var _thrown = undefined; try {
|
||||
ctx.putImageData(imgdata, 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
var _thrown = undefined; try {
|
||||
ctx.putImageData("cheese", 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
|
||||
var _thrown = undefined; try {
|
||||
ctx.putImageData(42, 0, 0);
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
|
||||
|
||||
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -11681,13 +11614,7 @@ ctx.moveTo(0, 25);
|
||||
ctx.arc(200, 25, 0, 0, Math.PI, true);
|
||||
ctx.stroke();
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -14425,7 +14352,7 @@ ctx.lineTo(50, 25);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
|
||||
if (IsAzureEnabled() && IsAzureSkia()) {
|
||||
if (IsAzureSkia()) {
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
@ -14501,7 +14428,7 @@ ctx.moveTo(50, 25);
|
||||
ctx.bezierCurveTo(50, 25, 50, 25, 50, 25);
|
||||
ctx.stroke();
|
||||
|
||||
if (IsAzureEnabled() && IsAzureSkia()) {
|
||||
if (IsAzureSkia()) {
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
@ -14538,7 +14465,7 @@ ctx.moveTo(50, 25);
|
||||
ctx.lineTo(50, 25);
|
||||
ctx.stroke();
|
||||
|
||||
if (IsAzureEnabled() && IsAzureSkia()) {
|
||||
if (IsAzureSkia()) {
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
@ -14575,7 +14502,7 @@ ctx.stroke();
|
||||
|
||||
ctx.strokeRect(50, 25, 0, 0);
|
||||
|
||||
if (IsAzureEnabled() && IsAzureSkia()) {
|
||||
if (IsAzureSkia()) {
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
@ -15173,13 +15100,7 @@ var ctx = canvas.getContext('2d');
|
||||
var _thrown = undefined; try {
|
||||
ctx.createPattern(null, 'repeat');
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
|
||||
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -15197,13 +15118,7 @@ var ctx = canvas.getContext('2d');
|
||||
var _thrown = undefined; try {
|
||||
ctx.createPattern('image_red.png', 'repeat');
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
|
||||
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -15221,13 +15136,7 @@ var ctx = canvas.getContext('2d');
|
||||
var _thrown = undefined; try {
|
||||
ctx.createPattern(undefined, 'repeat');
|
||||
} catch (e) { _thrown = e };
|
||||
if (IsAzureEnabled()) {
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
} else {
|
||||
todo(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
|
||||
|
||||
ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -15727,18 +15636,10 @@ ctx.fillRect(0, 0, 100, 50);
|
||||
ctx.translate(-128, -78);
|
||||
ctx.fillRect(128, 78, 100, 50);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
</script>
|
||||
<img src="image_rgrg-256x256.png" id="rgrg-256x256_4.png" class="resource">
|
||||
@ -15831,22 +15732,12 @@ ctx.fillRect(0, -16, 100, 50);
|
||||
ctx.fillStyle = '#0f0';
|
||||
ctx.fillRect(0, 0, 100, 16);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,25, 0,255,0,255, 0);
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
<img src="image_red-16x16.png" id="red-16x16_1.png" class="resource">
|
||||
@ -15877,16 +15768,8 @@ ctx.fillRect(0, 0, 100, 16);
|
||||
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
</script>
|
||||
<img src="image_red-16x16.png" id="red-16x16_2.png" class="resource">
|
||||
@ -15951,19 +15834,10 @@ ctx.fillRect(0, 0, 16, 50);
|
||||
isPixel(ctx, 50,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 50,48, 0,255,0,255, 0);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
</script>
|
||||
<img src="image_red-16x16.png" id="red-16x16_3.png" class="resource">
|
||||
@ -15994,15 +15868,8 @@ ctx.fillRect(0, 0, 16, 50);
|
||||
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
|
||||
if (IsAzureEnabled()) {
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
} else {
|
||||
todo_isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
}
|
||||
</script>
|
||||
<img src="image_red-16x16.png" id="red-16x16_4.png" class="resource">
|
||||
@ -19648,11 +19515,7 @@ ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.p
|
||||
window.CanvasRenderingContext2D.prototype.fill = 1;
|
||||
ok(window.CanvasRenderingContext2D.prototype.fill === 1, "window.CanvasRenderingContext2D.prototype.fill === 1");
|
||||
delete window.CanvasRenderingContext2D.prototype.fill;
|
||||
if (IsAzureEnabled()) {
|
||||
ok(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
|
||||
} else {
|
||||
todo(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
|
||||
}
|
||||
ok(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
|
||||
|
||||
//restore the original method to ensure that other tests can run successfully
|
||||
window.CanvasRenderingContext2D.prototype.fill = fill;
|
||||
|
@ -73,11 +73,26 @@ public:
|
||||
*/
|
||||
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile) = 0;
|
||||
|
||||
/* Called when the stream wants more data */
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) = 0;
|
||||
|
||||
/* Stop the device and release the corresponding MediaStream */
|
||||
virtual nsresult Stop() = 0;
|
||||
|
||||
/* Return false if device is currently allocated or started */
|
||||
bool IsAvailable() {
|
||||
if (mState == kAllocated || mState == kStarted) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* It is an error to call Start() before an Allocate(), and Stop() before
|
||||
* a Start(). Only Allocate() may be called after a Deallocate(). */
|
||||
|
||||
protected:
|
||||
MediaEngineState mState;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,10 @@ const MediaEngineVideoOptions MediaEngineDefaultVideoSource::mOpts = {
|
||||
};
|
||||
|
||||
MediaEngineDefaultVideoSource::MediaEngineDefaultVideoSource()
|
||||
: mTimer(nullptr), mState(kReleased)
|
||||
{}
|
||||
: mTimer(nullptr)
|
||||
{
|
||||
mState = kReleased;
|
||||
}
|
||||
|
||||
MediaEngineDefaultVideoSource::~MediaEngineDefaultVideoSource()
|
||||
{}
|
||||
@ -201,10 +203,35 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineDefaultAudioSource, nsITimerCallback)
|
||||
void
|
||||
MediaEngineDefaultVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
StreamTime aDesiredTime)
|
||||
{
|
||||
// Ignore - we push video data
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default audio source.
|
||||
*/
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineDefaultAudioSource, nsITimerCallback)
|
||||
|
||||
MediaEngineDefaultAudioSource::MediaEngineDefaultAudioSource()
|
||||
: mTimer(nullptr)
|
||||
{
|
||||
mState = kReleased;
|
||||
}
|
||||
|
||||
MediaEngineDefaultAudioSource::~MediaEngineDefaultAudioSource()
|
||||
{}
|
||||
|
||||
void
|
||||
MediaEngineDefaultAudioSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
StreamTime aDesiredTime)
|
||||
{
|
||||
// Ignore - we push audio data
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineDefaultAudioSource::GetName(nsAString& aName)
|
||||
{
|
||||
@ -312,13 +339,43 @@ MediaEngineDefaultAudioSource::Notify(nsITimer* aTimer)
|
||||
|
||||
void
|
||||
MediaEngineDefault::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >* aVSources) {
|
||||
aVSources->AppendElement(mVSource);
|
||||
int32_t found = false;
|
||||
int32_t len = mVSources.Length();
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
nsRefPtr<MediaEngineVideoSource> source = mVSources.ElementAt(i);
|
||||
aVSources->AppendElement(source);
|
||||
if (source->IsAvailable()) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// All streams are currently busy, just make a new one.
|
||||
if (!found) {
|
||||
nsRefPtr<MediaEngineVideoSource> newSource =
|
||||
new MediaEngineDefaultVideoSource();
|
||||
mVSources.AppendElement(newSource);
|
||||
aVSources->AppendElement(newSource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineDefault::EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >* aASources) {
|
||||
aASources->AppendElement(mASource);
|
||||
int32_t len = mVSources.Length();
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
nsRefPtr<MediaEngineAudioSource> source = mASources.ElementAt(i);
|
||||
if (source->IsAvailable()) {
|
||||
aASources->AppendElement(source);
|
||||
}
|
||||
}
|
||||
|
||||
// All streams are currently busy, just make a new one.
|
||||
if (aASources->Length() == 0) {
|
||||
nsRefPtr<MediaEngineAudioSource> newSource =
|
||||
new MediaEngineDefaultAudioSource();
|
||||
mASources.AppendElement(newSource);
|
||||
aASources->AppendElement(newSource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -41,11 +41,11 @@ public:
|
||||
|
||||
virtual const MediaEngineVideoOptions *GetOptions();
|
||||
virtual nsresult Allocate();
|
||||
|
||||
virtual nsresult Deallocate();
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop();
|
||||
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
@ -60,7 +60,6 @@ protected:
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsRefPtr<layers::ImageContainer> mImageContainer;
|
||||
|
||||
MediaEngineState mState;
|
||||
SourceMediaStream* mSource;
|
||||
layers::PlanarYCbCrImage* mImage;
|
||||
static const MediaEngineVideoOptions mOpts;
|
||||
@ -70,18 +69,18 @@ class MediaEngineDefaultAudioSource : public nsITimerCallback,
|
||||
public MediaEngineAudioSource
|
||||
{
|
||||
public:
|
||||
MediaEngineDefaultAudioSource() : mTimer(nullptr), mState(kReleased) {}
|
||||
~MediaEngineDefaultAudioSource(){};
|
||||
MediaEngineDefaultAudioSource();
|
||||
~MediaEngineDefaultAudioSource();
|
||||
|
||||
virtual void GetName(nsAString&);
|
||||
virtual void GetUUID(nsAString&);
|
||||
|
||||
virtual nsresult Allocate();
|
||||
|
||||
virtual nsresult Deallocate();
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop();
|
||||
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
@ -90,25 +89,21 @@ protected:
|
||||
TrackID mTrackID;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
MediaEngineState mState;
|
||||
SourceMediaStream* mSource;
|
||||
};
|
||||
|
||||
class MediaEngineDefault : public MediaEngine
|
||||
{
|
||||
public:
|
||||
MediaEngineDefault() {
|
||||
mVSource = new MediaEngineDefaultVideoSource();
|
||||
mASource = new MediaEngineDefaultAudioSource();
|
||||
}
|
||||
MediaEngineDefault() {}
|
||||
~MediaEngineDefault() {}
|
||||
|
||||
virtual void EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >*);
|
||||
virtual void EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >*);
|
||||
|
||||
private:
|
||||
nsRefPtr<MediaEngineVideoSource> mVSource;
|
||||
nsRefPtr<MediaEngineAudioSource> mASource;
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> > mVSources;
|
||||
nsTArray<nsRefPtr<MediaEngineAudioSource> > mASources;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -53,13 +53,20 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* We still enumerate every time, in case a new device was plugged in since
|
||||
* the last call. TODO: Verify that WebRTC actually does deal with hotplugging
|
||||
* new devices (with or without new engine creation) and accordingly adjust.
|
||||
* Enumeration is not neccessary if GIPS reports the same set of devices
|
||||
* for a given instance of the engine. Likewise, if a device was plugged out,
|
||||
* mVideoSources must be updated.
|
||||
*/
|
||||
int num = ptrViECapture->NumberOfCaptureDevices();
|
||||
if (num <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
#ifdef DEBUG
|
||||
const unsigned int kMaxDeviceNameLength = 128; // XXX FIX!
|
||||
const unsigned int kMaxUniqueIdLength = 256;
|
||||
char deviceName[kMaxDeviceNameLength];
|
||||
@ -71,8 +78,10 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
||||
int error = ptrViECapture->GetCaptureDevice(i, deviceName,
|
||||
sizeof(deviceName), uniqueId,
|
||||
sizeof(uniqueId));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (error) {
|
||||
LOG((" VieCapture:GetCaptureDevice: Failed %d",
|
||||
LOG((" VieCapture:GetCaptureDevice: Failed %d",
|
||||
ptrViEBase->LastError() ));
|
||||
continue;
|
||||
}
|
||||
@ -82,7 +91,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
||||
int numCaps = ptrViECapture->NumberOfCapabilities(uniqueId, kMaxUniqueIdLength);
|
||||
LOG(("Number of Capabilities %d", numCaps));
|
||||
for (int j = 0; j < numCaps; j++) {
|
||||
if (ptrViECapture->GetCaptureCapability(uniqueId, kMaxUniqueIdLength,
|
||||
if (ptrViECapture->GetCaptureCapability(uniqueId, kMaxUniqueIdLength,
|
||||
j, cap ) != 0 ) {
|
||||
break;
|
||||
}
|
||||
@ -91,8 +100,16 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
||||
}
|
||||
#endif
|
||||
|
||||
nsRefPtr<MediaEngineVideoSource> vSource = new MediaEngineWebRTCVideoSource(mVideoEngine, i);
|
||||
aVSources->AppendElement(vSource.forget());
|
||||
nsRefPtr<MediaEngineWebRTCVideoSource> vSource;
|
||||
NS_ConvertUTF8toUTF16 uuid(uniqueId);
|
||||
if (mVideoSources.Get(uuid, getter_AddRefs(vSource))) {
|
||||
// We've already seen this device, just append.
|
||||
aVSources->AppendElement(vSource.get());
|
||||
} else {
|
||||
vSource = new MediaEngineWebRTCVideoSource(mVideoEngine, i);
|
||||
mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
|
||||
aVSources->AppendElement(vSource);
|
||||
}
|
||||
}
|
||||
|
||||
ptrViEBase->Release();
|
||||
@ -136,31 +153,41 @@ MediaEngineWebRTC::EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSourc
|
||||
for (int i = 0; i < nDevices; i++) {
|
||||
// We use constants here because GetRecordingDeviceName takes char[128].
|
||||
char deviceName[128];
|
||||
char uniqueID[128];
|
||||
char uniqueId[128];
|
||||
// paranoia; jingle doesn't bother with this
|
||||
deviceName[0] = '\0';
|
||||
uniqueID[0] = '\0';
|
||||
uniqueId[0] = '\0';
|
||||
|
||||
ptrVoEHw->GetRecordingDeviceName(i, deviceName, uniqueID);
|
||||
nsRefPtr<MediaEngineAudioSource> aSource = new MediaEngineWebRTCAudioSource(
|
||||
mVoiceEngine, i, deviceName, uniqueID
|
||||
);
|
||||
aASources->AppendElement(aSource.forget());
|
||||
ptrVoEHw->GetRecordingDeviceName(i, deviceName, uniqueId);
|
||||
|
||||
nsRefPtr<MediaEngineWebRTCAudioSource> aSource;
|
||||
NS_ConvertUTF8toUTF16 uuid(uniqueId);
|
||||
if (mAudioSources.Get(uuid, getter_AddRefs(aSource))) {
|
||||
// We've already seen this device, just append.
|
||||
aASources->AppendElement(aSource.get());
|
||||
} else {
|
||||
aSource = new MediaEngineWebRTCAudioSource(
|
||||
mVoiceEngine, i, deviceName, uniqueId
|
||||
);
|
||||
mAudioSources.Put(uuid, aSource); // Hashtable takes ownership.
|
||||
aASources->AppendElement(aSource);
|
||||
}
|
||||
}
|
||||
|
||||
ptrVoEHw->Release();
|
||||
ptrVoEBase->Release();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MediaEngineWebRTC::Shutdown()
|
||||
{
|
||||
if (mVideoEngine) {
|
||||
mVideoSources.Clear();
|
||||
webrtc::VideoEngine::Delete(mVideoEngine);
|
||||
}
|
||||
|
||||
if (mVoiceEngine) {
|
||||
mAudioSources.Clear();
|
||||
webrtc::VoiceEngine::Delete(mVoiceEngine);
|
||||
}
|
||||
|
||||
|
@ -53,16 +53,31 @@ class MediaEngineWebRTCVideoSource : public MediaEngineVideoSource,
|
||||
public nsRunnable
|
||||
{
|
||||
public:
|
||||
static const int DEFAULT_VIDEO_FPS = 30;
|
||||
static const int DEFAULT_VIDEO_FPS = 60;
|
||||
static const int DEFAULT_MIN_VIDEO_FPS = 10;
|
||||
|
||||
// ViEExternalRenderer.
|
||||
virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int);
|
||||
virtual int DeliverFrame(unsigned char*, int, uint32_t, int64_t);
|
||||
|
||||
MediaEngineWebRTCVideoSource(webrtc::VideoEngine* videoEnginePtr,
|
||||
int index, int aMinFps = DEFAULT_MIN_VIDEO_FPS);
|
||||
~MediaEngineWebRTCVideoSource();
|
||||
MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr,
|
||||
int aIndex, int aMinFps = DEFAULT_MIN_VIDEO_FPS)
|
||||
: mVideoEngine(aVideoEnginePtr)
|
||||
, mCaptureIndex(aIndex)
|
||||
, mCapabilityChosen(false)
|
||||
, mWidth(640)
|
||||
, mHeight(480)
|
||||
, mLastEndTime(0)
|
||||
, mMonitor("WebRTCCamera.Monitor")
|
||||
, mFps(DEFAULT_VIDEO_FPS)
|
||||
, mMinFps(aMinFps)
|
||||
, mInitDone(false)
|
||||
, mInSnapshotMode(false)
|
||||
, mSnapshotPath(NULL) {
|
||||
mState = kReleased;
|
||||
Init();
|
||||
}
|
||||
~MediaEngineWebRTCVideoSource() { Shutdown(); }
|
||||
|
||||
virtual void GetName(nsAString&);
|
||||
virtual void GetUUID(nsAString&);
|
||||
@ -72,6 +87,7 @@ public:
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop();
|
||||
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
@ -114,8 +130,8 @@ private:
|
||||
bool mCapabilityChosen;
|
||||
int mWidth, mHeight;
|
||||
TrackID mTrackID;
|
||||
TrackTicks mLastEndTime;
|
||||
|
||||
MediaEngineState mState;
|
||||
mozilla::ReentrantMonitor mMonitor; // Monitor for processing WebRTC frames.
|
||||
SourceMediaStream* mSource;
|
||||
|
||||
@ -125,6 +141,7 @@ private:
|
||||
bool mInSnapshotMode;
|
||||
nsString* mSnapshotPath;
|
||||
|
||||
nsRefPtr<layers::Image> mImage;
|
||||
nsRefPtr<layers::ImageContainer> mImageContainer;
|
||||
|
||||
PRLock* mSnapshotLock;
|
||||
@ -148,15 +165,12 @@ public:
|
||||
, mMonitor("WebRTCMic.Monitor")
|
||||
, mCapIndex(aIndex)
|
||||
, mChannel(-1)
|
||||
, mInitDone(false)
|
||||
, mState(kReleased) {
|
||||
|
||||
mVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
|
||||
, mInitDone(false) {
|
||||
mState = kReleased;
|
||||
mDeviceName.Assign(NS_ConvertUTF8toUTF16(name));
|
||||
mDeviceUUID.Assign(NS_ConvertUTF8toUTF16(uuid));
|
||||
mInitDone = true;
|
||||
Init();
|
||||
}
|
||||
|
||||
~MediaEngineWebRTCAudioSource() { Shutdown(); }
|
||||
|
||||
virtual void GetName(nsAString&);
|
||||
@ -167,6 +181,7 @@ public:
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop();
|
||||
virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
|
||||
|
||||
// VoEMediaProcess.
|
||||
void Process(const int channel, const webrtc::ProcessingTypes type,
|
||||
@ -192,7 +207,6 @@ private:
|
||||
int mChannel;
|
||||
TrackID mTrackID;
|
||||
bool mInitDone;
|
||||
MediaEngineState mState;
|
||||
|
||||
nsString mDeviceName;
|
||||
nsString mDeviceUUID;
|
||||
@ -207,8 +221,10 @@ public:
|
||||
: mVideoEngine(NULL)
|
||||
, mVoiceEngine(NULL)
|
||||
, mVideoEngineInit(false)
|
||||
, mAudioEngineInit(false) {}
|
||||
|
||||
, mAudioEngineInit(false) {
|
||||
mVideoSources.Init();
|
||||
mAudioSources.Init();
|
||||
}
|
||||
~MediaEngineWebRTC() { Shutdown(); }
|
||||
|
||||
// Clients should ensure to clean-up sources video/audio sources
|
||||
@ -225,6 +241,11 @@ private:
|
||||
// Need this to avoid unneccesary WebRTC calls while enumerating.
|
||||
bool mVideoEngineInit;
|
||||
bool mAudioEngineInit;
|
||||
|
||||
// Store devices we've already seen in a hashtable for quick return.
|
||||
// Maps UUID to MediaEngineSource (one set for audio, one for video).
|
||||
nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCVideoSource > mVideoSources;
|
||||
nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCAudioSource > mAudioSources;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -53,49 +53,6 @@ MediaEngineWebRTCAudioSource::Allocate()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mVoEBase->Init();
|
||||
|
||||
mVoERender = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
|
||||
if (!mVoERender) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mChannel = mVoEBase->CreateChannel();
|
||||
if (mChannel < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Check for availability.
|
||||
webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
|
||||
if (ptrVoEHw->SetRecordingDevice(mCapIndex)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool avail = false;
|
||||
ptrVoEHw->GetRecordingDeviceStatus(avail);
|
||||
if (!avail) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Set "codec" to PCM, 32kHz on 1 channel
|
||||
webrtc::VoECodec* ptrVoECodec;
|
||||
webrtc::CodecInst codec;
|
||||
ptrVoECodec = webrtc::VoECodec::GetInterface(mVoiceEngine);
|
||||
if (!ptrVoECodec) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
strcpy(codec.plname, ENCODING);
|
||||
codec.channels = CHANNELS;
|
||||
codec.rate = SAMPLE_RATE;
|
||||
codec.plfreq = SAMPLE_FREQUENCY;
|
||||
codec.pacsize = SAMPLE_LENGTH;
|
||||
codec.pltype = 0; // Default payload type
|
||||
|
||||
if (ptrVoECodec->SetSendCodec(mChannel, codec)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Audio doesn't play through unless we set a receiver and destination, so
|
||||
// we setup a dummy local destination, and do a loopback.
|
||||
mVoEBase->SetLocalReceiver(mChannel, DEFAULT_PORT);
|
||||
@ -112,9 +69,6 @@ MediaEngineWebRTCAudioSource::Deallocate()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mVoEBase->Terminate();
|
||||
mVoERender->Release();
|
||||
|
||||
mState = kReleased;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -135,6 +89,7 @@ MediaEngineWebRTCAudioSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
segment->Init(CHANNELS);
|
||||
mSource->AddTrack(aID, SAMPLE_FREQUENCY, 0, segment);
|
||||
mSource->AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
LOG(("Initial audio"));
|
||||
mTrackID = aID;
|
||||
|
||||
if (mVoEBase->StartReceive(mChannel)) {
|
||||
@ -174,12 +129,69 @@ MediaEngineWebRTCAudioSource::Stop()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCAudioSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
StreamTime aDesiredTime)
|
||||
{
|
||||
// Ignore - we push audio data
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineWebRTCAudioSource::Snapshot(uint32_t aDuration, nsIDOMFile** aFile)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCAudioSource::Init()
|
||||
{
|
||||
mVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
|
||||
|
||||
mVoEBase->Init();
|
||||
|
||||
mVoERender = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
|
||||
if (!mVoERender) {
|
||||
return;
|
||||
}
|
||||
|
||||
mChannel = mVoEBase->CreateChannel();
|
||||
if (mChannel < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for availability.
|
||||
webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
|
||||
if (ptrVoEHw->SetRecordingDevice(mCapIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool avail = false;
|
||||
ptrVoEHw->GetRecordingDeviceStatus(avail);
|
||||
if (!avail) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set "codec" to PCM, 32kHz on 1 channel
|
||||
webrtc::VoECodec* ptrVoECodec;
|
||||
webrtc::CodecInst codec;
|
||||
ptrVoECodec = webrtc::VoECodec::GetInterface(mVoiceEngine);
|
||||
if (!ptrVoECodec) {
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(codec.plname, ENCODING);
|
||||
codec.channels = CHANNELS;
|
||||
codec.rate = SAMPLE_RATE;
|
||||
codec.plfreq = SAMPLE_FREQUENCY;
|
||||
codec.pacsize = SAMPLE_LENGTH;
|
||||
codec.pltype = 0; // Default payload type
|
||||
|
||||
if (ptrVoECodec->SetSendCodec(mChannel, codec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mInitDone = true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCAudioSource::Shutdown()
|
||||
@ -196,6 +208,8 @@ MediaEngineWebRTCAudioSource::Shutdown()
|
||||
Deallocate();
|
||||
}
|
||||
|
||||
mVoEBase->Terminate();
|
||||
mVoERender->Release();
|
||||
mVoEBase->Release();
|
||||
|
||||
mState = kReleased;
|
||||
|
@ -21,29 +21,6 @@ extern PRLogModuleInfo* gMediaManagerLog;
|
||||
*/
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
|
||||
|
||||
MediaEngineWebRTCVideoSource::MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr,
|
||||
int aIndex, int aMinFps)
|
||||
: mVideoEngine(aVideoEnginePtr)
|
||||
, mCaptureIndex(aIndex)
|
||||
, mCapabilityChosen(false)
|
||||
, mWidth(640)
|
||||
, mHeight(480)
|
||||
, mState(kReleased)
|
||||
, mMonitor("WebRTCCamera.Monitor")
|
||||
, mFps(DEFAULT_VIDEO_FPS)
|
||||
, mMinFps(aMinFps)
|
||||
, mInitDone(false)
|
||||
, mInSnapshotMode(false)
|
||||
, mSnapshotPath(NULL)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
MediaEngineWebRTCVideoSource::~MediaEngineWebRTCVideoSource()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
// ViEExternalRenderer Callback.
|
||||
int
|
||||
MediaEngineWebRTCVideoSource::FrameSizeChange(
|
||||
@ -59,8 +36,6 @@ int
|
||||
MediaEngineWebRTCVideoSource::DeliverFrame(
|
||||
unsigned char* buffer, int size, uint32_t time_stamp, int64_t render_time)
|
||||
{
|
||||
ReentrantMonitorAutoEnter enter(mMonitor);
|
||||
|
||||
if (mInSnapshotMode) {
|
||||
// Set the condition variable to false and notify Snapshot().
|
||||
PR_Lock(mSnapshotLock);
|
||||
@ -78,6 +53,7 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
|
||||
|
||||
// Create a video frame and append it to the track.
|
||||
ImageFormat format = PLANAR_YCBCR;
|
||||
|
||||
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&format, 1);
|
||||
|
||||
layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
|
||||
@ -101,12 +77,48 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
|
||||
|
||||
videoImage->SetData(data);
|
||||
|
||||
VideoSegment segment;
|
||||
segment.AppendFrame(image.forget(), 1, gfxIntSize(mWidth, mHeight));
|
||||
mSource->AppendToTrack(mTrackID, &(segment));
|
||||
#ifdef LOG_ALL_FRAMES
|
||||
static uint32_t frame_num = 0;
|
||||
LOG(("frame %d; timestamp %u, render_time %lu", frame_num++, time_stamp, render_time));
|
||||
#endif
|
||||
|
||||
// we don't touch anything in 'this' until here (except for snapshot,
|
||||
// which has it's own lock)
|
||||
ReentrantMonitorAutoEnter enter(mMonitor);
|
||||
|
||||
// implicitly releases last image
|
||||
mImage = image.forget();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Called if the graph thinks it's running out of buffered video; repeat
|
||||
// the last frame for whatever minimum period it think it needs. Note that
|
||||
// this means that no *real* frame can be inserted during this period.
|
||||
void
|
||||
MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
StreamTime aDesiredTime)
|
||||
{
|
||||
VideoSegment segment;
|
||||
|
||||
ReentrantMonitorAutoEnter enter(mMonitor);
|
||||
|
||||
if (mState != kStarted)
|
||||
return;
|
||||
|
||||
// Note: we're not giving up mImage here
|
||||
nsRefPtr<layers::Image> image = mImage;
|
||||
TrackTicks target = TimeToTicksRoundUp(USECS_PER_S, aDesiredTime);
|
||||
TrackTicks delta = target - mLastEndTime;
|
||||
#ifdef LOG_ALL_FRAMES
|
||||
LOG(("NotifyPull, target = %lu, delta = %lu", (uint64_t) target, (uint64_t) delta));
|
||||
#endif
|
||||
// NULL images are allowed
|
||||
segment.AppendFrame(image ? image.forget() : nullptr, delta, gfxIntSize(mWidth, mHeight));
|
||||
mSource->AppendToTrack(mTrackID, &(segment));
|
||||
mLastEndTime = target;
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCVideoSource::ChooseCapability(uint32_t aWidth, uint32_t aHeight, uint32_t aMinFPS)
|
||||
{
|
||||
@ -191,10 +203,6 @@ MediaEngineWebRTCVideoSource::Allocate()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mViECapture->StartCapture(mCaptureIndex, mCapability) < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mState = kAllocated;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -206,7 +214,6 @@ MediaEngineWebRTCVideoSource::Deallocate()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mViECapture->StopCapture(mCaptureIndex);
|
||||
mViECapture->ReleaseCaptureDevice(mCaptureIndex);
|
||||
mState = kReleased;
|
||||
return NS_OK;
|
||||
@ -241,8 +248,10 @@ MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
mTrackID = aID;
|
||||
|
||||
mImageContainer = layers::LayerManager::CreateImageContainer();
|
||||
mSource->AddTrack(aID, mFps, 0, new VideoSegment());
|
||||
|
||||
mSource->AddTrack(aID, USECS_PER_S, 0, new VideoSegment());
|
||||
mSource->AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
mLastEndTime = 0;
|
||||
|
||||
error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
|
||||
if (error == -1) {
|
||||
@ -254,6 +263,10 @@ MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mViECapture->StartCapture(mCaptureIndex, mCapability) < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mState = kStarted;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -270,6 +283,7 @@ MediaEngineWebRTCVideoSource::Stop()
|
||||
|
||||
mViERender->StopRender(mCaptureIndex);
|
||||
mViERender->RemoveRenderer(mCaptureIndex);
|
||||
mViECapture->StopCapture(mCaptureIndex);
|
||||
|
||||
mState = kStopped;
|
||||
return NS_OK;
|
||||
|
@ -1,6 +1,6 @@
|
||||
This is sqlite 3.7.14
|
||||
This is sqlite 3.7.14.1
|
||||
|
||||
-- Ryan VanderMeulen <ryanvm@gmail.com>, 09/2012
|
||||
-- Ryan VanderMeulen <ryanvm@gmail.com>, 10/2012
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version 3.7.14. By combining all the individual C code files into this
|
||||
** version 3.7.14.1. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@ -673,9 +673,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.7.14"
|
||||
#define SQLITE_VERSION "3.7.14.1"
|
||||
#define SQLITE_VERSION_NUMBER 3007014
|
||||
#define SQLITE_SOURCE_ID "2012-09-03 15:42:36 c0d89d4a9752922f9e367362366efde4f1b06f2a"
|
||||
#define SQLITE_SOURCE_ID "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -53849,6 +53849,9 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
|
||||
** If aOvflSpace is set to a null pointer, this function returns
|
||||
** SQLITE_NOMEM.
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
static int balance_nonroot(
|
||||
MemPage *pParent, /* Parent page of siblings being balanced */
|
||||
int iParentIdx, /* Index of "the page" in pParent */
|
||||
@ -54479,6 +54482,9 @@ balance_cleanup:
|
||||
|
||||
return rc;
|
||||
}
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@ -106086,7 +106092,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
}
|
||||
pLevel->u.pCovidx = pCov;
|
||||
pLevel->iIdxCur = iCovCur;
|
||||
if( pCov ) pLevel->iIdxCur = iCovCur;
|
||||
if( pAndExpr ){
|
||||
pAndExpr->pLeft = 0;
|
||||
sqlite3ExprDelete(pParse->db, pAndExpr);
|
||||
|
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.7.14"
|
||||
#define SQLITE_VERSION "3.7.14.1"
|
||||
#define SQLITE_VERSION_NUMBER 3007014
|
||||
#define SQLITE_SOURCE_ID "2012-09-03 15:42:36 c0d89d4a9752922f9e367362366efde4f1b06f2a"
|
||||
#define SQLITE_SOURCE_ID "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
@ -4933,6 +4933,23 @@ nsDocShell::Destroy()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
|
||||
{
|
||||
if (mParentWidget) {
|
||||
*aScale = mParentWidget->GetDefaultScale();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
|
||||
if (ownerWindow) {
|
||||
return ownerWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale);
|
||||
}
|
||||
|
||||
*aScale = 1.0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetPosition(int32_t x, int32_t y)
|
||||
{
|
||||
@ -4990,6 +5007,13 @@ NS_IMETHODIMP
|
||||
nsDocShell::GetPositionAndSize(int32_t * x, int32_t * y, int32_t * cx,
|
||||
int32_t * cy)
|
||||
{
|
||||
if (mParentWidget) {
|
||||
// ensure size is up-to-date if window has changed resolution
|
||||
nsIntRect r;
|
||||
mParentWidget->GetClientBounds(r);
|
||||
SetPositionAndSize(mBounds.x, mBounds.y, r.width, r.height, false);
|
||||
}
|
||||
|
||||
// We should really consider just getting this information from
|
||||
// our window instead of duplicating the storage and code...
|
||||
if (cx || cy) {
|
||||
|
@ -27,7 +27,7 @@ static mozilla::RefPtr<BluetoothOppManager> sInstance;
|
||||
static nsCOMPtr<nsIInputStream> stream = nullptr;
|
||||
static uint32_t sSentFileLength = 0;
|
||||
static nsString sFileName;
|
||||
static uint64_t sFileLength = 0;
|
||||
static uint32_t sFileLength = 0;
|
||||
static nsString sContentType;
|
||||
static int sUpdateProgressCounter = 0;
|
||||
|
||||
@ -98,6 +98,8 @@ BluetoothOppManager::BluetoothOppManager() : mConnected(false)
|
||||
, mAbortFlag(false)
|
||||
, mReadFileThread(nullptr)
|
||||
, mPacketLeftLength(0)
|
||||
, mReceiving(false)
|
||||
, mPutFinal(false)
|
||||
{
|
||||
// FIXME / Bug 800249:
|
||||
// mConnectedDeviceAddress is Bluetooth address of connected device,
|
||||
@ -222,7 +224,7 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
int receivedLength = aMessage->mSize;
|
||||
|
||||
if (mPacketLeftLength > 0) {
|
||||
opCode = ObexRequestCode::Put;
|
||||
opCode = mPutFinal ? ObexRequestCode::PutFinal : ObexRequestCode::Put;
|
||||
packetLength = mPacketLeftLength;
|
||||
} else {
|
||||
opCode = aMessage->mData[0];
|
||||
@ -254,18 +256,32 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
sFileName.AssignLiteral("Unknown");
|
||||
}
|
||||
|
||||
rv = mBlob->GetSize(&sFileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
return;
|
||||
}
|
||||
|
||||
rv = mBlob->GetType(sContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get content type");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t fileLength;
|
||||
rv = mBlob->GetSize(&fileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently we keep the size of files which were sent/received via
|
||||
// Bluetooth not exceed UINT32_MAX because the Length header in OBEX
|
||||
// is only 4-byte long. Although it is possible to transfer a file
|
||||
// larger than UINT32_MAX, it needs to parse another OBEX Header
|
||||
// and I would like to leave it as a feature.
|
||||
if (fileLength <= UINT32_MAX) {
|
||||
NS_WARNING("The file size is too large for now");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
|
||||
NS_WARNING("Can't create thread");
|
||||
SendDisconnectRequest();
|
||||
@ -286,6 +302,7 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
NS_WARNING("[OPP] Disconnect failed");
|
||||
} else {
|
||||
mConnected = false;
|
||||
mReceiving = false;
|
||||
mLastCommand = 0;
|
||||
mBlob = nullptr;
|
||||
mReadFileThread = nullptr;
|
||||
@ -330,35 +347,53 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
SendDisconnectRequest();
|
||||
} else {
|
||||
// Remote request or unknown mLastCommand
|
||||
ObexHeaderSet pktHeaders(opCode);
|
||||
|
||||
if (opCode == ObexRequestCode::Connect) {
|
||||
ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders);
|
||||
ReplyToConnect();
|
||||
} else if (opCode == ObexRequestCode::Disconnect) {
|
||||
ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders);
|
||||
ReplyToDisconnect();
|
||||
} else if (opCode == ObexRequestCode::Put ||
|
||||
opCode == ObexRequestCode::PutFinal) {
|
||||
if (!mReceiving) {
|
||||
MOZ_ASSERT(mPacketLeftLength == 0);
|
||||
ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders);
|
||||
|
||||
pktHeaders.GetName(sFileName);
|
||||
pktHeaders.GetContentType(sContentType);
|
||||
pktHeaders.GetLength(&sFileLength);
|
||||
|
||||
ReceivingFileConfirmation(mConnectedDeviceAddress, sFileName, sFileLength, sContentType);
|
||||
mReceiving = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* A PUT request from remote devices may be divided into multiple parts.
|
||||
* In other words, one request may need to be received multiple times,
|
||||
* so here we keep a variable mPacketLeftLength to indicate if current
|
||||
* PUT request is done.
|
||||
*/
|
||||
bool final = (opCode == ObexRequestCode::PutFinal);
|
||||
mPutFinal = (opCode == ObexRequestCode::PutFinal);
|
||||
|
||||
if (mPacketLeftLength == 0) {
|
||||
if (receivedLength < packetLength) {
|
||||
mPacketLeftLength = packetLength - receivedLength;
|
||||
} else {
|
||||
ReplyToPut(final);
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(mPacketLeftLength < receivedLength,
|
||||
NS_ASSERTION(mPacketLeftLength >= receivedLength,
|
||||
"Invalid packet length");
|
||||
mPacketLeftLength = packetLength - receivedLength;
|
||||
} else {
|
||||
NS_ASSERTION(mPacketLeftLength >= receivedLength,
|
||||
"Invalid packet length");
|
||||
mPacketLeftLength -= receivedLength;
|
||||
}
|
||||
|
||||
if (mPacketLeftLength <= receivedLength) {
|
||||
ReplyToPut(final);
|
||||
mPacketLeftLength = 0;
|
||||
} else {
|
||||
mPacketLeftLength -= receivedLength;
|
||||
if (mPacketLeftLength == 0) {
|
||||
ReplyToPut(mPutFinal);
|
||||
|
||||
if (mPutFinal) {
|
||||
mReceiving = false;
|
||||
FileTransferComplete(mConnectedDeviceAddress, true, true, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -668,6 +703,39 @@ BluetoothOppManager::UpdateProgress(const nsString& aDeviceAddress,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::ReceivingFileConfirmation(const nsString& aAddress,
|
||||
const nsString& aFileName,
|
||||
uint32_t aFileLength,
|
||||
const nsString& aContentType)
|
||||
{
|
||||
nsString type, name;
|
||||
BluetoothValue v;
|
||||
InfallibleTArray<BluetoothNamedValue> parameters;
|
||||
type.AssignLiteral("bluetooth-opp-receiving-file-confirmation");
|
||||
|
||||
name.AssignLiteral("address");
|
||||
v = aAddress;
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
|
||||
name.AssignLiteral("fileName");
|
||||
v = aFileName;
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
|
||||
name.AssignLiteral("fileLength");
|
||||
v = aFileLength;
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
|
||||
name.AssignLiteral("contentType");
|
||||
v = aContentType;
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
|
||||
if (!BroadcastSystemMessage(type, parameters)) {
|
||||
NS_WARNING("Failed to broadcast [bluetooth-opp-receiving-file-confirmation]");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::OnConnectSuccess()
|
||||
{
|
||||
|
@ -76,6 +76,10 @@ private:
|
||||
bool aReceived,
|
||||
uint32_t aProcessedLength,
|
||||
uint32_t aFileLength);
|
||||
void ReceivingFileConfirmation(const nsString& aAddress,
|
||||
const nsString& aFileName,
|
||||
uint32_t aFileLength,
|
||||
const nsString& aContentType);
|
||||
void ReplyToConnect();
|
||||
void ReplyToDisconnect();
|
||||
void ReplyToPut(bool aFinal);
|
||||
@ -92,6 +96,8 @@ private:
|
||||
bool mAbortFlag;
|
||||
int mPacketLeftLength;
|
||||
nsString mConnectedDeviceAddress;
|
||||
bool mReceiving;
|
||||
bool mPutFinal;
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> mBlob;
|
||||
nsCOMPtr<nsIThread> mReadFileThread;
|
||||
|
@ -75,7 +75,7 @@ ParseHeaders(uint8_t* buf, int totalLength, ObexHeaderSet* retHandlerSet)
|
||||
|
||||
while (ptr - buf < totalLength) {
|
||||
ObexHeaderId headerId = (ObexHeaderId)*ptr++;
|
||||
int headerLength = 0;
|
||||
int contentLength = 0;
|
||||
uint8_t highByte, lowByte;
|
||||
|
||||
// Defined in 2.1 OBEX Headers, IrOBEX 1.2
|
||||
@ -87,26 +87,31 @@ ParseHeaders(uint8_t* buf, int totalLength, ObexHeaderSet* retHandlerSet)
|
||||
// byte sequence, length prefixed with 2 byte unsigned integer.
|
||||
highByte = *ptr++;
|
||||
lowByte = *ptr++;
|
||||
headerLength = ((int)highByte << 8) | lowByte;
|
||||
contentLength = (((int)highByte << 8) | lowByte) - 3;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
// 1 byte quantity
|
||||
headerLength = 1;
|
||||
contentLength = 1;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
// 4 byte quantity
|
||||
headerLength = 4;
|
||||
contentLength = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
// Content
|
||||
uint8_t* headerContent = new uint8_t[headerLength];
|
||||
memcpy(headerContent, ptr, headerLength);
|
||||
retHandlerSet->AddHeader(new ObexHeader(headerId, headerLength, headerContent));
|
||||
// FIXME: This case should be happened when we are receiving header 'Body'
|
||||
// (file body). I will handle this in another bug.
|
||||
if (contentLength + (ptr - buf) > totalLength) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += headerLength;
|
||||
uint8_t* content = new uint8_t[contentLength];
|
||||
memcpy(content, ptr, contentLength);
|
||||
retHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, content));
|
||||
|
||||
ptr += contentLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,56 @@ public:
|
||||
{
|
||||
mHeaders.AppendElement(aHeader);
|
||||
}
|
||||
|
||||
void GetName(nsString& aRetName)
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Name) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
int nameLength = mHeaders[i]->mDataLength / 2;
|
||||
|
||||
for (int j = 0; j < nameLength; ++j) {
|
||||
PRUnichar c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
|
||||
aRetName += c;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetContentType(nsString& aRetContentType)
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Type) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
aRetContentType.AssignASCII((const char*)ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @return file length, 0 means file length is unknown.
|
||||
void GetLength(uint32_t* aRetLength)
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
*aRetLength = 0;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Length) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
*aRetLength = ((uint32_t)ptr[0] << 24) |
|
||||
((uint32_t)ptr[1] << 16) |
|
||||
((uint32_t)ptr[2] << 8) |
|
||||
((uint32_t)ptr[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int AppendHeaderName(uint8_t* retBuf, const char* name, int length);
|
||||
|
@ -452,20 +452,56 @@ BrowserElementChild.prototype = {
|
||||
|
||||
_recvGetScreenshot: function(data) {
|
||||
debug("Received getScreenshot message: (" + data.json.id + ")");
|
||||
|
||||
// You can think of the screenshotting algorithm as carrying out the
|
||||
// following steps:
|
||||
//
|
||||
// - Let max-width be data.json.args.width, and let max-height be
|
||||
// data.json.args.height.
|
||||
//
|
||||
// - Let scale-width be the factor by which we'd need to downscale the
|
||||
// viewport so it would fit within max-width. (If the viewport's width
|
||||
// is less than max-width, let scale-width be 1.) Compute scale-height
|
||||
// the same way.
|
||||
//
|
||||
// - Scale the viewport by max(scale-width, scale-height). Now either the
|
||||
// viewport's width is no larger than max-width, the viewport's height is
|
||||
// no larger than max-height, or both.
|
||||
//
|
||||
// - Crop the viewport so its width is no larger than max-width and its
|
||||
// height is no larger than max-height.
|
||||
//
|
||||
// - Return a screenshot of the page's viewport scaled and cropped per
|
||||
// above.
|
||||
|
||||
let maxWidth = data.json.args.width;
|
||||
let maxHeight = data.json.args.height;
|
||||
|
||||
let scaleWidth = Math.min(1, maxWidth / content.innerWidth);
|
||||
let scaleHeight = Math.min(1, maxHeight / content.innerHeight);
|
||||
|
||||
let scale = Math.max(scaleWidth, scaleHeight);
|
||||
|
||||
let canvasWidth = Math.min(maxWidth, Math.round(content.innerWidth * scale));
|
||||
let canvasHeight = Math.min(maxHeight, Math.round(content.innerHeight * scale));
|
||||
|
||||
var canvas = content.document
|
||||
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
canvas.mozOpaque = true;
|
||||
canvas.height = content.innerHeight;
|
||||
canvas.width = content.innerWidth;
|
||||
ctx.drawWindow(content, 0, 0, content.innerWidth,
|
||||
content.innerHeight, "rgb(255,255,255)");
|
||||
canvas.width = canvasWidth;
|
||||
canvas.height = canvasHeight;
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.scale(scale, scale);
|
||||
ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
|
||||
"rgb(255,255,255)");
|
||||
|
||||
sendAsyncMsg('got-screenshot', {
|
||||
id: data.json.id,
|
||||
// Hack around the fact that we can't specify opaque PNG, this requires
|
||||
// us to unpremultiply the alpha channel which is expensive on ARM
|
||||
// processors because they lack a hardware integer division instruction.
|
||||
rv: canvas.toDataURL("image/jpeg")
|
||||
successRv: canvas.toDataURL("image/jpeg")
|
||||
});
|
||||
},
|
||||
|
||||
@ -550,7 +586,7 @@ BrowserElementChild.prototype = {
|
||||
var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
sendAsyncMsg('got-can-go-back', {
|
||||
id: data.json.id,
|
||||
rv: webNav.canGoBack
|
||||
successRv: webNav.canGoBack
|
||||
});
|
||||
},
|
||||
|
||||
@ -558,7 +594,7 @@ BrowserElementChild.prototype = {
|
||||
var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
sendAsyncMsg('got-can-go-forward', {
|
||||
id: data.json.id,
|
||||
rv: webNav.canGoForward
|
||||
successRv: webNav.canGoForward
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -243,7 +243,7 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
||||
defineMethod('goForward', this._goForward);
|
||||
defineMethod('reload', this._reload);
|
||||
defineMethod('stop', this._stop);
|
||||
defineDOMRequestMethod('getScreenshot', 'get-screenshot');
|
||||
defineMethod('getScreenshot', this._getScreenshot);
|
||||
defineDOMRequestMethod('getCanGoBack', 'get-can-go-back');
|
||||
defineDOMRequestMethod('getCanGoForward', 'get-can-go-forward');
|
||||
|
||||
@ -470,15 +470,18 @@ BrowserElementParent.prototype = {
|
||||
* Kick off a DOMRequest in the child process.
|
||||
*
|
||||
* We'll fire an event called |msgName| on the child process, passing along
|
||||
* an object with a single field, id, containing the ID of this request.
|
||||
* an object with two fields:
|
||||
*
|
||||
* - id: the ID of this request.
|
||||
* - arg: arguments to pass to the child along with this request.
|
||||
*
|
||||
* We expect the child to pass the ID back to us upon completion of the
|
||||
* request; see _gotDOMRequestResult.
|
||||
* request. See _gotDOMRequestResult.
|
||||
*/
|
||||
_sendDOMRequest: function(msgName) {
|
||||
_sendDOMRequest: function(msgName, args) {
|
||||
let id = 'req_' + this._domRequestCounter++;
|
||||
let req = Services.DOMRequest.createRequest(this._window);
|
||||
if (this._sendAsyncMsg(msgName, {id: id})) {
|
||||
if (this._sendAsyncMsg(msgName, {id: id, args: args})) {
|
||||
this._pendingDOMRequests[id] = req;
|
||||
} else {
|
||||
Services.DOMRequest.fireErrorAsync(req, "fail");
|
||||
@ -487,17 +490,30 @@ BrowserElementParent.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the child process finishes handling a DOMRequest. We expect
|
||||
* data.json to have two fields:
|
||||
* Called when the child process finishes handling a DOMRequest. data.json
|
||||
* must have the fields [id, successRv], if the DOMRequest was successful, or
|
||||
* [id, errorMsg], if the request was not successful.
|
||||
*
|
||||
* - id: the ID of the DOM request (see _sendDOMRequest), and
|
||||
* - rv: the request's return value.
|
||||
* The fields have the following meanings:
|
||||
*
|
||||
* - id: the ID of the DOM request (see _sendDOMRequest)
|
||||
* - successRv: the request's return value, if the request succeeded
|
||||
* - errorMsg: the message to pass to DOMRequest.fireError(), if the request
|
||||
* failed.
|
||||
*
|
||||
*/
|
||||
_gotDOMRequestResult: function(data) {
|
||||
let req = this._pendingDOMRequests[data.json.id];
|
||||
delete this._pendingDOMRequests[data.json.id];
|
||||
Services.DOMRequest.fireSuccess(req, data.json.rv);
|
||||
|
||||
if ('successRv' in data.json) {
|
||||
debug("Successful gotDOMRequestResult.");
|
||||
Services.DOMRequest.fireSuccess(req, data.json.successRv);
|
||||
}
|
||||
else {
|
||||
debug("Got error in gotDOMRequestResult.");
|
||||
Services.DOMRequest.fireErrorAsync(req, data.json.errorMsg);
|
||||
}
|
||||
},
|
||||
|
||||
_setVisible: function(visible) {
|
||||
@ -548,6 +564,18 @@ BrowserElementParent.prototype = {
|
||||
this._sendAsyncMsg('stop');
|
||||
},
|
||||
|
||||
_getScreenshot: function(_width, _height) {
|
||||
let width = parseInt(_width);
|
||||
let height = parseInt(_height);
|
||||
if (isNaN(width) || isNaN(height) || width < 0 || height < 0) {
|
||||
throw Components.Exception("Invalid argument",
|
||||
Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
return this._sendDOMRequest('get-screenshot',
|
||||
{width: width, height: height});
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(data) {
|
||||
let evt = this._window.document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent(data.json.type, true, true, this._window,
|
||||
|
@ -43,6 +43,8 @@ MOCHITEST_FILES = \
|
||||
test_browserElement_inproc_Iconchange.html \
|
||||
browserElement_GetScreenshot.js \
|
||||
test_browserElement_inproc_GetScreenshot.html \
|
||||
browserElement_BadScreenshot.js \
|
||||
test_browserElement_inproc_BadScreenshot.html \
|
||||
browserElement_SetVisible.js \
|
||||
test_browserElement_inproc_SetVisible.html \
|
||||
browserElement_SetVisibleFrames.js \
|
||||
@ -169,6 +171,7 @@ MOCHITEST_FILES += \
|
||||
test_browserElement_oop_TopBarrier.html \
|
||||
test_browserElement_oop_Iconchange.html \
|
||||
test_browserElement_oop_GetScreenshot.html \
|
||||
test_browserElement_oop_BadScreenshot.html \
|
||||
test_browserElement_oop_SetVisible.html \
|
||||
test_browserElement_oop_SetVisibleFrames.html \
|
||||
test_browserElement_oop_SetVisibleFrames2.html \
|
||||
|
@ -0,0 +1,74 @@
|
||||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Bug 800170 - Test that we get errors when we pass bad arguments to
|
||||
// mozbrowser's getScreenshot.
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var iframe;
|
||||
var numPendingTests = 0;
|
||||
|
||||
// Call iframe.getScreenshot with the given args. If expectSuccess is true, we
|
||||
// expect the screenshot's onsuccess handler to fire. Otherwise, we expect
|
||||
// getScreenshot() to throw an exception.
|
||||
function checkScreenshotResult(expectSuccess, args) {
|
||||
var req;
|
||||
try {
|
||||
req = iframe.getScreenshot.apply(iframe, args);
|
||||
}
|
||||
catch(e) {
|
||||
ok(!expectSuccess, "getScreenshot(" + JSON.stringify(args) + ") threw an exception.");
|
||||
return;
|
||||
}
|
||||
|
||||
numPendingTests++;
|
||||
req.onsuccess = function() {
|
||||
ok(expectSuccess, "getScreenshot(" + JSON.stringify(args) + ") succeeded.");
|
||||
numPendingTests--;
|
||||
if (numPendingTests == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
// We never expect to see onerror.
|
||||
req.onerror = function() {
|
||||
ok(false, "getScreenshot(" + JSON.stringify(args) + ") ran onerror.");
|
||||
numPendingTests--;
|
||||
if (numPendingTests == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
dump("XXX runTest\n");
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.mozbrowser = true;
|
||||
document.body.appendChild(iframe);
|
||||
iframe.src = 'data:text/html,<html>' +
|
||||
'<body style="background:green">hello</body></html>';
|
||||
|
||||
iframe.addEventListener('mozbrowserfirstpaint', function() {
|
||||
// This one should succeed.
|
||||
checkScreenshotResult(true, [100, 100]);
|
||||
|
||||
// These should fail.
|
||||
checkScreenshotResult(false, []);
|
||||
checkScreenshotResult(false, [100]);
|
||||
checkScreenshotResult(false, ['a', 100]);
|
||||
checkScreenshotResult(false, [100, 'a']);
|
||||
checkScreenshotResult(false, [-1, 100]);
|
||||
checkScreenshotResult(false, [100, -1]);
|
||||
|
||||
if (numPendingTests == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
runTest();
|
@ -27,7 +27,7 @@ function runTest() {
|
||||
SimpleTest.executeSoon(nextTest);
|
||||
}
|
||||
|
||||
var domRequest = iframe1.getScreenshot();
|
||||
var domRequest = iframe1.getScreenshot(1000, 1000);
|
||||
domRequest.onsuccess = function(e) {
|
||||
testEnd();
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
// We continually take screenshots until we get one that we are
|
||||
// happy with
|
||||
// happy with.
|
||||
function waitForScreenshot(filter) {
|
||||
|
||||
function screenshotLoaded(e) {
|
||||
@ -50,13 +50,13 @@ function runTest() {
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
content.document.defaultView.setTimeout(function() {
|
||||
iframe1.getScreenshot().onsuccess = screenshotLoaded;
|
||||
iframe1.getScreenshot(1000, 1000).onsuccess = screenshotLoaded;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
var attempts = 10;
|
||||
iframe1.getScreenshot().onsuccess = screenshotLoaded;
|
||||
iframe1.getScreenshot(1000, 1000).onsuccess = screenshotLoaded;
|
||||
}
|
||||
|
||||
function iframeLoadedHandler() {
|
||||
@ -72,5 +72,3 @@ function runTest() {
|
||||
}
|
||||
|
||||
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ function runTest() {
|
||||
else if (e.detail.message == 'finish') {
|
||||
// We assume here that iframe is completely blank, and spin until popup's
|
||||
// screenshot is not the same as iframe.
|
||||
iframe.getScreenshot().onsuccess = function(e) {
|
||||
iframe.getScreenshot(1000, 1000).onsuccess = function(e) {
|
||||
test2(popup, e.target.result, popup);
|
||||
};
|
||||
}
|
||||
@ -72,7 +72,7 @@ var prevScreenshot;
|
||||
function test2(popup, blankScreenshot) {
|
||||
// Take screenshots of popup until it doesn't equal blankScreenshot (or we
|
||||
// time out).
|
||||
popup.getScreenshot().onsuccess = function(e) {
|
||||
popup.getScreenshot(1000, 1000).onsuccess = function(e) {
|
||||
var screenshot = e.target.result;
|
||||
if (screenshot != blankScreenshot) {
|
||||
SimpleTest.finish();
|
||||
|
@ -25,7 +25,7 @@ function runTest() {
|
||||
// taking the screenshot).
|
||||
e.preventDefault();
|
||||
|
||||
iframe.getScreenshot().onsuccess = function(sshot) {
|
||||
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
|
||||
if (initialScreenshot == null)
|
||||
initialScreenshot = sshot.target.result;
|
||||
e.detail.unblock();
|
||||
@ -37,7 +37,7 @@ function runTest() {
|
||||
case 'finish':
|
||||
// The page has now attempted to load the X-Frame-Options page; take
|
||||
// another screenshot.
|
||||
iframe.getScreenshot().onsuccess = function(sshot) {
|
||||
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
|
||||
is(sshot.target.result, initialScreenshot, "Screenshots should be identical");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ function runTest() {
|
||||
// taking the screenshot).
|
||||
e.preventDefault();
|
||||
|
||||
iframe.getScreenshot().onsuccess = function(sshot) {
|
||||
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
|
||||
initialScreenshot = sshot.target.result;
|
||||
e.detail.unblock();
|
||||
};
|
||||
@ -36,7 +36,7 @@ function runTest() {
|
||||
case 'step 2':
|
||||
// The page has now attempted to load the X-Frame-Options page; take
|
||||
// another screenshot.
|
||||
iframe.getScreenshot().onsuccess = function(sshot) {
|
||||
iframe.getScreenshot(1000, 1000).onsuccess = function(sshot) {
|
||||
is(sshot.target.result, initialScreenshot, "Screenshots should be identical");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 800170</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_BadScreenshot.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 800170</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_BadScreenshot.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -21,10 +21,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
|
||||
|
||||
"use strict";
|
||||
|
||||
var comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
comp.utils.import("resource://gre/modules/ContactService.jsm");
|
||||
comp.utils.import("resource://gre/modules/PermissionPromptHelper.jsm");
|
||||
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
|
||||
// this shouldn't be necessary when bug 792594 is fixed
|
||||
if (!SpecialPowers.getBoolPref("dom.mozContacts.enabled")) {
|
||||
var comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
comp.utils.import("resource://gre/modules/ContactService.jsm");
|
||||
comp.utils.import("resource://gre/modules/PermissionPromptHelper.jsm");
|
||||
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
|
||||
}
|
||||
|
||||
SpecialPowers.addPermission("contacts", true, document);
|
||||
|
||||
// For Sorting
|
||||
|
@ -21,10 +21,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
|
||||
|
||||
"use strict";
|
||||
|
||||
var comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
comp.utils.import("resource://gre/modules/ContactService.jsm");
|
||||
comp.utils.import("resource://gre/modules/PermissionPromptHelper.jsm");
|
||||
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
|
||||
// this shouldn't be necessary when bug 792594 is fixed
|
||||
if (!SpecialPowers.getBoolPref("dom.mozContacts.enabled")) {
|
||||
var comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
comp.utils.import("resource://gre/modules/ContactService.jsm");
|
||||
comp.utils.import("resource://gre/modules/PermissionPromptHelper.jsm");
|
||||
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
|
||||
}
|
||||
|
||||
SpecialPowers.addPermission("contacts", true, document);
|
||||
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
@ -345,9 +345,6 @@ test(
|
||||
continue;
|
||||
if (encoding === "iso-2022-kr" && (i === 0x0E || i === 0x0F || i === 0x1B))
|
||||
continue;
|
||||
// TODO: Gecko decoder bugs
|
||||
if ((encoding === "big5" || encoding === "euc-kr") && i === 0x7F)
|
||||
continue;
|
||||
|
||||
string += String.fromCharCode(i);
|
||||
bytes.push(i);
|
||||
|
@ -25,7 +25,7 @@ windows-1250.title = Central European (Windows-1250)
|
||||
windows-1252.title = Western (Windows-1252)
|
||||
windows-1254.title = Turkish (Windows-1254)
|
||||
windows-1257.title = Baltic (Windows-1257)
|
||||
x-mac-roman.title = Western (MacRoman)
|
||||
macintosh.title = Western (MacRoman)
|
||||
x-mac-ce.title = Central European (MacCE)
|
||||
x-mac-turkish.title = Turkish (MacTurkish)
|
||||
x-mac-croatian.title = Croatian (MacCroatian)
|
||||
|
@ -443,6 +443,7 @@ public:
|
||||
nsresult
|
||||
SelectDevice()
|
||||
{
|
||||
bool found = false;
|
||||
uint32_t count;
|
||||
if (mPicture || mVideo) {
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> > videoSources;
|
||||
@ -455,7 +456,22 @@ public:
|
||||
));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mVideoDevice = new MediaDevice(videoSources[0]);
|
||||
|
||||
// Pick the first available device.
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
nsRefPtr<MediaEngineVideoSource> vSource = videoSources[i];
|
||||
if (vSource->IsAvailable()) {
|
||||
found = true;
|
||||
mVideoDevice = new MediaDevice(videoSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(
|
||||
mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
|
||||
));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
LOG(("Selected video device"));
|
||||
}
|
||||
if (mAudio) {
|
||||
@ -469,7 +485,21 @@ public:
|
||||
));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mAudioDevice = new MediaDevice(audioSources[0]);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
nsRefPtr<MediaEngineAudioSource> aSource = audioSources[i];
|
||||
if (aSource->IsAvailable()) {
|
||||
found = true;
|
||||
mAudioDevice = new MediaDevice(audioSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(
|
||||
mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
|
||||
));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
LOG(("Selected audio device"));
|
||||
}
|
||||
|
||||
@ -596,11 +626,23 @@ public:
|
||||
nsTArray<nsCOMPtr<nsIMediaDevice> > *devices =
|
||||
new nsTArray<nsCOMPtr<nsIMediaDevice> >;
|
||||
|
||||
/**
|
||||
* We only display available devices in the UI for now. We can easily
|
||||
* change this later, when we implement a more sophisticated UI that
|
||||
* lets the user revoke a device currently held by another tab (or
|
||||
* we decide to provide a stream from a device already allocated).
|
||||
*/
|
||||
for (i = 0; i < videoCount; i++) {
|
||||
devices->AppendElement(new MediaDevice(videoSources[i]));
|
||||
nsRefPtr<MediaEngineVideoSource> vSource = videoSources[i];
|
||||
if (vSource->IsAvailable()) {
|
||||
devices->AppendElement(new MediaDevice(vSource));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < audioCount; i++) {
|
||||
devices->AppendElement(new MediaDevice(audioSources[i]));
|
||||
nsRefPtr<MediaEngineAudioSource> aSource = audioSources[i];
|
||||
if (aSource->IsAvailable()) {
|
||||
devices->AppendElement(new MediaDevice(aSource));
|
||||
}
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(
|
||||
|
@ -110,6 +110,8 @@ public:
|
||||
nsresult rv;
|
||||
|
||||
SourceMediaStream* stream = mStream->GetStream()->AsSourceStream();
|
||||
stream->SetPullEnabled(true);
|
||||
|
||||
if (mAudioSource) {
|
||||
rv = mAudioSource->Start(stream, kAudioTrack);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -122,6 +124,7 @@ public:
|
||||
MM_LOG(("Starting video failed, rv=%d",rv));
|
||||
}
|
||||
}
|
||||
|
||||
MM_LOG(("started all sources"));
|
||||
nsCOMPtr<GetUserMediaNotificationEvent> event =
|
||||
new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING);
|
||||
@ -135,6 +138,20 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// Proxy NotifyPull() to sources
|
||||
void
|
||||
NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime)
|
||||
{
|
||||
// Currently audio sources ignore NotifyPull, but they could
|
||||
// watch it especially for fake audio.
|
||||
if (mAudioSource) {
|
||||
mAudioSource->NotifyPull(aGraph, aDesiredTime);
|
||||
}
|
||||
if (mVideoSource) {
|
||||
mVideoSource->NotifyPull(aGraph, aDesiredTime);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<MediaEngineSource> mAudioSource;
|
||||
nsRefPtr<MediaEngineSource> mVideoSource;
|
||||
|
@ -174,8 +174,9 @@ SystemMessageManager.prototype = {
|
||||
" (" + this._manifest + ")");
|
||||
|
||||
let msg = aMessage.json;
|
||||
if (msg.manifest != this._manifest)
|
||||
if (msg.manifest != this._manifest || msg.uri != this._uri) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send an acknowledgement to parent to clean up the pending message,
|
||||
// so a re-launched app won't handle it again, which is redundant.
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(1b8ea6e4-8142-4aba-b174-4d580b5bc294)]
|
||||
[scriptable, builtinclass, uuid(c0de7fba-725f-4180-b1f1-83163014d1e2)]
|
||||
interface nsIDOMUSSDReceivedEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString message;
|
||||
[infallible] readonly attribute boolean sessionEnded;
|
||||
};
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "nsJSON.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "mozilla/dom/USSDReceivedEventBinding.h"
|
||||
|
||||
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
|
||||
|
||||
#define VOICECHANGE_EVENTNAME NS_LITERAL_STRING("voicechange")
|
||||
@ -157,13 +159,15 @@ MobileConnection::Observe(nsISupports* aSubject,
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kUssdReceivedTopic)) {
|
||||
nsString ussd;
|
||||
ussd.Assign(aData);
|
||||
nsRefPtr<USSDReceivedEvent> event = USSDReceivedEvent::Create(ussd);
|
||||
mozilla::dom::USSDReceivedEventDict dict;
|
||||
bool ok = dict.Init(nsDependentString(aData));
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
|
||||
nsRefPtr<USSDReceivedEvent> event =
|
||||
USSDReceivedEvent::Create(dict.message, dict.sessionEnded);
|
||||
NS_ASSERTION(event, "This should never fail!");
|
||||
|
||||
nsresult rv =
|
||||
event->Dispatch(ToIDOMEventTarget(), USSDRECEIVED_EVENTNAME);
|
||||
nsresult rv = event->Dispatch(ToIDOMEventTarget(), USSDRECEIVED_EVENTNAME);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -14,13 +14,14 @@ namespace dom {
|
||||
namespace network {
|
||||
|
||||
already_AddRefed<USSDReceivedEvent>
|
||||
USSDReceivedEvent::Create(nsAString& aMessage)
|
||||
USSDReceivedEvent::Create(nsAString& aMessage, bool aSessionEnded)
|
||||
{
|
||||
NS_ASSERTION(!aMessage.IsEmpty(), "Empty message!");
|
||||
|
||||
nsRefPtr<USSDReceivedEvent> event = new USSDReceivedEvent();
|
||||
|
||||
event->mMessage = aMessage;
|
||||
event->mSessionEnded = aSessionEnded;
|
||||
|
||||
return event.forget();
|
||||
}
|
||||
@ -40,6 +41,13 @@ USSDReceivedEvent::GetMessage(nsAString& aMessage)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
USSDReceivedEvent::GetSessionEnded(bool* aSessionEnded)
|
||||
{
|
||||
*aSessionEnded = mSessionEnded;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ class USSDReceivedEvent : public nsDOMEvent,
|
||||
public nsIDOMUSSDReceivedEvent
|
||||
{
|
||||
nsString mMessage;
|
||||
bool mSessionEnded;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -23,7 +24,7 @@ public:
|
||||
NS_DECL_NSIDOMUSSDRECEIVEDEVENT
|
||||
|
||||
static already_AddRefed<USSDReceivedEvent>
|
||||
Create(nsAString& aMessage);
|
||||
Create(nsAString& aMessage, bool aSessionEnded);
|
||||
|
||||
nsresult
|
||||
Dispatch(nsIDOMEventTarget* aTarget, const nsAString& aEventType)
|
||||
|
@ -277,6 +277,13 @@ PluginPRLibrary::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
|
||||
*aDrawing = false;
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
PluginPRLibrary::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor)
|
||||
{
|
||||
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
|
||||
NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
|
@ -114,6 +114,7 @@ public:
|
||||
virtual bool IsOOP() MOZ_OVERRIDE { return false; }
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing);
|
||||
virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor);
|
||||
#endif
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance) MOZ_OVERRIDE;
|
||||
virtual nsresult BeginUpdateBackground(NPP instance,
|
||||
|
@ -1081,6 +1081,26 @@ nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing)
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::ContentsScaleFactorChanged(double aContentsScaleFactor)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
if (!mPlugin)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// We only need to call this if the plugin is running OOP.
|
||||
if (!library->IsOOP())
|
||||
return NS_OK;
|
||||
|
||||
return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor);
|
||||
#else
|
||||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
|
||||
{
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
nsresult GetValueFromPlugin(NPPVariable variable, void* value);
|
||||
nsresult GetDrawingModel(int32_t* aModel);
|
||||
nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
|
||||
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
nsresult GetJSObject(JSContext *cx, JSObject** outObject);
|
||||
bool ShouldCache();
|
||||
nsresult IsWindowless(bool* isWindowless);
|
||||
|
@ -984,7 +984,7 @@ static const moz2javaCharset charsets[] =
|
||||
{"x-mac-greek", "MacGreek"},
|
||||
{"x-mac-hebrew", "MacHebrew"},
|
||||
{"x-mac-icelandic", "MacIceland"},
|
||||
{"x-mac-roman", "MacRoman"},
|
||||
{"macintosh", "MacRoman"},
|
||||
{"x-mac-romanian", "MacRomania"},
|
||||
{"x-mac-ukrainian", "MacUkraine"},
|
||||
{"Shift_JIS", "SJIS"},
|
||||
@ -1370,6 +1370,14 @@ bool nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation()
|
||||
return coreAnimation;
|
||||
}
|
||||
|
||||
nsresult nsPluginInstanceOwner::ContentsScaleFactorChanged(double aContentsScaleFactor)
|
||||
{
|
||||
if (!mInstance) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return mInstance->ContentsScaleFactorChanged(aContentsScaleFactor);
|
||||
}
|
||||
|
||||
NPEventModel nsPluginInstanceOwner::GetEventModel()
|
||||
{
|
||||
return mEventModel;
|
||||
|
@ -116,6 +116,7 @@ public:
|
||||
|
||||
NPDrawingModel GetDrawingModel();
|
||||
bool IsRemoteDrawingCoreAnimation();
|
||||
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
NPEventModel GetEventModel();
|
||||
static void CARefresh(nsITimer *aTimer, void *aClosure);
|
||||
void AddToCARefreshTimer();
|
||||
|
@ -118,6 +118,9 @@ child:
|
||||
returns (int16_t handled);
|
||||
// this is only used on windows to forward WM_WINDOWPOSCHANGE
|
||||
async WindowPosChanged(NPRemoteEvent event);
|
||||
// used on OS X to tell the child the contents scale factor
|
||||
// of its parent has changed
|
||||
async ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
|
||||
// ********************** Async plugins rendering
|
||||
// see https://wiki.mozilla.org/Gecko:AsyncPluginPainting
|
||||
|
@ -1013,6 +1013,24 @@ PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvContentsScaleFactorChanged(const double& aContentsScaleFactor)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
mContentsScaleFactor = aContentsScaleFactor;
|
||||
if (mShContext) {
|
||||
// Release the shared context so that it is reallocated
|
||||
// with the new size.
|
||||
::CGContextRelease(mShContext);
|
||||
mShContext = nullptr;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
NS_RUNTIMEABORT("ContentsScaleFactorChanged is an OSX-only message");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
// Create a new window from NPWindow
|
||||
bool PluginInstanceChild::CreateWindow(const NPRemoteWindow& aWindow)
|
||||
@ -3957,7 +3975,9 @@ PluginInstanceChild::SwapSurfaces()
|
||||
(mDoubleBufferCARenderer.GetFrontSurfaceWidth() !=
|
||||
mDoubleBufferCARenderer.GetBackSurfaceWidth() ||
|
||||
mDoubleBufferCARenderer.GetFrontSurfaceHeight() !=
|
||||
mDoubleBufferCARenderer.GetBackSurfaceHeight())) {
|
||||
mDoubleBufferCARenderer.GetBackSurfaceHeight() ||
|
||||
mDoubleBufferCARenderer.GetFrontSurfaceContentsScaleFactor() !=
|
||||
mDoubleBufferCARenderer.GetBackSurfaceContentsScaleFactor())) {
|
||||
|
||||
mDoubleBufferCARenderer.ClearFrontSurface();
|
||||
}
|
||||
|
@ -126,6 +126,9 @@ protected:
|
||||
virtual bool
|
||||
RecvWindowPosChanged(const NPRemoteEvent& event) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvContentsScaleFactorChanged(const double& aContentsScaleFactor) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
AnswerNPP_Destroy(NPError* result);
|
||||
|
||||
|
@ -447,7 +447,7 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel(
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginEventModel,
|
||||
(void*)eventModel);
|
||||
(void*)(intptr_t)eventModel);
|
||||
return true;
|
||||
#else
|
||||
*result = NPERR_GENERIC_ERROR;
|
||||
@ -799,7 +799,14 @@ PluginInstanceParent::IsRemoteDrawingCoreAnimation(bool *aDrawing)
|
||||
NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::ContentsScaleFactorChanged(double aContentsScaleFactor)
|
||||
{
|
||||
bool rv = SendContentsScaleFactorChanged(aContentsScaleFactor);
|
||||
return rv ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
#endif // #ifdef XP_MACOSX
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::SetBackgroundUnknown()
|
||||
|
@ -271,6 +271,7 @@ public:
|
||||
nsresult GetImageSize(nsIntSize* aSize);
|
||||
#ifdef XP_MACOSX
|
||||
nsresult IsRemoteDrawingCoreAnimation(bool *aDrawing);
|
||||
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
#endif
|
||||
nsresult SetBackgroundUnknown();
|
||||
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
virtual bool IsOOP() = 0;
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) = 0;
|
||||
virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -1185,7 +1185,17 @@ PluginModuleParent::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
|
||||
|
||||
return i->IsRemoteDrawingCoreAnimation(aDrawing);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor)
|
||||
{
|
||||
PluginInstanceParent* i = InstCast(instance);
|
||||
if (!i)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return i->ContentsScaleFactorChanged(aContentsScaleFactor);
|
||||
}
|
||||
#endif // #if defined(XP_MACOSX)
|
||||
|
||||
bool
|
||||
PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
|
||||
|
@ -271,6 +271,7 @@ private:
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing);
|
||||
virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor);
|
||||
#endif
|
||||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
virtual nsresult HandleGUIEvent(NPP instance, const nsGUIEvent& anEvent,
|
||||
|
@ -50,12 +50,14 @@ public:
|
||||
// Returns height in "display pixels". Multiply by
|
||||
// mContentsScaleFactor to get device pixels.
|
||||
size_t GetFrontSurfaceHeight();
|
||||
double GetFrontSurfaceContentsScaleFactor();
|
||||
// Returns width in "display pixels". Multiply by
|
||||
// mContentsScaleFactor to get device pixels.
|
||||
size_t GetBackSurfaceWidth();
|
||||
// Returns height in "display pixels". Multiply by
|
||||
// mContentsScaleFactor to get device pixels.
|
||||
size_t GetBackSurfaceHeight();
|
||||
double GetBackSurfaceContentsScaleFactor();
|
||||
IOSurfaceID GetFrontSurfaceID();
|
||||
|
||||
bool HasBackSurface();
|
||||
|
@ -269,6 +269,14 @@ size_t nsDoubleBufferCARenderer::GetFrontSurfaceHeight() {
|
||||
return mFrontSurface->GetHeight();
|
||||
}
|
||||
|
||||
double nsDoubleBufferCARenderer::GetFrontSurfaceContentsScaleFactor() {
|
||||
if (!HasFrontSurface()) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return mFrontSurface->GetContentsScaleFactor();
|
||||
}
|
||||
|
||||
size_t nsDoubleBufferCARenderer::GetBackSurfaceWidth() {
|
||||
if (!HasBackSurface()) {
|
||||
return 0;
|
||||
@ -285,6 +293,14 @@ size_t nsDoubleBufferCARenderer::GetBackSurfaceHeight() {
|
||||
return mBackSurface->GetHeight();
|
||||
}
|
||||
|
||||
double nsDoubleBufferCARenderer::GetBackSurfaceContentsScaleFactor() {
|
||||
if (!HasBackSurface()) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return mBackSurface->GetContentsScaleFactor();
|
||||
}
|
||||
|
||||
IOSurfaceID nsDoubleBufferCARenderer::GetFrontSurfaceID() {
|
||||
if (!HasFrontSurface()) {
|
||||
return 0;
|
||||
|
@ -710,14 +710,15 @@ RILContentHelper.prototype = {
|
||||
}
|
||||
break;
|
||||
case "RIL:USSDReceived":
|
||||
Services.obs.notifyObservers(null, kUssdReceivedTopic,
|
||||
msg.json.message);
|
||||
let res = JSON.stringify({message: msg.json.message,
|
||||
sessionEnded: msg.json.sessionEnded});
|
||||
Services.obs.notifyObservers(null, kUssdReceivedTopic, res);
|
||||
break;
|
||||
case "RIL:SendMMI:Return:OK":
|
||||
case "RIL:CancelMMI:Return:OK":
|
||||
request = this.takeRequest(msg.json.requestId);
|
||||
if (request) {
|
||||
Services.DOMRequest.fireSuccess(request, msg.json);
|
||||
Services.DOMRequest.fireSuccess(request, msg.json.result);
|
||||
}
|
||||
break;
|
||||
case "RIL:SendMMI:Return:KO":
|
||||
|
@ -1883,8 +1883,8 @@ let RIL = {
|
||||
Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
|
||||
},
|
||||
|
||||
getIMEI: function getIMEI() {
|
||||
Buf.simpleRequest(REQUEST_GET_IMEI);
|
||||
getIMEI: function getIMEI(options) {
|
||||
Buf.simpleRequest(REQUEST_GET_IMEI, options);
|
||||
},
|
||||
|
||||
getIMEISV: function getIMEISV() {
|
||||
@ -2369,8 +2369,16 @@ let RIL = {
|
||||
|
||||
// IMEI
|
||||
case MMI_SC_IMEI:
|
||||
// TODO: Bug 793189 - MMI Codes: get IMEI.
|
||||
_sendMMIError("GET_IMEI_NOT_SUPPORTED_VIA_MMI");
|
||||
// A device's IMEI can't change, so we only need to request it once.
|
||||
if (this.IMEI == null) {
|
||||
this.getIMEI({mmi: true});
|
||||
return;
|
||||
}
|
||||
// If we already had the device's IMEI, we just send it to the DOM.
|
||||
options.rilMessageType = "sendMMI";
|
||||
options.success = true;
|
||||
options.result = this.IMEI;
|
||||
this.sendDOMMessage(options);
|
||||
return;
|
||||
|
||||
// Call barring
|
||||
@ -4420,11 +4428,20 @@ RIL[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, option
|
||||
};
|
||||
RIL[REQUEST_SMS_ACKNOWLEDGE] = null;
|
||||
RIL[REQUEST_GET_IMEI] = function REQUEST_GET_IMEI(length, options) {
|
||||
if (options.rilRequestError) {
|
||||
this.IMEI = Buf.readString();
|
||||
// So far we only send the IMEI back to the DOM if it was requested via MMI.
|
||||
if (!options.mmi) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.IMEI = Buf.readString();
|
||||
options.rilMessageType = "sendMMI";
|
||||
options.success = options.rilRequestError == 0;
|
||||
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||
if ((!options.success || this.IMEI == null) && !options.errorMsg) {
|
||||
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
|
||||
}
|
||||
options.result = this.IMEI;
|
||||
this.sendDOMMessage(options);
|
||||
};
|
||||
RIL[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV(length, options) {
|
||||
if (options.rilRequestError) {
|
||||
@ -4828,14 +4845,11 @@ RIL[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
|
||||
debug("On USSD. Type Code: " + typeCode + " Message: " + message);
|
||||
}
|
||||
|
||||
this._ussdSession = (typeCode != "0" || typeCode != "2");
|
||||
this._ussdSession = (typeCode != "0" && typeCode != "2");
|
||||
|
||||
// Empty message should not be progressed to the DOM.
|
||||
if (!message || message == "") {
|
||||
return;
|
||||
}
|
||||
this.sendDOMMessage({rilMessageType: "USSDReceived",
|
||||
message: message});
|
||||
message: message,
|
||||
sessionEnded: !this._ussdSession});
|
||||
};
|
||||
RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
|
||||
let dateString = Buf.readString();
|
||||
|
@ -324,8 +324,55 @@ add_test(function test_sendMMI_sim_function() {
|
||||
});
|
||||
|
||||
add_test(function test_sendMMI_get_IMEI() {
|
||||
// TODO: Bug 793189 - MMI Codes: get IMEI
|
||||
testSendMMI("*#06#", "GET_IMEI_NOT_SUPPORTED_VIA_MMI");
|
||||
let postedMessage;
|
||||
let mmiOptions;
|
||||
let worker = newWorker({
|
||||
postRILMessage: function fakePostRILMessage(data) {
|
||||
},
|
||||
postMessage: function fakePostMessage(message) {
|
||||
postedMessage = message;
|
||||
},
|
||||
});
|
||||
|
||||
worker.RIL.getIMEI = function getIMEI(options){
|
||||
mmiOptions = options;
|
||||
worker.RIL[REQUEST_SEND_USSD](0, {
|
||||
rilRequestError: ERROR_SUCCESS,
|
||||
});
|
||||
}
|
||||
|
||||
worker.RIL.sendMMI({mmi: "*#06#"});
|
||||
|
||||
do_check_true(mmiOptions.mmi);
|
||||
do_check_eq (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
|
||||
do_check_true(postedMessage.success);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_sendMMI_get_IMEI_error() {
|
||||
let postedMessage;
|
||||
let mmiOptions;
|
||||
let worker = newWorker({
|
||||
postRILMessage: function fakePostRILMessage(data) {
|
||||
},
|
||||
postMessage: function fakePostMessage(message) {
|
||||
postedMessage = message;
|
||||
},
|
||||
});
|
||||
|
||||
worker.RIL.getIMEI = function getIMEI(options){
|
||||
mmiOptions = options;
|
||||
worker.RIL[REQUEST_SEND_USSD](0, {
|
||||
rilRequestError: ERROR_RADIO_NOT_AVAILABLE,
|
||||
});
|
||||
}
|
||||
|
||||
worker.RIL.sendMMI({mmi: "*#06#"});
|
||||
|
||||
do_check_true(mmiOptions.mmi);
|
||||
do_check_eq (postedMessage.errorMsg, GECKO_ERROR_RADIO_NOT_AVAILABLE);
|
||||
do_check_false(postedMessage.success);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
10
dom/webidl/USSDReceivedEvent.webidl
Normal file
10
dom/webidl/USSDReceivedEvent.webidl
Normal file
@ -0,0 +1,10 @@
|
||||
/* -*- Mode: IDL; 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/.
|
||||
*/
|
||||
|
||||
dictionary USSDReceivedEventDict {
|
||||
DOMString message = "";
|
||||
boolean sessionEnded = false;
|
||||
};
|
@ -61,6 +61,12 @@ webidl_files += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
webidl_files += \
|
||||
USSDReceivedEvent.webidl \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
test_webidl_files := \
|
||||
TestCodeGen.webidl \
|
||||
|
@ -470,6 +470,17 @@ nsDocShellTreeOwner::Destroy()
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
|
||||
{
|
||||
if (mWebBrowser) {
|
||||
return mWebBrowser->GetUnscaledDevicePixelsPerCSSPixel(aScale);
|
||||
}
|
||||
|
||||
*aScale = 1.0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user