mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Merge m-i to m-c, a=merge
This commit is contained in:
commit
66b3a90750
@ -76,10 +76,6 @@ leak:processInternalEntity
|
||||
# Bug 1187421 - With e10s, NSS does not always free the error stack. m1.
|
||||
leak:nss_ClearErrorStack
|
||||
|
||||
# Bug 1189430 - DNS leaks in mochitest-chrome.
|
||||
leak:nsDNSService::AsyncResolveExtended
|
||||
leak:_GetAddrInfo_Portable
|
||||
|
||||
# Bug 1189568 - Indirect leaks of IMContextWrapper and nsIntRect.
|
||||
leak:nsWindow::Create
|
||||
leak:nsBaseWidget::StoreWindowClipRegion
|
||||
|
@ -1136,10 +1136,11 @@ public:
|
||||
NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
|
||||
KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
|
||||
nsPrintfCString(
|
||||
"Memory used to back small memory files (less than %d bytes each).\n\n"
|
||||
"Memory used to back small memory files (i.e. those taking up less "
|
||||
"than %zu bytes of memory each).\n\n"
|
||||
"Note that the allocator may round up a memory file's length -- "
|
||||
"that is, an N-byte memory file may take up more than N bytes of "
|
||||
"memory."),
|
||||
"memory.", LARGE_OBJECT_MIN_SIZE),
|
||||
aData);
|
||||
}
|
||||
|
||||
|
@ -461,7 +461,7 @@ nsTextFragment::UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength)
|
||||
char16_t ch2 = *cp++;
|
||||
utf32Char = SURROGATE_TO_UCS4(ch1, ch2);
|
||||
}
|
||||
if (UTF32_CHAR_IS_BIDI(utf32Char) || IsBidiControl(utf32Char)) {
|
||||
if (UTF32_CHAR_IS_BIDI(utf32Char) || IsBidiControlRTL(utf32Char)) {
|
||||
mState.mIsBidi = true;
|
||||
break;
|
||||
}
|
||||
|
@ -3805,19 +3805,6 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
if (aVisitor.mEvent->mMessage == eKeyUp && aVisitor.mEvent->IsTrusted()) {
|
||||
WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
|
||||
if (MayFireChangeOnKeyUp(keyEvent->mKeyCode) &&
|
||||
!(keyEvent->IsShift() || keyEvent->IsControl() || keyEvent->IsAlt() ||
|
||||
keyEvent->IsMeta() || keyEvent->IsAltGraph() || keyEvent->IsFn() ||
|
||||
keyEvent->IsOS())) {
|
||||
// The up/down arrow key events fire 'change' events when released
|
||||
// so that at the end of a series of up/down arrow key repeat events
|
||||
// the value is considered to be "commited" by the user.
|
||||
FireChangeEventIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
|
||||
|
||||
// We do this after calling the base class' PreHandleEvent so that
|
||||
@ -4303,6 +4290,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
// event to increase/decrease the value of the number control.
|
||||
if (!aVisitor.mEvent->DefaultPreventedByContent() && IsMutable()) {
|
||||
StepNumberControlForUserEvent(keyEvent->mKeyCode == NS_VK_UP ? 1 : -1);
|
||||
FireChangeEventIfNeeded();
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
} else if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
|
||||
@ -4480,6 +4468,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
break;
|
||||
}
|
||||
SetValueOfRangeForUserEvent(newValue);
|
||||
FireChangeEventIfNeeded();
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
@ -4557,6 +4546,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
do_QueryFrame(GetPrimaryFrame());
|
||||
if (numberControlFrame && numberControlFrame->IsFocused()) {
|
||||
StepNumberControlForUserEvent(wheelEvent->mDeltaY > 0 ? -1 : 1);
|
||||
FireChangeEventIfNeeded();
|
||||
aVisitor.mEvent->PreventDefault();
|
||||
}
|
||||
} else if (mType == NS_FORM_INPUT_RANGE &&
|
||||
@ -4570,6 +4560,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
MOZ_ASSERT(value.isFinite() && step.isFinite());
|
||||
SetValueOfRangeForUserEvent(wheelEvent->mDeltaY < 0 ?
|
||||
value + step : value - step);
|
||||
FireChangeEventIfNeeded();
|
||||
aVisitor.mEvent->PreventDefault();
|
||||
}
|
||||
}
|
||||
@ -8344,18 +8335,6 @@ HTMLInputElement::GetWebkitEntries(nsTArray<RefPtr<FileSystemEntry>>& aSequence)
|
||||
aSequence.AppendElements(mEntries);
|
||||
}
|
||||
|
||||
bool HTMLInputElement::MayFireChangeOnKeyUp(uint32_t aKeyCode) const
|
||||
{
|
||||
switch (mType) {
|
||||
case NS_FORM_INPUT_NUMBER:
|
||||
return aKeyCode == NS_VK_UP || aKeyCode == NS_VK_DOWN;
|
||||
case NS_FORM_INPUT_RANGE:
|
||||
return aKeyCode == NS_VK_UP || aKeyCode == NS_VK_DOWN ||
|
||||
aKeyCode == NS_VK_LEFT || aKeyCode == NS_VK_RIGHT;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -1515,12 +1515,6 @@ private:
|
||||
aType == NS_FORM_INPUT_NUMBER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the key code may induce the input's value changed to fire
|
||||
* a "change" event accordingly.
|
||||
*/
|
||||
bool MayFireChangeOnKeyUp(uint32_t aKeyCode) const;
|
||||
|
||||
struct nsFilePickerFilter {
|
||||
nsFilePickerFilter()
|
||||
: mFilterMask(0) {}
|
||||
|
@ -215,9 +215,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599
|
||||
is(rangeChange, 0, "Change event shouldn't be dispatched on range input element for key changes that don't change its value");
|
||||
range.focus();
|
||||
synthesizeKey("VK_HOME", {});
|
||||
is(rangeChange, 0, "Change event shouldn't be dispatched on range input element for key changes until it loses focus");
|
||||
is(rangeChange, 1, "Change event should be dispatched on range input element for key changes");
|
||||
range.blur();
|
||||
is(rangeChange, 1, "Change event should be dispatched on range input element on blur");
|
||||
is(rangeChange, 1, "Change event shouldn't be dispatched on range input element on blur");
|
||||
range.focus();
|
||||
var bcr = range.getBoundingClientRect();
|
||||
var centerOfRangeX = bcr.width / 2;
|
||||
@ -233,6 +233,32 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599
|
||||
synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, {});
|
||||
is(rangeChange, 3, "Change event should be dispatched on range input element for a click that gives the range focus");
|
||||
|
||||
if (isDesktop) { // up/down arrow keys not supported on android/b2g
|
||||
synthesizeKey("VK_UP", {});
|
||||
is(rangeChange, 4, "Change event should be dispatched on range input element for key changes that change its value (VK_UP)");
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
is(rangeChange, 5, "Change event should be dispatched on range input element for key changes that change its value (VK_DOWN)");
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
is(rangeChange, 6, "Change event should be dispatched on range input element for key changes that change its value (VK_RIGHT)");
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
is(rangeChange, 7, "Change event should be dispatched on range input element for key changes that change its value (VK_LEFT)");
|
||||
synthesizeKey("VK_UP", {shiftKey: true});
|
||||
is(rangeChange, 8, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_UP)");
|
||||
synthesizeKey("VK_DOWN", {shiftKey: true});
|
||||
is(rangeChange, 9, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_DOWN)");
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
is(rangeChange, 10, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_RIGHT)");
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
is(rangeChange, 11, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_LEFT)");
|
||||
synthesizeKey("VK_PAGE_UP", {});
|
||||
is(rangeChange, 12, "Change event should be dispatched on range input element for key changes that change its value (VK_PAGE_UP)");
|
||||
synthesizeKey("VK_PAGE_DOWN", {});
|
||||
is(rangeChange, 13, "Change event should be dispatched on range input element for key changes that change its value (VK_PAGE_DOWN");
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
is(rangeChange, 14, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_PAGE_UP)");
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
is(rangeChange, 15, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_PAGE_DOWN)");
|
||||
}
|
||||
//Input type change test.
|
||||
input = document.getElementById("input_checkbox");
|
||||
input.type = "text";
|
||||
|
@ -631,3 +631,6 @@ skip-if = (os != 'win' && os != 'linux')
|
||||
[test_bug1260704.html]
|
||||
[test_allowMedia.html]
|
||||
[test_bug1292522_same_domain_with_different_port_number.html]
|
||||
[test_bug1295719_event_sequence_for_arrow_keys.html]
|
||||
skip-if = os == "android" || appname == "b2g" # up/down arrow keys not supported on android/b2g
|
||||
[test_bug1295719_event_sequence_for_number_keys.html]
|
@ -42,10 +42,17 @@ function runTests() {
|
||||
|
||||
let testIdx = 0;
|
||||
let result = parseInt(input.value);
|
||||
let numberChange = 0;
|
||||
let expectChange = 0;
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
++numberChange;
|
||||
}, false);
|
||||
|
||||
function runNext() {
|
||||
let p = params[testIdx];
|
||||
(p["focus"]) ? input.focus() : input.blur();
|
||||
expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1;
|
||||
result += parseInt(p["valueChanged"]);
|
||||
synthesizeWheel(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] });
|
||||
window.postMessage("finished", "http://mochi.test:8888");
|
||||
@ -57,6 +64,8 @@ function runTests() {
|
||||
ok(input.value == result,
|
||||
"Handle wheel in number input test-" + testIdx + " expect " + result +
|
||||
" get " + input.value);
|
||||
ok(numberChange == expectChange,
|
||||
"UA should fire change event when input's value changed, expect " + expectChange + " get " + numberChange);
|
||||
(testIdx >= params.length) ? SimpleTest.finish() : runNext();
|
||||
}
|
||||
});
|
||||
|
@ -43,14 +43,23 @@ function runTests() {
|
||||
|
||||
let testIdx = 0;
|
||||
let result = parseInt(input.value);
|
||||
let rangeChange = 0;
|
||||
let expectChange = 0;
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
++rangeChange;
|
||||
}, false);
|
||||
|
||||
function runNext() {
|
||||
let p = params[testIdx];
|
||||
(p["focus"]) ? input.focus() : input.blur();
|
||||
expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1;
|
||||
result += parseInt(p["valueChanged"]);
|
||||
sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => {
|
||||
ok(input.value == result,
|
||||
"Handle wheel in range input test-" + testIdx + " expect " + result + " get " + input.value);
|
||||
ok(rangeChange == expectChange,
|
||||
"UA should fire change event when input's value changed, expect " + expectChange + " get " + rangeChange);
|
||||
(++testIdx >= params.length) ? SimpleTest.finish() : runNext();
|
||||
});
|
||||
}
|
||||
|
@ -41,6 +41,11 @@ function runTests() {
|
||||
|
||||
let testIdx = 0;
|
||||
let result = parseInt(input.value);
|
||||
let rangeChange = 0;
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
++rangeChange;
|
||||
}, false);
|
||||
|
||||
function runNext() {
|
||||
let p = params[testIdx];
|
||||
@ -48,6 +53,7 @@ function runTests() {
|
||||
sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => {
|
||||
ok(input.value == result,
|
||||
"Handle wheel in range input test-" + testIdx + " expect " + result + " get " + input.value);
|
||||
ok(rangeChange == 0, "Wheel event should not trigger change event when max < min");
|
||||
testIdx++;
|
||||
(testIdx >= params.length) ? SimpleTest.finish() : runNext();
|
||||
});
|
||||
|
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1295719
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1295719</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295719">Mozilla Bug 1295719</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<input id="test_number" type="number" value=50>
|
||||
<input id="test_range" type="range" value=50 max=100 min=0>
|
||||
<script type="text/javascript">
|
||||
|
||||
/** Test for Bug 1295719 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function runTests() {
|
||||
let number = window.document.getElementById("test_number");
|
||||
let range = window.document.getElementById("test_range");
|
||||
let waiting_event_sequence = ["keydown", "keypress", "input", "change"];
|
||||
|
||||
let waiting_event_idx = 0;
|
||||
waiting_event_sequence.forEach((eventType) => {
|
||||
number.addEventListener(eventType, (event) => {
|
||||
let waiting_event = waiting_event_sequence[waiting_event_idx];
|
||||
is(waiting_event, eventType, "Waiting " + waiting_event + " get " + eventType);
|
||||
// Input element will fire input and change events when handling keypress
|
||||
// with keycode=arrows. When user press and hold the keyboard, we expect
|
||||
// that input element repeatedly fires "keydown", "keypress", "input", and
|
||||
// "change" events until user release the keyboard. Using
|
||||
// waiting_event_sequence as a circular buffer and reset waiting_event_idx
|
||||
// when it point to the end of buffer.
|
||||
waiting_event_idx = waiting_event_idx == waiting_event_sequence.length -1 ? 0 : waiting_event_idx + 1;
|
||||
}, false);
|
||||
range.addEventListener(eventType, (event) => {
|
||||
let waiting_event = waiting_event_sequence[waiting_event_idx];
|
||||
is(waiting_event, eventType, "Waiting " + waiting_event + " get " + eventType);
|
||||
waiting_event_idx = waiting_event_idx == waiting_event_sequence.length - 1 ? 0 : waiting_event_idx + 1;
|
||||
}, false);
|
||||
});
|
||||
|
||||
number.focus();
|
||||
synthesizeKey("VK_DOWN", {type: "keydown"});
|
||||
synthesizeKey("VK_DOWN", {type: "keydown"});
|
||||
synthesizeKey("VK_DOWN", {type: "keyup"});
|
||||
number.blur();
|
||||
range.focus();
|
||||
waiting_event_idx = 0;
|
||||
synthesizeKey("VK_DOWN", {type: "keydown"});
|
||||
synthesizeKey("VK_DOWN", {type: "keydown"});
|
||||
synthesizeKey("VK_DOWN", {type: "keyup"});
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1295719
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1295719</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295719">Mozilla Bug 1295719</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<input id="test_number" type="number" value=50>
|
||||
<script type="text/javascript">
|
||||
|
||||
/** Test for Bug 1295719 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function runTests() {
|
||||
let number = window.document.getElementById("test_number");
|
||||
let waiting_event_sequence = ["keydown", "keypress", "input"];
|
||||
let change_event_of_number = 0;
|
||||
let keyup_event_of_number = 0;
|
||||
let waiting_event_idx = 0;
|
||||
waiting_event_sequence.forEach((eventType) => {
|
||||
number.addEventListener(eventType, (event) => {
|
||||
let waiting_event = waiting_event_sequence[waiting_event_idx];
|
||||
is(eventType, waiting_event, "Waiting " + waiting_event + " get " + eventType);
|
||||
// Input element will fire input event when handling keypress with
|
||||
// keycode=numbers. When user press and hold the keyboard, we expect that
|
||||
// input element repeatedly fires "keydown", "keypress", and "input" until
|
||||
// user release the keyboard. Input element will fire change event when
|
||||
// it's blurred. Using waiting_event_sequence as a circular buffer and
|
||||
// reset waiting_event_idx when it point to the end of buffer.
|
||||
waiting_event_idx = waiting_event_idx == waiting_event_sequence.length - 1 ? 0 : waiting_event_idx + 1;
|
||||
}, false);
|
||||
});
|
||||
number.addEventListener("change", (event) => {
|
||||
is(keyup_event_of_number, 1, "change event should be fired after blurred");
|
||||
++change_event_of_number;
|
||||
}, false);
|
||||
number.addEventListener("keyup", (event) => {
|
||||
is(keyup_event_of_number, 0, "keyup event should be fired once");
|
||||
is(change_event_of_number, 0, "keyup event should be fired before change event");
|
||||
++keyup_event_of_number;
|
||||
}, false);
|
||||
number.focus();
|
||||
synthesizeKey("5", {type: "keydown"});
|
||||
synthesizeKey("5", {type: "keydown"});
|
||||
synthesizeKey("5", {type: "keyup"});
|
||||
is(change_event_of_number, 0, "change event shouldn't be fired when input element is focused");
|
||||
number.blur();
|
||||
is(change_event_of_number, 1, "change event should be fired when input element is blurred");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -294,6 +294,12 @@ void VideoFrameContainer::ClearFutureFrames()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VideoFrameContainer::ClearCachedResources()
|
||||
{
|
||||
mImageContainer->ClearCachedResources();
|
||||
}
|
||||
|
||||
ImageContainer* VideoFrameContainer::GetImageContainer() {
|
||||
return mImageContainer;
|
||||
}
|
||||
|
@ -73,6 +73,9 @@ public:
|
||||
// but was actually painted at t+n, this returns n in seconds. Threadsafe.
|
||||
double GetFrameDelay();
|
||||
|
||||
// Clear any resources that are not immediately necessary.
|
||||
void ClearCachedResources();
|
||||
|
||||
// Returns a new frame ID for SetCurrentFrames(). The client must either
|
||||
// call this on only one thread or provide barriers. Do not use together
|
||||
// with SetCurrentFrame().
|
||||
|
@ -145,6 +145,9 @@ VideoSink::SetPlaying(bool aPlaying)
|
||||
mUpdateScheduler.Reset();
|
||||
// Since playback is paused, tell compositor to render only current frame.
|
||||
RenderVideoFrames(1);
|
||||
if (mContainer) {
|
||||
mContainer->ClearCachedResources();
|
||||
}
|
||||
}
|
||||
|
||||
mAudioSink->SetPlaying(aPlaying);
|
||||
|
@ -72,7 +72,7 @@ AvailabilityCollection::Remove(PresentationAvailability* aAvailability)
|
||||
}
|
||||
|
||||
already_AddRefed<PresentationAvailability>
|
||||
AvailabilityCollection::Find(const uint64_t aWindowId, const nsAString& aUrl)
|
||||
AvailabilityCollection::Find(const uint64_t aWindowId, const nsTArray<nsString>& aUrls)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -85,7 +85,7 @@ AvailabilityCollection::Find(const uint64_t aWindowId, const nsAString& aUrl)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (availability->Equals(aWindowId, aUrl)) {
|
||||
if (availability->Equals(aWindowId, aUrls)) {
|
||||
RefPtr<PresentationAvailability> matchedAvailability = availability.get();
|
||||
return matchedAvailability.forget();
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
void Remove(PresentationAvailability* aAvailability);
|
||||
|
||||
already_AddRefed<PresentationAvailability>
|
||||
Find(const uint64_t aWindowId, const nsAString& aUrl);
|
||||
Find(const uint64_t aWindowId, const nsTArray<nsString>& aUrls);
|
||||
|
||||
private:
|
||||
friend class StaticAutoPtr<AvailabilityCollection>;
|
||||
|
@ -37,20 +37,20 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
/* static */ already_AddRefed<PresentationAvailability>
|
||||
PresentationAvailability::Create(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aUrl,
|
||||
const nsTArray<nsString>& aUrls,
|
||||
RefPtr<Promise>& aPromise)
|
||||
{
|
||||
RefPtr<PresentationAvailability> availability =
|
||||
new PresentationAvailability(aWindow, aUrl);
|
||||
new PresentationAvailability(aWindow, aUrls);
|
||||
return NS_WARN_IF(!availability->Init(aPromise)) ? nullptr
|
||||
: availability.forget();
|
||||
}
|
||||
|
||||
PresentationAvailability::PresentationAvailability(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aUrl)
|
||||
const nsTArray<nsString>& aUrls)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mIsAvailable(false)
|
||||
, mUrl(aUrl)
|
||||
, mUrls(aUrls)
|
||||
{
|
||||
}
|
||||
|
||||
@ -120,10 +120,15 @@ PresentationAvailability::WrapObject(JSContext* aCx,
|
||||
|
||||
bool
|
||||
PresentationAvailability::Equals(const uint64_t aWindowID,
|
||||
const nsAString& aUrl) const
|
||||
const nsTArray<nsString>& aUrls) const
|
||||
{
|
||||
if (GetOwner() && GetOwner()->WindowID() == aWindowID &&
|
||||
mUrl.Equals(aUrl)) {
|
||||
mUrls.Length() == aUrls.Length()) {
|
||||
for (const auto& url : aUrls) {
|
||||
if (!mUrls.Contains(url)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -162,8 +167,7 @@ PresentationAvailability::NotifyAvailableChange(bool aIsAvailable)
|
||||
void
|
||||
PresentationAvailability::UpdateAvailabilityAndDispatchEvent(bool aIsAvailable)
|
||||
{
|
||||
PRES_DEBUG("%s:id[%s]\n", __func__,
|
||||
NS_ConvertUTF16toUTF8(mUrl).get());
|
||||
PRES_DEBUG("%s\n", __func__);
|
||||
bool isChanged = (aIsAvailable != mIsAvailable);
|
||||
|
||||
mIsAvailable = aIsAvailable;
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
|
||||
static already_AddRefed<PresentationAvailability>
|
||||
Create(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aUrl,
|
||||
const nsTArray<nsString>& aUrls,
|
||||
RefPtr<Promise>& aPromise);
|
||||
|
||||
virtual void DisconnectFromOwner() override;
|
||||
@ -37,7 +37,7 @@ public:
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
bool Equals(const uint64_t aWindowID, const nsAString& aUrl) const;
|
||||
bool Equals(const uint64_t aWindowID, const nsTArray<nsString>& aUrls) const;
|
||||
|
||||
bool IsCachedValueReady();
|
||||
|
||||
@ -50,7 +50,7 @@ public:
|
||||
|
||||
private:
|
||||
explicit PresentationAvailability(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aUrl);
|
||||
const nsTArray<nsString>& aUrls);
|
||||
|
||||
virtual ~PresentationAvailability();
|
||||
|
||||
@ -64,7 +64,7 @@ private:
|
||||
|
||||
nsTArray<RefPtr<Promise>> mPromises;
|
||||
|
||||
nsString mUrl;
|
||||
nsTArray<nsString> mUrls;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -25,11 +25,9 @@ using namespace mozilla::dom;
|
||||
NS_IMPL_ISUPPORTS(PresentationRequesterCallback, nsIPresentationServiceCallback)
|
||||
|
||||
PresentationRequesterCallback::PresentationRequesterCallback(PresentationRequest* aRequest,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aSessionId,
|
||||
Promise* aPromise)
|
||||
: mRequest(aRequest)
|
||||
, mUrl(aUrl)
|
||||
, mSessionId(aSessionId)
|
||||
, mPromise(aPromise)
|
||||
{
|
||||
@ -44,12 +42,16 @@ PresentationRequesterCallback::~PresentationRequesterCallback()
|
||||
|
||||
// nsIPresentationServiceCallback
|
||||
NS_IMETHODIMP
|
||||
PresentationRequesterCallback::NotifySuccess()
|
||||
PresentationRequesterCallback::NotifySuccess(const nsAString& aUrl)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aUrl.IsEmpty()) {
|
||||
return NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
|
||||
RefPtr<PresentationConnection> connection =
|
||||
PresentationConnection::Create(mRequest->GetOwner(), mSessionId, mUrl,
|
||||
PresentationConnection::Create(mRequest->GetOwner(), mSessionId, aUrl,
|
||||
nsIPresentationService::ROLE_CONTROLLER);
|
||||
if (NS_WARN_IF(!connection)) {
|
||||
mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
||||
@ -79,11 +81,10 @@ NS_IMPL_ISUPPORTS_INHERITED0(PresentationReconnectCallback,
|
||||
|
||||
PresentationReconnectCallback::PresentationReconnectCallback(
|
||||
PresentationRequest* aRequest,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aSessionId,
|
||||
Promise* aPromise,
|
||||
PresentationConnection* aConnection)
|
||||
: PresentationRequesterCallback(aRequest, aUrl, aSessionId, aPromise)
|
||||
: PresentationRequesterCallback(aRequest, aSessionId, aPromise)
|
||||
, mConnection(aConnection)
|
||||
{
|
||||
}
|
||||
@ -93,7 +94,7 @@ PresentationReconnectCallback::~PresentationReconnectCallback()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationReconnectCallback::NotifySuccess()
|
||||
PresentationReconnectCallback::NotifySuccess(const nsAString& aUrl)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -116,7 +117,7 @@ PresentationReconnectCallback::NotifySuccess()
|
||||
} else {
|
||||
// Use |PresentationRequesterCallback::NotifySuccess| to create a new
|
||||
// connection since we don't find one that can be reused.
|
||||
rv = PresentationRequesterCallback::NotifySuccess();
|
||||
rv = PresentationRequesterCallback::NotifySuccess(aUrl);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ public:
|
||||
NS_DECL_NSIPRESENTATIONSERVICECALLBACK
|
||||
|
||||
PresentationRequesterCallback(PresentationRequest* aRequest,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aSessionId,
|
||||
Promise* aPromise);
|
||||
|
||||
@ -39,7 +38,6 @@ protected:
|
||||
virtual ~PresentationRequesterCallback();
|
||||
|
||||
RefPtr<PresentationRequest> mRequest;
|
||||
nsString mUrl;
|
||||
nsString mSessionId;
|
||||
RefPtr<Promise> mPromise;
|
||||
};
|
||||
@ -51,7 +49,6 @@ public:
|
||||
NS_DECL_NSIPRESENTATIONSERVICECALLBACK
|
||||
|
||||
PresentationReconnectCallback(PresentationRequest* aRequest,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aSessionId,
|
||||
Promise* aPromise,
|
||||
PresentationConnection* aConnection);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/dom/PresentationRequestBinding.h"
|
||||
#include "mozilla/dom/PresentationConnectionAvailableEvent.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozIThirdPartyUtil.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
@ -64,6 +65,16 @@ GetAbsoluteURL(const nsAString& aUrl,
|
||||
PresentationRequest::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aUrl,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Sequence<nsString> urls;
|
||||
urls.AppendElement(aUrl, fallible);
|
||||
return Constructor(aGlobal, urls, aRv);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<PresentationRequest>
|
||||
PresentationRequest::Constructor(const GlobalObject& aGlobal,
|
||||
const Sequence<nsString>& aUrls,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
@ -71,31 +82,35 @@ PresentationRequest::Constructor(const GlobalObject& aGlobal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Ensure the URL is not empty.
|
||||
if (NS_WARN_IF(aUrl.IsEmpty())) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
if (aUrls.IsEmpty()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Resolve relative URL to absolute URL
|
||||
nsCOMPtr<nsIURI> baseUri = window->GetDocBaseURI();
|
||||
nsTArray<nsString> urls;
|
||||
for (const auto& url : aUrls) {
|
||||
nsAutoString absoluteUrl;
|
||||
nsresult rv =
|
||||
GetAbsoluteURL(url, baseUri, window->GetExtantDoc(), absoluteUrl);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoString absoluteUrl;
|
||||
nsresult rv = GetAbsoluteURL(aUrl, baseUri, window->GetExtantDoc(), absoluteUrl);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
urls.AppendElement(absoluteUrl);
|
||||
}
|
||||
|
||||
RefPtr<PresentationRequest> request =
|
||||
new PresentationRequest(window, absoluteUrl);
|
||||
new PresentationRequest(window, Move(urls));
|
||||
return NS_WARN_IF(!request->Init()) ? nullptr : request.forget();
|
||||
}
|
||||
|
||||
PresentationRequest::PresentationRequest(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aUrl)
|
||||
nsTArray<nsString>&& aUrls)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mUrl(aUrl)
|
||||
, mUrls(Move(aUrls))
|
||||
{
|
||||
}
|
||||
|
||||
@ -152,7 +167,7 @@ PresentationRequest::StartWithDevice(const nsAString& aDeviceId,
|
||||
}
|
||||
|
||||
if (IsProhibitMixedSecurityContexts(doc) &&
|
||||
!IsPrioriAuthenticatedURL(mUrl)) {
|
||||
!IsAllURLAuthenticated()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
@ -185,8 +200,8 @@ PresentationRequest::StartWithDevice(const nsAString& aDeviceId,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresentationServiceCallback> callback =
|
||||
new PresentationRequesterCallback(this, mUrl, id, promise);
|
||||
rv = service->StartSession(mUrl, id, origin, aDeviceId, GetOwner()->WindowID(), callback);
|
||||
new PresentationRequesterCallback(this, id, promise);
|
||||
rv = service->StartSession(mUrls, id, origin, aDeviceId, GetOwner()->WindowID(), callback);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
@ -216,7 +231,7 @@ PresentationRequest::Reconnect(const nsAString& aPresentationId,
|
||||
}
|
||||
|
||||
if (IsProhibitMixedSecurityContexts(doc) &&
|
||||
!IsPrioriAuthenticatedURL(mUrl)) {
|
||||
!IsAllURLAuthenticated()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
@ -262,7 +277,7 @@ PresentationRequest::FindOrCreatePresentationConnection(
|
||||
if (connection) {
|
||||
nsAutoString url;
|
||||
connection->GetUrl(url);
|
||||
if (url.Equals(mUrl)) {
|
||||
if (mUrls.Contains(url)) {
|
||||
switch (connection->State()) {
|
||||
case PresentationConnectionState::Closed:
|
||||
// We found the matched connection.
|
||||
@ -293,13 +308,12 @@ PresentationRequest::FindOrCreatePresentationConnection(
|
||||
|
||||
nsCOMPtr<nsIPresentationServiceCallback> callback =
|
||||
new PresentationReconnectCallback(this,
|
||||
mUrl,
|
||||
aPresentationId,
|
||||
aPromise,
|
||||
connection);
|
||||
|
||||
nsresult rv =
|
||||
service->ReconnectSession(mUrl,
|
||||
service->ReconnectSession(mUrls,
|
||||
aPresentationId,
|
||||
nsIPresentationService::ROLE_CONTROLLER,
|
||||
callback);
|
||||
@ -311,8 +325,7 @@ PresentationRequest::FindOrCreatePresentationConnection(
|
||||
already_AddRefed<Promise>
|
||||
PresentationRequest::GetAvailability(ErrorResult& aRv)
|
||||
{
|
||||
PRES_DEBUG("%s:id[%s]\n", __func__,
|
||||
NS_ConvertUTF16toUTF8(mUrl).get());
|
||||
PRES_DEBUG("%s\n", __func__);
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
@ -331,7 +344,7 @@ PresentationRequest::GetAvailability(ErrorResult& aRv)
|
||||
}
|
||||
|
||||
if (IsProhibitMixedSecurityContexts(doc) &&
|
||||
!IsPrioriAuthenticatedURL(mUrl)) {
|
||||
!IsAllURLAuthenticated()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
@ -363,13 +376,12 @@ PresentationRequest::FindOrCreatePresentationAvailability(RefPtr<Promise>& aProm
|
||||
}
|
||||
|
||||
RefPtr<PresentationAvailability> availability =
|
||||
collection->Find(GetOwner()->WindowID(), mUrl);
|
||||
collection->Find(GetOwner()->WindowID(), mUrls);
|
||||
|
||||
if (!availability) {
|
||||
availability = PresentationAvailability::Create(GetOwner(), mUrl, aPromise);
|
||||
availability = PresentationAvailability::Create(GetOwner(), mUrls, aPromise);
|
||||
} else {
|
||||
PRES_DEBUG(">resolve with same object:id[%s]\n",
|
||||
NS_ConvertUTF16toUTF8(mUrl).get());
|
||||
PRES_DEBUG(">resolve with same object\n");
|
||||
|
||||
// Fetching cached available devices is asynchronous in our implementation,
|
||||
// we need to ensure the promise is resolved in order.
|
||||
@ -474,3 +486,15 @@ PresentationRequest::IsPrioriAuthenticatedURL(const nsAString& aUrl)
|
||||
csm->IsOriginPotentiallyTrustworthy(principal, &isTrustworthyOrigin);
|
||||
return isTrustworthyOrigin;
|
||||
}
|
||||
|
||||
bool
|
||||
PresentationRequest::IsAllURLAuthenticated()
|
||||
{
|
||||
for (const auto& url : mUrls) {
|
||||
if (!IsPrioriAuthenticatedURL(url)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef mozilla_dom_PresentationRequest_h
|
||||
#define mozilla_dom_PresentationRequest_h
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
class nsIDocument;
|
||||
@ -23,9 +24,15 @@ class PresentationRequest final : public DOMEventTargetHelper
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
static already_AddRefed<PresentationRequest> Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aUrl,
|
||||
ErrorResult& aRv);
|
||||
static already_AddRefed<PresentationRequest> Constructor(
|
||||
const GlobalObject& aGlobal,
|
||||
const nsAString& aUrl,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<PresentationRequest> Constructor(
|
||||
const GlobalObject& aGlobal,
|
||||
const Sequence<nsString>& aUrls,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
@ -47,7 +54,7 @@ public:
|
||||
|
||||
private:
|
||||
PresentationRequest(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aUrl);
|
||||
nsTArray<nsString>&& aUrls);
|
||||
|
||||
~PresentationRequest();
|
||||
|
||||
@ -64,7 +71,9 @@ private:
|
||||
// Implement https://w3c.github.io/webappsec-mixed-content/#a-priori-authenticated-url
|
||||
bool IsPrioriAuthenticatedURL(const nsAString& aUrl);
|
||||
|
||||
nsString mUrl;
|
||||
bool IsAllURLAuthenticated();
|
||||
|
||||
nsTArray<nsString> mUrls;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -59,6 +59,44 @@ IsSameDevice(nsIPresentationDevice* aDevice, nsIPresentationDevice* aDeviceAnoth
|
||||
return true;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ConvertURLArrayHelper(const nsTArray<nsString>& aUrls, nsIArray** aResult)
|
||||
{
|
||||
if (!aResult) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
*aResult = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> urls =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
for (const auto& url : aUrls) {
|
||||
nsCOMPtr<nsISupportsString> isupportsString =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = isupportsString->SetData(url);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = urls->AppendElement(isupportsString, false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
urls.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of PresentationDeviceRequest
|
||||
*/
|
||||
@ -69,7 +107,7 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPRESENTATIONDEVICEREQUEST
|
||||
|
||||
PresentationDeviceRequest(const nsAString& aRequestUrl,
|
||||
PresentationDeviceRequest(const nsTArray<nsString>& aUrls,
|
||||
const nsAString& aId,
|
||||
const nsAString& aOrigin,
|
||||
uint64_t aWindowId,
|
||||
@ -77,9 +115,10 @@ public:
|
||||
|
||||
private:
|
||||
virtual ~PresentationDeviceRequest() = default;
|
||||
nsresult CreateSessionInfo(nsIPresentationDevice* aDevice);
|
||||
nsresult CreateSessionInfo(nsIPresentationDevice* aDevice,
|
||||
const nsAString& aSelectedRequestUrl);
|
||||
|
||||
nsString mRequestUrl;
|
||||
nsTArray<nsString> mRequestUrls;
|
||||
nsString mId;
|
||||
nsString mOrigin;
|
||||
uint64_t mWindowId;
|
||||
@ -94,18 +133,18 @@ LazyLogModule gPresentationLog("Presentation");
|
||||
NS_IMPL_ISUPPORTS(PresentationDeviceRequest, nsIPresentationDeviceRequest)
|
||||
|
||||
PresentationDeviceRequest::PresentationDeviceRequest(
|
||||
const nsAString& aRequestUrl,
|
||||
const nsTArray<nsString>& aUrls,
|
||||
const nsAString& aId,
|
||||
const nsAString& aOrigin,
|
||||
uint64_t aWindowId,
|
||||
nsIPresentationServiceCallback* aCallback)
|
||||
: mRequestUrl(aRequestUrl)
|
||||
: mRequestUrls(aUrls)
|
||||
, mId(aId)
|
||||
, mOrigin(aOrigin)
|
||||
, mWindowId(aWindowId)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(!mRequestUrl.IsEmpty());
|
||||
MOZ_ASSERT(!mRequestUrls.IsEmpty());
|
||||
MOZ_ASSERT(!mId.IsEmpty());
|
||||
MOZ_ASSERT(!mOrigin.IsEmpty());
|
||||
MOZ_ASSERT(mCallback);
|
||||
@ -119,29 +158,47 @@ PresentationDeviceRequest::GetOrigin(nsAString& aOrigin)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationDeviceRequest::GetRequestURL(nsAString& aRequestUrl)
|
||||
PresentationDeviceRequest::GetRequestURLs(nsIArray** aUrls)
|
||||
{
|
||||
aRequestUrl = mRequestUrl;
|
||||
return NS_OK;
|
||||
return ConvertURLArrayHelper(mRequestUrls, aUrls);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationDeviceRequest::Select(nsIPresentationDevice* aDevice)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aDevice);
|
||||
|
||||
nsresult rv = CreateSessionInfo(aDevice);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mCallback->NotifyError(rv);
|
||||
return rv;
|
||||
if (NS_WARN_IF(!aDevice)) {
|
||||
MOZ_ASSERT(false, "|aDevice| should noe be null.");
|
||||
mCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return mCallback->NotifySuccess();
|
||||
// Select the most suitable URL for starting the presentation.
|
||||
nsAutoString selectedRequestUrl;
|
||||
for (const auto& url : mRequestUrls) {
|
||||
bool isSupported;
|
||||
if (NS_SUCCEEDED(aDevice->IsRequestedUrlSupported(url, &isSupported)) &&
|
||||
isSupported) {
|
||||
selectedRequestUrl.Assign(url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedRequestUrl.IsEmpty()) {
|
||||
return mCallback->NotifyError(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(CreateSessionInfo(aDevice, selectedRequestUrl)))) {
|
||||
return mCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
|
||||
return mCallback->NotifySuccess(selectedRequestUrl);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresentationDeviceRequest::CreateSessionInfo(nsIPresentationDevice* aDevice)
|
||||
PresentationDeviceRequest::CreateSessionInfo(
|
||||
nsIPresentationDevice* aDevice,
|
||||
const nsAString& aSelectedRequestUrl)
|
||||
{
|
||||
nsCOMPtr<nsIPresentationService> service =
|
||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
||||
@ -152,7 +209,7 @@ PresentationDeviceRequest::CreateSessionInfo(nsIPresentationDevice* aDevice)
|
||||
// Create the controlling session info
|
||||
RefPtr<PresentationSessionInfo> info =
|
||||
static_cast<PresentationService*>(service.get())->
|
||||
CreateControllingSessionInfo(mRequestUrl, mId, mWindowId);
|
||||
CreateControllingSessionInfo(aSelectedRequestUrl, mId, mWindowId);
|
||||
if (NS_WARN_IF(!info)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -572,23 +629,22 @@ PresentationService::IsAppInstalled(nsIURI* aUri)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationService::StartSession(const nsAString& aUrl,
|
||||
PresentationService::StartSession(const nsTArray<nsString>& aUrls,
|
||||
const nsAString& aSessionId,
|
||||
const nsAString& aOrigin,
|
||||
const nsAString& aDeviceId,
|
||||
uint64_t aWindowId,
|
||||
nsIPresentationServiceCallback* aCallback)
|
||||
{
|
||||
PRES_DEBUG("%s:url[%s], id[%s]\n", __func__,
|
||||
NS_ConvertUTF16toUTF8(aUrl).get(),
|
||||
NS_ConvertUTF16toUTF8(aSessionId).get());
|
||||
PRES_DEBUG("%s:id[%s]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get());
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
||||
MOZ_ASSERT(!aUrls.IsEmpty());
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceRequest> request =
|
||||
new PresentationDeviceRequest(aUrl,
|
||||
new PresentationDeviceRequest(aUrls,
|
||||
aSessionId,
|
||||
aOrigin,
|
||||
aWindowId,
|
||||
@ -617,15 +673,11 @@ PresentationService::StartSession(const nsAString& aUrl,
|
||||
return aCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMutableArray> presentationUrls =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (!presentationUrls) {
|
||||
nsCOMPtr<nsIArray> presentationUrls;
|
||||
if (NS_WARN_IF(NS_FAILED(
|
||||
ConvertURLArrayHelper(aUrls, getter_AddRefs(presentationUrls))))) {
|
||||
return aCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
nsCOMPtr<nsISupportsString> supportsStr =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
supportsStr->SetData(aUrl);
|
||||
presentationUrls->AppendElement(supportsStr, false);
|
||||
|
||||
nsCOMPtr<nsIArray> devices;
|
||||
nsresult rv = deviceManager->GetAvailableDevices(presentationUrls, getter_AddRefs(devices));
|
||||
@ -747,18 +799,17 @@ PresentationService::TerminateSession(const nsAString& aSessionId,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationService::ReconnectSession(const nsAString& aUrl,
|
||||
PresentationService::ReconnectSession(const nsTArray<nsString>& aUrls,
|
||||
const nsAString& aSessionId,
|
||||
uint8_t aRole,
|
||||
nsIPresentationServiceCallback* aCallback)
|
||||
{
|
||||
PRES_DEBUG("%s:url[%s], id[%s]\n", __func__,
|
||||
NS_ConvertUTF16toUTF8(aUrl).get(),
|
||||
NS_ConvertUTF16toUTF8(aSessionId).get());
|
||||
PRES_DEBUG("%s:id[%s]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get());
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(!aUrls.IsEmpty());
|
||||
|
||||
if (aRole != nsIPresentationService::ROLE_CONTROLLER) {
|
||||
MOZ_ASSERT(false, "Only controller can call ReconnectSession.");
|
||||
@ -774,7 +825,7 @@ PresentationService::ReconnectSession(const nsAString& aUrl,
|
||||
return aCallback->NotifyError(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!info->GetUrl().Equals(aUrl))) {
|
||||
if (NS_WARN_IF(!aUrls.Contains(info->GetUrl()))) {
|
||||
return aCallback->NotifyError(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
}
|
||||
|
||||
|
@ -806,7 +806,7 @@ PresentationControllingInfo::NotifyReconnected()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mReconnectCallback->NotifySuccess();
|
||||
return mReconnectCallback->NotifySuccess(GetUrl());
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsIPresentationDevice;
|
||||
|
||||
%{C++
|
||||
@ -19,8 +20,8 @@ interface nsIPresentationDeviceRequest : nsISupports
|
||||
// The origin which initiate the request.
|
||||
readonly attribute DOMString origin;
|
||||
|
||||
// The URL to be opened after selection.
|
||||
readonly attribute DOMString requestURL;
|
||||
// The array of candidate URLs.
|
||||
readonly attribute nsIArray requestURLs;
|
||||
|
||||
/*
|
||||
* Callback after selecting a device
|
||||
|
@ -15,15 +15,23 @@ interface nsIPresentationSessionListener;
|
||||
{ 0x9e, 0x4f, 0x40, 0x58, 0xb8, 0x51, 0x98, 0x32 } }
|
||||
#define PRESENTATION_SERVICE_CONTRACTID \
|
||||
"@mozilla.org/presentation/presentationservice;1"
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsString;
|
||||
%}
|
||||
|
||||
[ref] native URLArrayRef(const nsTArray<nsString>);
|
||||
|
||||
[scriptable, uuid(12073206-0065-4b10-9488-a6eb9b23e65b)]
|
||||
interface nsIPresentationServiceCallback : nsISupports
|
||||
{
|
||||
/*
|
||||
* Called when the operation succeeds.
|
||||
*
|
||||
* @param url: the selected request url used to start or reconnect a session.
|
||||
*/
|
||||
void notifySuccess();
|
||||
void notifySuccess(in DOMString url);
|
||||
|
||||
/*
|
||||
* Called when the operation fails.
|
||||
@ -47,7 +55,7 @@ interface nsIPresentationService : nsISupports
|
||||
* Start a new presentation session and display a prompt box which asks users
|
||||
* to select a device.
|
||||
*
|
||||
* @param url: The url of presenting page.
|
||||
* @param urls: The candidate Urls of presenting page. Only one url would be used.
|
||||
* @param sessionId: An ID to identify presentation session.
|
||||
* @param origin: The url of requesting page.
|
||||
* @param deviceId: The specified device of handling this request, null string
|
||||
@ -61,12 +69,12 @@ interface nsIPresentationService : nsISupports
|
||||
* established successfully with the selected device.
|
||||
* Otherwise, NotifyError() is called with a error message.
|
||||
*/
|
||||
void startSession(in DOMString url,
|
||||
in DOMString sessionId,
|
||||
in DOMString origin,
|
||||
in DOMString deviceId,
|
||||
in unsigned long long windowId,
|
||||
in nsIPresentationServiceCallback callback);
|
||||
[noscript] void startSession(in URLArrayRef urls,
|
||||
in DOMString sessionId,
|
||||
in DOMString origin,
|
||||
in DOMString deviceId,
|
||||
in unsigned long long windowId,
|
||||
in nsIPresentationServiceCallback callback);
|
||||
|
||||
/*
|
||||
* Send the message to the session.
|
||||
@ -101,17 +109,17 @@ interface nsIPresentationService : nsISupports
|
||||
/*
|
||||
* Reconnect the session.
|
||||
*
|
||||
* @param url: The url of presenting page.
|
||||
* @param url: The request Urls.
|
||||
* @param sessionId: An ID to identify presentation session.
|
||||
* @param role: Identify the function called by controller or receiver.
|
||||
* @param callback: NotifySuccess() is called when a control channel
|
||||
* is opened successfully.
|
||||
* Otherwise, NotifyError() is called with a error message.
|
||||
*/
|
||||
void reconnectSession(in DOMString url,
|
||||
in DOMString sessionId,
|
||||
in uint8_t role,
|
||||
in nsIPresentationServiceCallback callback);
|
||||
[noscript] void reconnectSession(in URLArrayRef urls,
|
||||
in DOMString sessionId,
|
||||
in uint8_t role,
|
||||
in nsIPresentationServiceCallback callback);
|
||||
|
||||
/*
|
||||
* Register an availability listener. Must be called from the main thread.
|
||||
|
@ -15,7 +15,7 @@ namespace dom {
|
||||
|
||||
struct StartSessionRequest
|
||||
{
|
||||
nsString url;
|
||||
nsString[] urls;
|
||||
nsString sessionId;
|
||||
nsString origin;
|
||||
nsString deviceId;
|
||||
@ -44,7 +44,7 @@ struct TerminateSessionRequest
|
||||
|
||||
struct ReconnectSessionRequest
|
||||
{
|
||||
nsString url;
|
||||
nsString[] urls;
|
||||
nsString sessionId;
|
||||
uint8_t role;
|
||||
};
|
||||
|
@ -15,6 +15,7 @@ sync protocol PPresentationRequest
|
||||
|
||||
child:
|
||||
async __delete__(nsresult result);
|
||||
async NotifyRequestUrlSelected(nsString aUrl);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -163,12 +163,17 @@ PresentationRequestChild::Recv__delete__(const nsresult& aResult)
|
||||
}
|
||||
|
||||
if (mCallback) {
|
||||
if (NS_SUCCEEDED(aResult)) {
|
||||
NS_WARN_IF(NS_FAILED(mCallback->NotifySuccess()));
|
||||
} else {
|
||||
if (NS_FAILED(aResult)) {
|
||||
NS_WARN_IF(NS_FAILED(mCallback->NotifyError(aResult)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PresentationRequestChild::RecvNotifyRequestUrlSelected(const nsString& aUrl)
|
||||
{
|
||||
NS_WARN_IF(NS_FAILED(mCallback->NotifySuccess(aUrl)));
|
||||
return true;
|
||||
}
|
||||
|
@ -78,6 +78,9 @@ public:
|
||||
virtual bool
|
||||
Recv__delete__(const nsresult& aResult) override;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyRequestUrlSelected(const nsString& aUrl) override;
|
||||
|
||||
private:
|
||||
virtual ~PresentationRequestChild();
|
||||
|
||||
|
@ -52,7 +52,7 @@ PresentationIPCService::~PresentationIPCService()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationIPCService::StartSession(const nsAString& aUrl,
|
||||
PresentationIPCService::StartSession(const nsTArray<nsString>& aUrls,
|
||||
const nsAString& aSessionId,
|
||||
const nsAString& aOrigin,
|
||||
const nsAString& aDeviceId,
|
||||
@ -65,7 +65,7 @@ PresentationIPCService::StartSession(const nsAString& aUrl,
|
||||
nsIPresentationService::ROLE_CONTROLLER);
|
||||
}
|
||||
|
||||
return SendRequest(aCallback, StartSessionRequest(nsString(aUrl),
|
||||
return SendRequest(aCallback, StartSessionRequest(aUrls,
|
||||
nsString(aSessionId),
|
||||
nsString(aOrigin),
|
||||
nsString(aDeviceId),
|
||||
@ -135,7 +135,7 @@ PresentationIPCService::TerminateSession(const nsAString& aSessionId,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationIPCService::ReconnectSession(const nsAString& aUrl,
|
||||
PresentationIPCService::ReconnectSession(const nsTArray<nsString>& aUrls,
|
||||
const nsAString& aSessionId,
|
||||
uint8_t aRole,
|
||||
nsIPresentationServiceCallback* aCallback)
|
||||
@ -147,7 +147,7 @@ PresentationIPCService::ReconnectSession(const nsAString& aUrl,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return SendRequest(aCallback, ReconnectSessionRequest(nsString(aUrl),
|
||||
return SendRequest(aCallback, ReconnectSessionRequest(aUrls,
|
||||
nsString(aSessionId),
|
||||
aRole));
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "DCPresentationChannelDescription.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIPresentationDeviceManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "PresentationBuilderParent.h"
|
||||
@ -333,7 +334,7 @@ PresentationRequestParent::DoRequest(const StartSessionRequest& aRequest)
|
||||
MOZ_ASSERT(mService);
|
||||
mNeedRegisterBuilder = true;
|
||||
mSessionId = aRequest.sessionId();
|
||||
return mService->StartSession(aRequest.url(), aRequest.sessionId(),
|
||||
return mService->StartSession(aRequest.urls(), aRequest.sessionId(),
|
||||
aRequest.origin(), aRequest.deviceId(),
|
||||
aRequest.windowId(), this);
|
||||
}
|
||||
@ -347,16 +348,16 @@ PresentationRequestParent::DoRequest(const SendSessionMessageRequest& aRequest)
|
||||
// compromised child process can't fake the ID.
|
||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
||||
return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
nsresult rv = mService->SendSessionMessage(aRequest.sessionId(),
|
||||
aRequest.role(),
|
||||
aRequest.data());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NotifyError(rv);
|
||||
return SendResponse(rv);
|
||||
}
|
||||
return NotifySuccess();
|
||||
return SendResponse(NS_OK);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -368,16 +369,16 @@ PresentationRequestParent::DoRequest(const CloseSessionRequest& aRequest)
|
||||
// compromised child process can't fake the ID.
|
||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
||||
return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
nsresult rv = mService->CloseSession(aRequest.sessionId(),
|
||||
aRequest.role(),
|
||||
aRequest.closedReason());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NotifyError(rv);
|
||||
return SendResponse(rv);
|
||||
}
|
||||
return NotifySuccess();
|
||||
return SendResponse(NS_OK);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -389,14 +390,14 @@ PresentationRequestParent::DoRequest(const TerminateSessionRequest& aRequest)
|
||||
// compromised child process can't fake the ID.
|
||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
||||
return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
nsresult rv = mService->TerminateSession(aRequest.sessionId(), aRequest.role());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NotifyError(rv);
|
||||
return SendResponse(rv);
|
||||
}
|
||||
return NotifySuccess();
|
||||
return SendResponse(NS_OK);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -411,12 +412,12 @@ PresentationRequestParent::DoRequest(const ReconnectSessionRequest& aRequest)
|
||||
|
||||
// NOTE: Return NS_ERROR_DOM_NOT_FOUND_ERR here to match the spec.
|
||||
// https://w3c.github.io/presentation-api/#reconnecting-to-a-presentation
|
||||
return NotifyError(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return SendResponse(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
}
|
||||
|
||||
mNeedRegisterBuilder = true;
|
||||
mSessionId = aRequest.sessionId();
|
||||
return mService->ReconnectSession(aRequest.url(),
|
||||
return mService->ReconnectSession(aRequest.urls(),
|
||||
aRequest.sessionId(),
|
||||
aRequest.role(),
|
||||
this);
|
||||
@ -431,18 +432,18 @@ PresentationRequestParent::DoRequest(const BuildTransportRequest& aRequest)
|
||||
// compromised child process can't fake the ID.
|
||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
||||
return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
nsresult rv = mService->BuildTransport(aRequest.sessionId(), aRequest.role());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NotifyError(rv);
|
||||
return SendResponse(rv);
|
||||
}
|
||||
return NotifySuccess();
|
||||
return SendResponse(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationRequestParent::NotifySuccess()
|
||||
PresentationRequestParent::NotifySuccess(const nsAString& aUrl)
|
||||
{
|
||||
if (mNeedRegisterBuilder) {
|
||||
RefPtr<PresentationParent> parent = static_cast<PresentationParent*>(Manager());
|
||||
@ -451,6 +452,7 @@ PresentationRequestParent::NotifySuccess()
|
||||
nsIPresentationService::ROLE_CONTROLLER));
|
||||
}
|
||||
|
||||
Unused << SendNotifyRequestUrlSelected(nsString(aUrl));
|
||||
return SendResponse(NS_OK);
|
||||
}
|
||||
|
||||
|
@ -238,6 +238,29 @@ function teardown() {
|
||||
gScript.sendAsyncMessage('teardown');
|
||||
}
|
||||
|
||||
function testConstructRequestError() {
|
||||
return Promise.all([
|
||||
new Promise(function(aResolve, aReject) {
|
||||
try {
|
||||
request = new PresentationRequest("\\\\\\");
|
||||
}
|
||||
catch(e) {
|
||||
is(e.name, "SyntaxError", "Expect to get SyntaxError.");
|
||||
aResolve();
|
||||
}
|
||||
}),
|
||||
new Promise(function(aResolve, aReject) {
|
||||
try {
|
||||
request = new PresentationRequest([]);
|
||||
}
|
||||
catch(e) {
|
||||
is(e.name, "NotSupportedError", "Expect to get NotSupportedError.");
|
||||
aResolve();
|
||||
}
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
ok(window.PresentationRequest, "PresentationRequest should be available.");
|
||||
|
||||
@ -248,6 +271,7 @@ function runTests() {
|
||||
then(testCloseConnection).
|
||||
then(testReconnect).
|
||||
then(testCloseConnection).
|
||||
then(testConstructRequestError).
|
||||
then(teardown);
|
||||
}
|
||||
|
||||
|
@ -41,17 +41,6 @@ function setup() {
|
||||
});
|
||||
}
|
||||
|
||||
function testCreateRequestWithEmptyURL() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
try {
|
||||
request = new PresentationRequest("");
|
||||
} catch (aError) {
|
||||
is(aError.name, "SyntaxError", "SyntaxError is expected when using an empty URL.");
|
||||
aResolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testStartConnectionCancelPrompt() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
|
||||
@ -380,8 +369,7 @@ function teardown() {
|
||||
function runTests() {
|
||||
ok(window.PresentationRequest, "PresentationRequest should be available.");
|
||||
|
||||
testCreateRequestWithEmptyURL().
|
||||
then(setup).
|
||||
setup().
|
||||
then(testStartConnectionCancelPrompt).
|
||||
then(testStartConnectionNoDevice).
|
||||
then(testStartConnectionUnexpectedControlChannelCloseBeforeDataTransportInit).
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
[Constructor(DOMString url),
|
||||
Constructor(sequence<DOMString> urls),
|
||||
Pref="dom.presentation.controller.enabled"]
|
||||
interface PresentationRequest : EventTarget {
|
||||
/*
|
||||
|
@ -481,28 +481,28 @@ CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName,
|
||||
nsAutoPrinter autoPrinter(hPrinter);
|
||||
|
||||
// Get the buffer size
|
||||
DWORD dwNeeded = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr,
|
||||
nullptr, 0);
|
||||
if (dwNeeded == 0) {
|
||||
LONG needed = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr,
|
||||
nullptr, 0);
|
||||
if (needed < 0) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
// Allocate a buffer of the correct size.
|
||||
nsAutoDevMode newDevMode((LPDEVMODEW)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
dwNeeded));
|
||||
needed));
|
||||
if (!newDevMode) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
nsHGLOBAL hDevMode = ::GlobalAlloc(GHND, dwNeeded);
|
||||
nsHGLOBAL hDevMode = ::GlobalAlloc(GHND, needed);
|
||||
nsAutoGlobalMem globalDevMode(hDevMode);
|
||||
if (!hDevMode) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
DWORD dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, newDevMode,
|
||||
nullptr, DM_OUT_BUFFER);
|
||||
if (dwRet != IDOK) {
|
||||
LONG ret = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, newDevMode,
|
||||
nullptr, DM_OUT_BUFFER);
|
||||
if (ret != IDOK) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
@ -513,16 +513,16 @@ CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName,
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
memcpy(devMode, newDevMode.get(), dwNeeded);
|
||||
memcpy(devMode, newDevMode.get(), needed);
|
||||
// Initialize values from the PrintSettings
|
||||
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
|
||||
MOZ_ASSERT(psWin);
|
||||
psWin->CopyToNative(devMode);
|
||||
|
||||
// Sets back the changes we made to the DevMode into the Printer Driver
|
||||
dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode,
|
||||
DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
if (dwRet != IDOK) {
|
||||
ret = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode,
|
||||
DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
if (ret != IDOK) {
|
||||
::GlobalUnlock(hDevMode);
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
@ -1016,7 +1016,12 @@ gfxFontUtils::RenameFont(const nsAString& aName, const uint8_t *aFontData,
|
||||
uint16_t nameCount = ArrayLength(neededNameIDs);
|
||||
|
||||
// leave room for null-terminator
|
||||
uint16_t nameStrLength = (aName.Length() + 1) * sizeof(char16_t);
|
||||
uint32_t nameStrLength = (aName.Length() + 1) * sizeof(char16_t);
|
||||
if (nameStrLength > 65535) {
|
||||
// The name length _in bytes_ must fit in an unsigned short field;
|
||||
// therefore, a name longer than this cannot be used.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// round name table size up to 4-byte multiple
|
||||
uint32_t nameTableSize = (sizeof(NameHeader) +
|
||||
|
@ -2515,17 +2515,18 @@ gfxPlatform::InitOpenGLConfig()
|
||||
openGLFeature.EnableByDefault();
|
||||
#endif
|
||||
|
||||
// When layers acceleration is force-enabled, enable it even for blacklisted
|
||||
// devices.
|
||||
if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
|
||||
openGLFeature.UserForceEnable("Force-enabled by pref");
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString message;
|
||||
nsCString failureId;
|
||||
if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &message, failureId)) {
|
||||
openGLFeature.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
|
||||
}
|
||||
|
||||
// Ensure that an accelerated compositor backend is available when layers
|
||||
// acceleration is force-enabled.
|
||||
if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
|
||||
openGLFeature.UserForceEnable("Force-enabled by pref");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -111,10 +111,19 @@ typedef enum nsCharType nsCharType;
|
||||
* Return false, otherwise
|
||||
*/
|
||||
#define LRM_CHAR 0x200e
|
||||
#define RLM_CHAR 0x200f
|
||||
|
||||
#define LRE_CHAR 0x202a
|
||||
#define RLE_CHAR 0x202b
|
||||
#define PDF_CHAR 0x202c
|
||||
#define LRO_CHAR 0x202d
|
||||
#define RLO_CHAR 0x202e
|
||||
|
||||
#define LRI_CHAR 0x2066
|
||||
#define RLI_CHAR 0x2067
|
||||
#define FSI_CHAR 0x2068
|
||||
#define PDI_CHAR 0x2069
|
||||
|
||||
#define ALM_CHAR 0x061C
|
||||
inline bool IsBidiControl(uint32_t aChar) {
|
||||
return ((LRE_CHAR <= aChar && aChar <= RLO_CHAR) ||
|
||||
@ -123,6 +132,20 @@ typedef enum nsCharType nsCharType;
|
||||
(aChar & 0xfffffe) == LRM_CHAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a UTF-32 codepoint
|
||||
* Return true if the codepoint is a Bidi control character that may result
|
||||
* in RTL directionality and therefore needs to trigger bidi resolution;
|
||||
* return false otherwise.
|
||||
*/
|
||||
inline bool IsBidiControlRTL(uint32_t aChar) {
|
||||
return aChar == RLM_CHAR ||
|
||||
aChar == RLE_CHAR ||
|
||||
aChar == RLO_CHAR ||
|
||||
aChar == RLI_CHAR ||
|
||||
aChar == ALM_CHAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give an nsString.
|
||||
* @return true if the string contains right-to-left characters
|
||||
|
@ -54,24 +54,6 @@ namespace {
|
||||
|
||||
static const char kDefaultRuntimeScriptFilename[] = "xpcshell.js";
|
||||
|
||||
class XPCShellDirProvider : public nsIDirectoryServiceProvider
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDIRECTORYSERVICEPROVIDER
|
||||
|
||||
XPCShellDirProvider() { }
|
||||
~XPCShellDirProvider() { }
|
||||
|
||||
bool SetGREDirs(const char *dir);
|
||||
void ClearGREDirs() { mGREDir = nullptr;
|
||||
mGREBinDir = nullptr; }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIFile> mGREDir;
|
||||
nsCOMPtr<nsIFile> mGREBinDir;
|
||||
};
|
||||
|
||||
inline XPCShellEnvironment*
|
||||
Environment(Handle<JSObject*> global)
|
||||
{
|
||||
@ -389,51 +371,6 @@ XPCShellEnvironment::ProcessFile(JSContext *cx,
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(MozExternalRefCountType)
|
||||
XPCShellDirProvider::AddRef()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(MozExternalRefCountType)
|
||||
XPCShellDirProvider::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE(XPCShellDirProvider, nsIDirectoryServiceProvider)
|
||||
|
||||
bool
|
||||
XPCShellDirProvider::SetGREDirs(const char *dir)
|
||||
{
|
||||
nsresult rv = XRE_GetFileFromPath(dir, getter_AddRefs(mGREDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mGREDir->Clone(getter_AddRefs(mGREBinDir));
|
||||
#ifdef XP_MACOSX
|
||||
mGREBinDir->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
|
||||
#endif
|
||||
}
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XPCShellDirProvider::GetFile(const char *prop,
|
||||
bool *persistent,
|
||||
nsIFile* *result)
|
||||
{
|
||||
if (mGREDir && !strcmp(prop, NS_GRE_DIR)) {
|
||||
*persistent = true;
|
||||
NS_ADDREF(*result = mGREDir);
|
||||
return NS_OK;
|
||||
} else if (mGREBinDir && !strcmp(prop, NS_GRE_BIN_DIR)) {
|
||||
*persistent = true;
|
||||
NS_ADDREF(*result = mGREBinDir);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// static
|
||||
XPCShellEnvironment*
|
||||
XPCShellEnvironment::CreateEnvironment()
|
||||
|
@ -169,9 +169,13 @@ FulfillMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj, HandleValue v
|
||||
RootedValue value(cx, value_);
|
||||
|
||||
mozilla::Maybe<AutoCompartment> ac;
|
||||
if (!IsWrapper(promiseObj)) {
|
||||
if (!IsProxy(promiseObj)) {
|
||||
promise = &promiseObj->as<PromiseObject>();
|
||||
} else {
|
||||
if (JS_IsDeadWrapper(promiseObj)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
promise = &UncheckedUnwrap(promiseObj)->as<PromiseObject>();
|
||||
ac.emplace(cx, promise);
|
||||
if (!promise->compartment()->wrap(cx, &value))
|
||||
@ -190,9 +194,13 @@ RejectMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj, HandleValue re
|
||||
RootedValue reason(cx, reason_);
|
||||
|
||||
mozilla::Maybe<AutoCompartment> ac;
|
||||
if (!IsWrapper(promiseObj)) {
|
||||
if (!IsProxy(promiseObj)) {
|
||||
promise = &promiseObj->as<PromiseObject>();
|
||||
} else {
|
||||
if (JS_IsDeadWrapper(promiseObj)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
promise = &UncheckedUnwrap(promiseObj)->as<PromiseObject>();
|
||||
ac.emplace(cx, promise);
|
||||
|
||||
|
@ -4559,12 +4559,6 @@ Parser<SyntaxParseHandler>::importDeclaration()
|
||||
return SyntaxParseHandler::NodeFailure;
|
||||
}
|
||||
|
||||
template <>
|
||||
ParseNode*
|
||||
Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
ClassContext classContext,
|
||||
DefaultHandling defaultHandling);
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedName(JSAtom* exportName)
|
||||
@ -6191,11 +6185,11 @@ GeneratorKindFromPropertyType(PropertyType propType)
|
||||
return propType == PropertyType::GeneratorMethod ? StarGenerator : NotGenerator;
|
||||
}
|
||||
|
||||
template <>
|
||||
ParseNode*
|
||||
Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
ClassContext classContext,
|
||||
DefaultHandling defaultHandling)
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
ClassContext classContext,
|
||||
DefaultHandling defaultHandling)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS));
|
||||
|
||||
@ -6250,7 +6244,7 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
// in order to provide it for the nodes created later.
|
||||
TokenPos namePos = pos();
|
||||
|
||||
ParseNode* classHeritage = null();
|
||||
Node classHeritage = null();
|
||||
bool hasHeritage;
|
||||
if (!tokenStream.matchToken(&hasHeritage, TOK_EXTENDS))
|
||||
return null();
|
||||
@ -6264,7 +6258,7 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CLASS);
|
||||
|
||||
ParseNode* classMethods = handler.newClassMethodList(pos().begin);
|
||||
Node classMethods = handler.newClassMethodList(pos().begin);
|
||||
if (!classMethods)
|
||||
return null();
|
||||
|
||||
@ -6304,7 +6298,7 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
}
|
||||
|
||||
PropertyType propType;
|
||||
ParseNode* propName = propertyName(yieldHandling, classMethods, &propType, &propAtom);
|
||||
Node propName = propertyName(yieldHandling, classMethods, &propType, &propAtom);
|
||||
if (!propName)
|
||||
return null();
|
||||
|
||||
@ -6356,7 +6350,7 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
if (!tokenStream.isCurrentTokenType(TOK_RB))
|
||||
funName = propAtom;
|
||||
}
|
||||
ParseNode* fn = methodDefinition(yieldHandling, propType, funName);
|
||||
Node fn = methodDefinition(yieldHandling, propType, funName);
|
||||
if (!fn)
|
||||
return null();
|
||||
|
||||
@ -6365,18 +6359,18 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
return null();
|
||||
}
|
||||
|
||||
ParseNode* nameNode = null();
|
||||
ParseNode* methodsOrBlock = classMethods;
|
||||
Node nameNode = null();
|
||||
Node methodsOrBlock = classMethods;
|
||||
if (name) {
|
||||
// The inner name is immutable.
|
||||
if (!noteDeclaredName(name, DeclarationKind::Const, namePos))
|
||||
return null();
|
||||
|
||||
ParseNode* innerName = newName(name, namePos);
|
||||
Node innerName = newName(name, namePos);
|
||||
if (!innerName)
|
||||
return null();
|
||||
|
||||
ParseNode* classBlock = finishLexicalScope(*classScope, classMethods);
|
||||
Node classBlock = finishLexicalScope(*classScope, classMethods);
|
||||
if (!classBlock)
|
||||
return null();
|
||||
|
||||
@ -6386,7 +6380,7 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
classScope.reset();
|
||||
classStmt.reset();
|
||||
|
||||
ParseNode* outerName = null();
|
||||
Node outerName = null();
|
||||
if (classContext == ClassStatement) {
|
||||
// The outer name is mutable.
|
||||
if (!noteDeclaredName(name, DeclarationKind::Let, namePos))
|
||||
@ -6407,16 +6401,6 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
return handler.newClass(nameNode, classHeritage, methodsOrBlock);
|
||||
}
|
||||
|
||||
template <>
|
||||
SyntaxParseHandler::Node
|
||||
Parser<SyntaxParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
ClassContext classContext,
|
||||
DefaultHandling defaultHandling)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return SyntaxParseHandler::NodeFailure;
|
||||
}
|
||||
|
||||
template <class ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::nextTokenContinuesLetDeclaration(TokenKind next, YieldHandling yieldHandling)
|
||||
@ -6851,8 +6835,6 @@ Parser<ParseHandler>::statementListItem(YieldHandling yieldHandling,
|
||||
|
||||
// ClassDeclaration[?Yield, ~Default]
|
||||
case TOK_CLASS:
|
||||
if (!abortIfSyntaxParser())
|
||||
return null();
|
||||
return classDefinition(yieldHandling, ClassStatement, NameRequired);
|
||||
|
||||
// LexicalDeclaration[In, ?Yield]
|
||||
|
@ -262,6 +262,8 @@ class SyntaxParseHandler
|
||||
|
||||
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newClass(Node name, Node heritage, Node methodBlock) { return NodeGeneric; }
|
||||
|
||||
Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
|
||||
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
39
js/xpconnect/tests/unit/test_resolve_dead_promise.js
Normal file
39
js/xpconnect/tests/unit/test_resolve_dead_promise.js
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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/. */
|
||||
|
||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=1298597 */
|
||||
|
||||
function run_test()
|
||||
{
|
||||
var sb = Components.utils.Sandbox("http://www.blah.com");
|
||||
var resolveFun;
|
||||
var p1 = new sb.Promise((res, rej) => {resolveFun = res});
|
||||
var rejectFun;
|
||||
var p2 = new sb.Promise((res, rej) => {rejectFun = rej});
|
||||
Components.utils.nukeSandbox(sb);
|
||||
do_check_true(Components.utils.isDeadWrapper(sb), "sb should be dead");
|
||||
do_check_true(Components.utils.isDeadWrapper(p1), "p1 should be dead");
|
||||
do_check_true(Components.utils.isDeadWrapper(p2), "p2 should be dead");
|
||||
|
||||
var exception;
|
||||
|
||||
try{
|
||||
resolveFun(1);
|
||||
do_check_true(false);
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
do_check_true(exception.toString().includes("can't access dead object"),
|
||||
"Resolving dead wrapped promise should throw");
|
||||
|
||||
exception = undefined;
|
||||
try{
|
||||
rejectFun(1);
|
||||
do_check_true(false);
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
do_check_true(exception.toString().includes("can't access dead object"),
|
||||
"Rejecting dead wrapped promise should throw");
|
||||
}
|
@ -133,3 +133,4 @@ head = head_watchdog.js
|
||||
[test_xrayed_iterator.js]
|
||||
[test_xray_SavedFrame.js]
|
||||
[test_xray_SavedFrame-02.js]
|
||||
[test_resolve_dead_promise.js]
|
||||
|
@ -46,17 +46,12 @@ PresentationDevicePrompt.prototype = {
|
||||
return this.bundle.GetStringFromName(aName);
|
||||
},
|
||||
|
||||
_loadDevices: function(requestURL) {
|
||||
_loadDevices: function(requestURLs) {
|
||||
debug("_loadDevices");
|
||||
|
||||
let presentationUrls = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
let url = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
url.data = requestURL;
|
||||
presentationUrls.appendElement(url, false);
|
||||
|
||||
let deviceManager = Cc["@mozilla.org/presentation-device/manager;1"]
|
||||
.getService(Ci.nsIPresentationDeviceManager);
|
||||
let devices = deviceManager.getAvailableDevices(presentationUrls).QueryInterface(Ci.nsIArray);
|
||||
let devices = deviceManager.getAvailableDevices(requestURLs).QueryInterface(Ci.nsIArray);
|
||||
|
||||
// Re-load the available devices
|
||||
this._devices = [];
|
||||
@ -118,7 +113,7 @@ PresentationDevicePrompt.prototype = {
|
||||
debug("promptDeviceSelection");
|
||||
|
||||
// Load available presentation devices into this._devices
|
||||
this._loadDevices(aRequest.requestURL);
|
||||
this._loadDevices(aRequest.requestURLs);
|
||||
|
||||
if (!this._devices.length) { // Cancel request if no available device
|
||||
aRequest.cancel(Cr.NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
|
@ -284,9 +284,7 @@ NetAddrElement::~NetAddrElement()
|
||||
|
||||
AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo,
|
||||
bool disableIPv4, bool filterNameCollision, const char *cname)
|
||||
: mHostName(nullptr)
|
||||
, mCanonicalName(nullptr)
|
||||
, ttl(NO_TTL_DATA)
|
||||
: ttl(NO_TTL_DATA)
|
||||
{
|
||||
MOZ_ASSERT(prAddrInfo, "Cannot construct AddrInfo with a null prAddrInfo pointer!");
|
||||
const uint32_t nameCollisionAddr = htonl(0x7f003535); // 127.0.53.53
|
||||
@ -307,9 +305,7 @@ AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo,
|
||||
}
|
||||
|
||||
AddrInfo::AddrInfo(const char *host, const char *cname)
|
||||
: mHostName(nullptr)
|
||||
, mCanonicalName(nullptr)
|
||||
, ttl(NO_TTL_DATA)
|
||||
: ttl(NO_TTL_DATA)
|
||||
{
|
||||
Init(host, cname);
|
||||
}
|
||||
@ -320,8 +316,6 @@ AddrInfo::~AddrInfo()
|
||||
while ((addrElement = mAddresses.popLast())) {
|
||||
delete addrElement;
|
||||
}
|
||||
free(mHostName);
|
||||
free(mCanonicalName);
|
||||
}
|
||||
|
||||
void
|
||||
@ -331,15 +325,13 @@ AddrInfo::Init(const char *host, const char *cname)
|
||||
|
||||
ttl = NO_TTL_DATA;
|
||||
size_t hostlen = strlen(host);
|
||||
mHostName = static_cast<char*>(moz_xmalloc(hostlen + 1));
|
||||
memcpy(mHostName, host, hostlen + 1);
|
||||
mHostName = mozilla::MakeUnique<char[]>(hostlen + 1);
|
||||
memcpy(mHostName.get(), host, hostlen + 1);
|
||||
|
||||
if (cname) {
|
||||
size_t cnameLen = strlen(cname);
|
||||
mCanonicalName = static_cast<char*>(moz_xmalloc(cnameLen + 1));
|
||||
memcpy(mCanonicalName, cname, cnameLen + 1);
|
||||
}
|
||||
else {
|
||||
mCanonicalName = nullptr;
|
||||
mCanonicalName = mozilla::MakeUnique<char[]>(cnameLen + 1);
|
||||
memcpy(mCanonicalName.get(), cname, cnameLen + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,8 +347,8 @@ size_t
|
||||
AddrInfo::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += mallocSizeOf(mHostName);
|
||||
n += mallocSizeOf(mCanonicalName);
|
||||
n += mallocSizeOf(mHostName.get());
|
||||
n += mallocSizeOf(mCanonicalName.get());
|
||||
n += mAddresses.sizeOfExcludingThis(mallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "plstr.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#if !defined(XP_WIN)
|
||||
#include <arpa/inet.h>
|
||||
@ -141,8 +142,8 @@ public:
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
char *mHostName;
|
||||
char *mCanonicalName;
|
||||
UniquePtr<char[]> mHostName;
|
||||
UniquePtr<char[]> mCanonicalName;
|
||||
uint16_t ttl;
|
||||
static const uint16_t NO_TTL_DATA = (uint16_t) -1;
|
||||
|
||||
|
@ -345,7 +345,7 @@ GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags,
|
||||
// we have.
|
||||
const char *name = nullptr;
|
||||
if (*aAddrInfo != nullptr && (*aAddrInfo)->mCanonicalName) {
|
||||
name = (*aAddrInfo)->mCanonicalName;
|
||||
name = (*aAddrInfo)->mCanonicalName.get();
|
||||
} else {
|
||||
name = aHost;
|
||||
}
|
||||
|
@ -93,9 +93,9 @@ nsDNSRecord::GetCanonicalName(nsACString &result)
|
||||
{
|
||||
MutexAutoLock lock(mHostRecord->addr_info_lock);
|
||||
if (mHostRecord->addr_info)
|
||||
cname = mHostRecord->addr_info->mCanonicalName ?
|
||||
mHostRecord->addr_info->mCanonicalName :
|
||||
mHostRecord->addr_info->mHostName;
|
||||
cname = !mHostRecord->addr_info->mCanonicalName.get() ?
|
||||
mHostRecord->addr_info->mCanonicalName.get() :
|
||||
mHostRecord->addr_info->mHostName.get();
|
||||
else
|
||||
cname = mHostRecord->host;
|
||||
result.Assign(cname);
|
||||
@ -156,7 +156,7 @@ nsDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
|
||||
// attempt to reresolve it failed.
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
|
||||
memcpy(addr, mHostRecord->addr.get(), sizeof(NetAddr));
|
||||
mDone = true;
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ nsDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
NetAddr *addr = aAddressArray.AppendElement(NetAddr());
|
||||
memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
|
||||
memcpy(addr, mHostRecord->addr.get(), sizeof(NetAddr));
|
||||
if (addr->raw.family == AF_INET) {
|
||||
addr->inet.port = 0;
|
||||
} else if (addr->raw.family == AF_INET6) {
|
||||
|
@ -164,8 +164,6 @@ IsLowPriority(uint16_t flags)
|
||||
nsHostRecord::nsHostRecord(const nsHostKey *key)
|
||||
: addr_info_lock("nsHostRecord.addr_info_lock")
|
||||
, addr_info_gencnt(0)
|
||||
, addr_info(nullptr)
|
||||
, addr(nullptr)
|
||||
, negative(false)
|
||||
, resolving(false)
|
||||
, onQueue(false)
|
||||
@ -226,8 +224,6 @@ nsHostRecord::CopyExpirationTimesAndFlagsFrom(const nsHostRecord *aFromHostRecor
|
||||
nsHostRecord::~nsHostRecord()
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mBlacklistedCount);
|
||||
delete addr_info;
|
||||
delete addr;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -317,7 +313,7 @@ nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now, uint16_t queryFlags
|
||||
return false;
|
||||
}
|
||||
|
||||
return addr_info || addr || negative;
|
||||
return addr_info.get() || addr.get() || negative;
|
||||
}
|
||||
|
||||
static size_t
|
||||
@ -347,7 +343,7 @@ nsHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
|
||||
|
||||
n += SizeOfResolveHostCallbackListExcludingHead(&callbacks, mallocSizeOf);
|
||||
n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
|
||||
n += mallocSizeOf(addr);
|
||||
n += mallocSizeOf(addr.get());
|
||||
|
||||
n += mBlacklistedItems.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
for (size_t i = 0; i < mBlacklistedItems.Length(); i++) {
|
||||
@ -807,8 +803,8 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
LOG((" Host is IP Literal [%s].\n", host));
|
||||
// ok, just copy the result into the host record, and be done
|
||||
// with it! ;-)
|
||||
he->rec->addr = new NetAddr();
|
||||
PRNetAddrToNetAddr(&tempAddr, he->rec->addr);
|
||||
he->rec->addr.reset(new NetAddr());
|
||||
PRNetAddrToNetAddr(&tempAddr, he->rec->addr.get());
|
||||
// put reference to host record on stack...
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_LITERAL);
|
||||
@ -870,9 +866,9 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
if ((af == addrIter->mAddress.inet.family) &&
|
||||
!unspecHe->rec->Blacklisted(&addrIter->mAddress)) {
|
||||
if (!he->rec->addr_info) {
|
||||
he->rec->addr_info = new AddrInfo(
|
||||
unspecHe->rec->addr_info->mHostName,
|
||||
unspecHe->rec->addr_info->mCanonicalName);
|
||||
he->rec->addr_info.reset(new AddrInfo(
|
||||
unspecHe->rec->addr_info->mHostName.get(),
|
||||
unspecHe->rec->addr_info->mCanonicalName.get()));
|
||||
he->rec->CopyExpirationTimesAndFlagsFrom(unspecHe->rec);
|
||||
}
|
||||
he->rec->addr_info->AddAddress(
|
||||
@ -1222,7 +1218,7 @@ different_rrset(AddrInfo *rrset1, AddrInfo *rrset2)
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG(("different_rrset %s\n", rrset1->mHostName));
|
||||
LOG(("different_rrset %s\n", rrset1->mHostName.get()));
|
||||
nsTArray<NetAddr> orderedSet1;
|
||||
nsTArray<NetAddr> orderedSet2;
|
||||
|
||||
@ -1289,27 +1285,24 @@ nsHostResolver::OnLookupComplete(nsHostRecord* rec, nsresult status, AddrInfo* n
|
||||
|
||||
// update record fields. We might have a rec->addr_info already if a
|
||||
// previous lookup result expired and we're reresolving it..
|
||||
AddrInfo *old_addr_info;
|
||||
{
|
||||
MutexAutoLock lock(rec->addr_info_lock);
|
||||
if (different_rrset(rec->addr_info, newRRSet)) {
|
||||
if (different_rrset(rec->addr_info.get(), newRRSet)) {
|
||||
LOG(("nsHostResolver record %p new gencnt\n", rec));
|
||||
old_addr_info = rec->addr_info;
|
||||
rec->addr_info = newRRSet;
|
||||
rec->addr_info.reset(newRRSet);
|
||||
rec->addr_info_gencnt++;
|
||||
} else {
|
||||
if (rec->addr_info && newRRSet) {
|
||||
rec->addr_info->ttl = newRRSet->ttl;
|
||||
}
|
||||
old_addr_info = newRRSet;
|
||||
delete newRRSet;
|
||||
}
|
||||
}
|
||||
delete old_addr_info;
|
||||
|
||||
rec->negative = !rec->addr_info;
|
||||
PrepareRecordExpiration(rec);
|
||||
rec->resolving = false;
|
||||
|
||||
|
||||
if (rec->usingAnyThread) {
|
||||
mActiveAnyThreadCount--;
|
||||
rec->usingAnyThread = false;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include "mozilla/net/DashboardTypes.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
class nsHostResolver;
|
||||
class nsHostRecord;
|
||||
@ -73,8 +74,8 @@ public:
|
||||
*/
|
||||
Mutex addr_info_lock;
|
||||
int addr_info_gencnt; /* generation count of |addr_info| */
|
||||
mozilla::net::AddrInfo *addr_info;
|
||||
mozilla::net::NetAddr *addr;
|
||||
mozilla::UniquePtr<mozilla::net::AddrInfo> addr_info;
|
||||
mozilla::UniquePtr<mozilla::net::NetAddr> addr;
|
||||
bool negative; /* True if this record is a cache of a failed lookup.
|
||||
Negative cache entries are valid just like any other
|
||||
(though never for more than 60 seconds), but a use
|
||||
|
@ -139,34 +139,6 @@ nsNSSCertTrust::SetValidCA()
|
||||
false, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsNSSCertTrust::SetTrustedServerCA()
|
||||
{
|
||||
SetSSLTrust(false, false,
|
||||
true, true, false,
|
||||
false, false);
|
||||
SetEmailTrust(false, false,
|
||||
true, true, false,
|
||||
false, false);
|
||||
SetObjSignTrust(false, false,
|
||||
true, true, false,
|
||||
false, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsNSSCertTrust::SetTrustedCA()
|
||||
{
|
||||
SetSSLTrust(false, false,
|
||||
true, true, true,
|
||||
false, false);
|
||||
SetEmailTrust(false, false,
|
||||
true, true, true,
|
||||
false, false);
|
||||
SetObjSignTrust(false, false,
|
||||
true, true, true,
|
||||
false, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsNSSCertTrust::SetValidPeer()
|
||||
{
|
||||
@ -181,34 +153,6 @@ nsNSSCertTrust::SetValidPeer()
|
||||
false, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsNSSCertTrust::SetTrustedPeer()
|
||||
{
|
||||
SetSSLTrust(true, true,
|
||||
false, false, false,
|
||||
false, false);
|
||||
SetEmailTrust(true, true,
|
||||
false, false, false,
|
||||
false, false);
|
||||
SetObjSignTrust(true, true,
|
||||
false, false, false,
|
||||
false, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsNSSCertTrust::SetUser()
|
||||
{
|
||||
SetSSLTrust(false, false,
|
||||
false, false, false,
|
||||
true, false);
|
||||
SetEmailTrust(false, false,
|
||||
false, false, false,
|
||||
true, false);
|
||||
SetObjSignTrust(false, false,
|
||||
false, false, false,
|
||||
true, false);
|
||||
}
|
||||
|
||||
bool
|
||||
nsNSSCertTrust::HasAnyCA()
|
||||
{
|
||||
@ -219,20 +163,6 @@ nsNSSCertTrust::HasAnyCA()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsNSSCertTrust::HasCA(bool checkSSL,
|
||||
bool checkEmail,
|
||||
bool checkObjSign)
|
||||
{
|
||||
if (checkSSL && !hasTrust(mTrust.sslFlags, CERTDB_VALID_CA))
|
||||
return false;
|
||||
if (checkEmail && !hasTrust(mTrust.emailFlags, CERTDB_VALID_CA))
|
||||
return false;
|
||||
if (checkObjSign && !hasTrust(mTrust.objectSigningFlags, CERTDB_VALID_CA))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsNSSCertTrust::HasPeer(bool checkSSL,
|
||||
bool checkEmail,
|
||||
@ -257,20 +187,6 @@ nsNSSCertTrust::HasAnyUser()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsNSSCertTrust::HasUser(bool checkSSL,
|
||||
bool checkEmail,
|
||||
bool checkObjSign)
|
||||
{
|
||||
if (checkSSL && !hasTrust(mTrust.sslFlags, CERTDB_USER))
|
||||
return false;
|
||||
if (checkEmail && !hasTrust(mTrust.emailFlags, CERTDB_USER))
|
||||
return false;
|
||||
if (checkObjSign && !hasTrust(mTrust.objectSigningFlags, CERTDB_USER))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsNSSCertTrust::HasTrustedCA(bool checkSSL,
|
||||
bool checkEmail,
|
||||
@ -315,4 +231,3 @@ nsNSSCertTrust::hasTrust(unsigned int t, unsigned int v)
|
||||
{
|
||||
return !!(t & v);
|
||||
}
|
||||
|
||||
|
@ -2,15 +2,13 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _NSNSSCERTTRUST_H_
|
||||
#define _NSNSSCERTTRUST_H_
|
||||
#ifndef nsNSSCertTrust_h
|
||||
#define nsNSSCertTrust_h
|
||||
|
||||
#include "certt.h"
|
||||
#include "certdb.h"
|
||||
#include "certt.h"
|
||||
|
||||
/*
|
||||
* nsNSSCertTrust
|
||||
*
|
||||
* Class for maintaining trust flags for an NSS certificate.
|
||||
*/
|
||||
class nsNSSCertTrust
|
||||
@ -24,15 +22,9 @@ public:
|
||||
/* query */
|
||||
bool HasAnyCA();
|
||||
bool HasAnyUser();
|
||||
bool HasCA(bool checkSSL = true,
|
||||
bool checkEmail = true,
|
||||
bool checkObjSign = true);
|
||||
bool HasPeer(bool checkSSL = true,
|
||||
bool checkEmail = true,
|
||||
bool checkObjSign = true);
|
||||
bool HasUser(bool checkSSL = true,
|
||||
bool checkEmail = true,
|
||||
bool checkObjSign = true);
|
||||
bool HasTrustedCA(bool checkSSL = true,
|
||||
bool checkEmail = true,
|
||||
bool checkObjSign = true);
|
||||
@ -43,16 +35,8 @@ public:
|
||||
/* common defaults */
|
||||
/* equivalent to "c,c,c" */
|
||||
void SetValidCA();
|
||||
/* equivalent to "C,C,C" */
|
||||
void SetTrustedServerCA();
|
||||
/* equivalent to "CT,CT,CT" */
|
||||
void SetTrustedCA();
|
||||
/* equivalent to "p,p,p" */
|
||||
void SetValidPeer();
|
||||
/* equivalent to "P,P,P" */
|
||||
void SetTrustedPeer();
|
||||
/* equivalent to "u,u,u" */
|
||||
void SetUser();
|
||||
|
||||
/* general setters */
|
||||
/* read: "p, P, c, C, T, u, w" */
|
||||
@ -83,4 +67,4 @@ private:
|
||||
CERTCertTrust mTrust;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // nsNSSCertTrust_h
|
||||
|
@ -333,7 +333,9 @@ this.FxAccountsWebChannelHelpers.prototype = {
|
||||
// features (ie, new fields) - forcing the server to track a map of
|
||||
// versions to supported field names doesn't buy us much.
|
||||
// So we just remove field names we know aren't handled.
|
||||
let newCredentials = {};
|
||||
let newCredentials = {
|
||||
deviceId: null
|
||||
};
|
||||
for (let name of Object.keys(credentials)) {
|
||||
if (name == "email" || name == "uid" || FxAccountsStorageManagerCanStoreField(name)) {
|
||||
newCredentials[name] = credentials[name];
|
||||
|
@ -414,6 +414,8 @@ add_task(function* test_helpers_change_password() {
|
||||
do_check_true(credentials.hasOwnProperty("email"));
|
||||
do_check_true(credentials.hasOwnProperty("uid"));
|
||||
do_check_true(credentials.hasOwnProperty("kA"));
|
||||
do_check_true(credentials.hasOwnProperty("deviceId"));
|
||||
do_check_null(credentials.deviceId);
|
||||
// "foo" isn't a field known by storage, so should be dropped.
|
||||
do_check_false(credentials.hasOwnProperty("foo"));
|
||||
wasCalled.updateUserAccountData = true;
|
||||
|
@ -66,6 +66,7 @@ enum VersionComparisonOp {
|
||||
DRIVER_LESS_THAN, // driver < version
|
||||
DRIVER_BUILD_ID_LESS_THAN, // driver build id < version
|
||||
DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
|
||||
DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, // driver build id <= version
|
||||
DRIVER_GREATER_THAN, // driver > version
|
||||
DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
|
||||
DRIVER_EQUAL, // driver == version
|
||||
|
@ -375,8 +375,12 @@ BlacklistComparatorToComparisonOp(const nsAString& op)
|
||||
{
|
||||
if (op.EqualsLiteral("LESS_THAN"))
|
||||
return DRIVER_LESS_THAN;
|
||||
else if (op.EqualsLiteral("BUILD_ID_LESS_THAN"))
|
||||
return DRIVER_BUILD_ID_LESS_THAN;
|
||||
else if (op.EqualsLiteral("LESS_THAN_OR_EQUAL"))
|
||||
return DRIVER_LESS_THAN_OR_EQUAL;
|
||||
else if (op.EqualsLiteral("BUILD_ID_LESS_THAN_OR_EQUAL"))
|
||||
return DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL;
|
||||
else if (op.EqualsLiteral("GREATER_THAN"))
|
||||
return DRIVER_GREATER_THAN;
|
||||
else if (op.EqualsLiteral("GREATER_THAN_OR_EQUAL"))
|
||||
@ -740,6 +744,9 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
|
||||
case DRIVER_LESS_THAN_OR_EQUAL:
|
||||
match = driverVersion <= info[i].mDriverVersion;
|
||||
break;
|
||||
case DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL:
|
||||
match = (driverVersion & 0xFFFF) <= info[i].mDriverVersion;
|
||||
break;
|
||||
case DRIVER_GREATER_THAN:
|
||||
match = driverVersion > info[i].mDriverVersion;
|
||||
break;
|
||||
|
@ -1067,7 +1067,7 @@ GfxInfo::GetGfxDriverInfo()
|
||||
APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Windows,
|
||||
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelHD3000),
|
||||
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
|
||||
DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2321), "FEATURE_FAILURE_BUG_1018278", "8.15.10.2342");
|
||||
DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 2321, "FEATURE_FAILURE_BUG_1018278", "X.X.X.2342");
|
||||
|
||||
/* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302
|
||||
* See bug 806786
|
||||
|
@ -13,15 +13,12 @@
|
||||
|
||||
#include <winspool.h>
|
||||
|
||||
#include <tchar.h>
|
||||
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsIPrintSettingsWin.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsStringEnumerator.h"
|
||||
@ -34,15 +31,6 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
||||
// For NS_CopyNativeToUnicode
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
|
||||
// File Picker
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFilePicker.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties"
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
@ -342,42 +330,50 @@ nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings*
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
HANDLE hPrinter = nullptr;
|
||||
nsHPRINTER hPrinter = nullptr;
|
||||
wchar_t *name = (wchar_t*)aName; // Windows APIs use non-const name argument
|
||||
|
||||
BOOL status = ::OpenPrinterW(name, &hPrinter, nullptr);
|
||||
if (status) {
|
||||
nsAutoPrinter autoPrinter(hPrinter);
|
||||
|
||||
LPDEVMODEW pDevMode;
|
||||
DWORD dwNeeded, dwRet;
|
||||
|
||||
// Allocate a buffer of the correct size.
|
||||
dwNeeded = ::DocumentPropertiesW(nullptr, hPrinter, name, nullptr, nullptr, 0);
|
||||
LONG needed = ::DocumentPropertiesW(nullptr, hPrinter, name, nullptr,
|
||||
nullptr, 0);
|
||||
if (needed < 0) {
|
||||
PR_PL(("**** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't get "
|
||||
"size of DEVMODE using DocumentPropertiesW(pDeviceName = \"%s\"). "
|
||||
"GetLastEror() = %08x\n",
|
||||
aName ? NS_ConvertUTF16toUTF8(aName).get() : "", GetLastError()));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
pDevMode = (LPDEVMODEW)::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);
|
||||
pDevMode = (LPDEVMODEW)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
needed);
|
||||
if (!pDevMode) return NS_ERROR_FAILURE;
|
||||
|
||||
// Get the default DevMode for the printer and modify it for our needs.
|
||||
dwRet = DocumentPropertiesW(nullptr, hPrinter, name,
|
||||
pDevMode, nullptr, DM_OUT_BUFFER);
|
||||
LONG ret = ::DocumentPropertiesW(nullptr, hPrinter, name,
|
||||
pDevMode, nullptr, DM_OUT_BUFFER);
|
||||
|
||||
if (dwRet == IDOK && aPS) {
|
||||
if (ret == IDOK && aPS) {
|
||||
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
|
||||
MOZ_ASSERT(psWin);
|
||||
psWin->CopyToNative(pDevMode);
|
||||
// Sets back the changes we made to the DevMode into the Printer Driver
|
||||
dwRet = ::DocumentPropertiesW(nullptr, hPrinter, name,
|
||||
pDevMode, pDevMode,
|
||||
DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
ret = ::DocumentPropertiesW(nullptr, hPrinter, name,
|
||||
pDevMode, pDevMode,
|
||||
DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
|
||||
// We need to copy the final DEVMODE settings back to our print settings,
|
||||
// because they may have been set from invalid prefs.
|
||||
if (dwRet == IDOK) {
|
||||
if (ret == IDOK) {
|
||||
// We need to get information from the device as well.
|
||||
nsAutoHDC printerDC(::CreateICW(kDriverName, aName, nullptr, pDevMode));
|
||||
if (NS_WARN_IF(!printerDC)) {
|
||||
::HeapFree(::GetProcessHeap(), 0, pDevMode);
|
||||
::ClosePrinter(hPrinter);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -385,10 +381,9 @@ nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings*
|
||||
}
|
||||
}
|
||||
|
||||
if (dwRet != IDOK) {
|
||||
if (ret != IDOK) {
|
||||
::HeapFree(::GetProcessHeap(), 0, pDevMode);
|
||||
::ClosePrinter(hPrinter);
|
||||
PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - DocumentProperties call failed code: %d/0x%x\n", dwRet, dwRet));
|
||||
PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - DocumentProperties call failed code: %d/0x%x\n", ret, ret));
|
||||
DISPLAY_LAST_ERROR
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -399,7 +394,6 @@ nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings*
|
||||
|
||||
SetDriverName(kDriverName);
|
||||
|
||||
::ClosePrinter(hPrinter);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND;
|
||||
|
Loading…
Reference in New Issue
Block a user