mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Merge inbound to m-c a=merge
This commit is contained in:
commit
a3f4d1e96c
@ -6,6 +6,9 @@
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<style>
|
||||
#listitemnone {
|
||||
list-style-type: none;
|
||||
}
|
||||
h6.gencontent:before {
|
||||
content: "aga"
|
||||
}
|
||||
@ -67,13 +70,17 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IDs = [ "list" ];
|
||||
testCharacterCount(IDs, 1);
|
||||
testText(IDs, 0, 1, kEmbedChar);
|
||||
testCharacterCount(IDs, 2);
|
||||
testText(IDs, 0, 2, kEmbedChar + kEmbedChar);
|
||||
|
||||
IDs = [ "listitem" ];
|
||||
testCharacterCount(IDs, 6);
|
||||
testText(IDs, 0, 6, "1. foo");
|
||||
|
||||
IDs = [ "listitemnone" ];
|
||||
testCharacterCount(IDs, 3);
|
||||
testText(IDs, 0, 3, "bar");
|
||||
|
||||
testText(["testbr"], 0, 3, "foo");
|
||||
|
||||
testTextAtOffset(2, nsIAccessibleText.BOUNDARY_CHAR, "o", 2, 3, "testbr",
|
||||
@ -117,7 +124,10 @@
|
||||
|
||||
<div id="hypertext">hello <a>friend</a> see <img></div>
|
||||
<div id="hypertext2">hello <a>friend</a> see <input></div>
|
||||
<ol id="list"><li id="listitem">foo</li></ol>
|
||||
<ol id="list">
|
||||
<li id="listitem">foo</li>
|
||||
<li id="listitemnone">bar</li>
|
||||
</ol>
|
||||
|
||||
<div id="hypertext3">line
|
||||
<!-- haha -->
|
||||
|
@ -62,7 +62,8 @@ TestRunner.prototype = {
|
||||
},
|
||||
|
||||
_uncaughtErrorObserver: function({message, date, fileName, stack, lineNumber}) {
|
||||
this.fail("There was an uncaught Promise rejection: " + stack);
|
||||
this.fail("There was an uncaught Promise rejection: " + message + " @ " +
|
||||
fileName + ":" + lineNumber + "\n" + stack);
|
||||
},
|
||||
|
||||
pass: function pass(message) {
|
||||
|
@ -52,19 +52,37 @@ var security = {
|
||||
cAName : issuerName,
|
||||
encryptionAlgorithm : undefined,
|
||||
encryptionStrength : undefined,
|
||||
version: undefined,
|
||||
isBroken : isBroken,
|
||||
isEV : isEV,
|
||||
cert : cert,
|
||||
fullLocation : gWindow.location
|
||||
};
|
||||
|
||||
var version;
|
||||
try {
|
||||
retval.encryptionAlgorithm = status.cipherName;
|
||||
retval.encryptionStrength = status.secretKeyLength;
|
||||
version = status.protocolVersion;
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case nsISSLStatus.SSL_VERSION_3:
|
||||
retval.version = "SSL 3";
|
||||
break;
|
||||
case nsISSLStatus.TLS_VERSION_1:
|
||||
retval.version = "TLS 1.0";
|
||||
break;
|
||||
case nsISSLStatus.TLS_VERSION_1_1:
|
||||
retval.version = "TLS 1.1";
|
||||
break;
|
||||
case nsISSLStatus.TLS_VERSION_1_2:
|
||||
retval.version = "TLS 1.2"
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
} else {
|
||||
return {
|
||||
@ -72,6 +90,7 @@ var security = {
|
||||
cAName : "",
|
||||
encryptionAlgorithm : "",
|
||||
encryptionStrength : 0,
|
||||
version: "",
|
||||
isBroken : isBroken,
|
||||
isEV : isEV,
|
||||
cert : null,
|
||||
@ -239,15 +258,19 @@ function securityOnLoad() {
|
||||
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
|
||||
}
|
||||
else if (info.encryptionStrength >= 90) {
|
||||
hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBits",
|
||||
[info.encryptionAlgorithm, info.encryptionStrength + ""]);
|
||||
hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBitsAndProtocol",
|
||||
[info.encryptionAlgorithm,
|
||||
info.encryptionStrength + "",
|
||||
info.version]);
|
||||
msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
|
||||
msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2");
|
||||
security._cert = info.cert;
|
||||
}
|
||||
else if (info.encryptionStrength > 0) {
|
||||
hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBits",
|
||||
[info.encryptionAlgorithm, info.encryptionStrength + ""]);
|
||||
hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBitsAndProtocol",
|
||||
[info.encryptionAlgorithm,
|
||||
info.encryptionStrength + "",
|
||||
info.version]);
|
||||
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]);
|
||||
msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
|
||||
|
||||
explicit nsIScriptElement(mozilla::dom::FromParser aFromParser)
|
||||
: mLineNumber(0),
|
||||
: mLineNumber(1),
|
||||
mAlreadyStarted(false),
|
||||
mMalformed(false),
|
||||
mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
||||
|
@ -557,6 +557,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
||||
[test_bug927196.html]
|
||||
[test_bug945152.html]
|
||||
run-if = os == 'linux'
|
||||
[test_bug982153.html]
|
||||
[test_bug1008126.html]
|
||||
run-if = os == 'linux'
|
||||
[test_bug1057176.html]
|
||||
|
29
content/base/test/test_bug982153.html
Normal file
29
content/base/test/test_bug982153.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=982153
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 982153</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script>
|
||||
|
||||
var sc = document.createElement("script");
|
||||
var error = null;
|
||||
sc.textContent = "try {\n reference_error; } catch(e) { error = e; }";
|
||||
document.documentElement.appendChild(sc);
|
||||
is(error.lineNumber, 2, "Error line number must be correct");
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982153">Mozilla Bug 982153</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -230,6 +230,10 @@ public:
|
||||
/* This call reserves but does not start the device. */
|
||||
virtual nsresult Allocate(const VideoTrackConstraintsN &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs) = 0;
|
||||
|
||||
virtual bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets) = 0;
|
||||
|
||||
protected:
|
||||
explicit MediaEngineVideoSource(MediaEngineState aState)
|
||||
: MediaEngineSource(aState) {}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using dom::ConstrainLongRange;
|
||||
using dom::ConstrainDoubleRange;
|
||||
using dom::MediaTrackConstraintSet;
|
||||
@ -47,6 +48,26 @@ MediaEngineCameraVideoSource::Intersect(ConstrainLongRange& aA, const ConstrainL
|
||||
return true;
|
||||
}
|
||||
|
||||
// guts for appending data to the MSG track
|
||||
bool MediaEngineCameraVideoSource::AppendToTrack(SourceMediaStream* aSource,
|
||||
layers::Image* aImage,
|
||||
TrackID aID,
|
||||
TrackTicks delta)
|
||||
{
|
||||
MOZ_ASSERT(aSource);
|
||||
|
||||
VideoSegment segment;
|
||||
nsRefPtr<layers::Image> image = aImage;
|
||||
IntSize size(image ? mWidth : 0, image ? mHeight : 0);
|
||||
segment.AppendFrame(image.forget(), delta, size);
|
||||
|
||||
// This is safe from any thread, and is safe if the track is Finished
|
||||
// or Destroyed.
|
||||
// This can fail if either a) we haven't added the track yet, or b)
|
||||
// we've removed or finished the track.
|
||||
return aSource->AppendToTrack(aID, &(segment));
|
||||
}
|
||||
|
||||
// A special version of the algorithm for cameras that don't list capabilities.
|
||||
void
|
||||
MediaEngineCameraVideoSource::GuessCapability(
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
, mInitDone(false)
|
||||
, mHasDirectListeners(false)
|
||||
, mCaptureIndex(aIndex)
|
||||
, mTrackID(0)
|
||||
, mFps(-1)
|
||||
{}
|
||||
|
||||
@ -60,6 +61,12 @@ public:
|
||||
protected:
|
||||
~MediaEngineCameraVideoSource() {}
|
||||
|
||||
// guts for appending data to the MSG track
|
||||
virtual bool AppendToTrack(SourceMediaStream* aSource,
|
||||
layers::Image* aImage,
|
||||
TrackID aID,
|
||||
TrackTicks delta);
|
||||
|
||||
static bool IsWithin(int32_t n, const dom::ConstrainLongRange& aRange);
|
||||
static bool IsWithin(double n, const dom::ConstrainDoubleRange& aRange);
|
||||
static int32_t Clamp(int32_t n, const dom::ConstrainLongRange& aRange);
|
||||
@ -87,6 +94,7 @@ protected:
|
||||
bool mInitDone;
|
||||
bool mHasDirectListeners;
|
||||
int mCaptureIndex;
|
||||
TrackID mTrackID;
|
||||
int mFps; // Track rate (30 fps by default)
|
||||
|
||||
webrtc::CaptureCapability mCapability; // Doesn't work on OS X.
|
||||
|
@ -55,6 +55,11 @@ public:
|
||||
TrackID aId,
|
||||
StreamTime aDesiredTime,
|
||||
TrackTicks &aLastEndTime);
|
||||
virtual bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsFake() {
|
||||
return true;
|
||||
|
@ -154,6 +154,7 @@ MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
if (mState == kStarted) {
|
||||
return NS_OK;
|
||||
}
|
||||
mTrackID = aID;
|
||||
mImageContainer = layers::LayerManager::CreateImageContainer();
|
||||
|
||||
NS_DispatchToMainThread(WrapRunnable(nsRefPtr<MediaEngineGonkVideoSource>(this),
|
||||
@ -621,6 +622,21 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
|
||||
|
||||
// implicitly releases last image
|
||||
mImage = image.forget();
|
||||
|
||||
// Push the frame into the MSG with a minimal duration. This will likely
|
||||
// mean we'll still get NotifyPull calls which will then return the same
|
||||
// frame again with a longer duration. However, this means we won't
|
||||
// fail to get the frame in and drop frames.
|
||||
|
||||
// XXX The timestamp for the frame should be base on the Capture time,
|
||||
// not the MSG time, and MSG should never, ever block on a (realtime)
|
||||
// video frame (or even really for streaming - audio yes, video probably no).
|
||||
uint32_t len = mSources.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (mSources[i]) {
|
||||
AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -64,6 +64,11 @@ public:
|
||||
TrackID aId,
|
||||
StreamTime aDesiredTime,
|
||||
TrackTicks& aLastEndTime) MOZ_OVERRIDE;
|
||||
virtual bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnHardwareStateChange(HardwareState aState);
|
||||
void GetRotation();
|
||||
|
@ -32,6 +32,11 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
|
||||
virtual const MediaSourceType GetMediaSource() {
|
||||
return MediaSourceType::Browser;
|
||||
}
|
||||
virtual bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
|
@ -110,6 +110,9 @@ public:
|
||||
|
||||
void Refresh(int aIndex);
|
||||
|
||||
bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
|
||||
|
||||
protected:
|
||||
~MediaEngineWebRTCVideoSource() { Shutdown(); }
|
||||
|
||||
@ -128,7 +131,7 @@ private:
|
||||
int mMinFps; // Min rate we want to accept
|
||||
MediaSourceType mMediaSource; // source of media (camera | application | screen)
|
||||
|
||||
static bool SatisfyConstraintSet(const dom::MediaTrackConstraintSet& aConstraints,
|
||||
static bool SatisfiesConstraintSet(const dom::MediaTrackConstraintSet& aConstraints,
|
||||
const webrtc::CaptureCapability& aCandidate);
|
||||
void ChooseCapability(const VideoTrackConstraintsN& aConstraints,
|
||||
const MediaEnginePrefs& aPrefs);
|
||||
|
@ -39,8 +39,10 @@ namespace mozilla {
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* GetMediaManagerLog();
|
||||
#define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
|
||||
#define LOG_FRAMES(msg) PR_LOG(GetMediaManagerLog(), 6, msg)
|
||||
#else
|
||||
#define LOG(msg)
|
||||
#define LOG_FRAMES(msg)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -401,7 +403,7 @@ MediaEngineWebRTCAudioSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
#ifdef DEBUG
|
||||
TrackTicks target = aSource->TimeToTicksRoundUp(SAMPLE_FREQUENCY, aDesiredTime);
|
||||
TrackTicks delta = target - aLastEndTime;
|
||||
LOG(("Audio: NotifyPull: aDesiredTime %ld, target %ld, delta %ld",(int64_t) aDesiredTime, (int64_t) target, (int64_t) delta));
|
||||
LOG_FRAMES(("Audio: NotifyPull: aDesiredTime %ld, target %ld, delta %ld",(int64_t) aDesiredTime, (int64_t) target, (int64_t) delta));
|
||||
aLastEndTime = target;
|
||||
#endif
|
||||
}
|
||||
|
@ -98,6 +98,22 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
|
||||
// implicitly releases last image
|
||||
mImage = image.forget();
|
||||
|
||||
// Push the frame into the MSG with a minimal duration. This will likely
|
||||
// mean we'll still get NotifyPull calls which will then return the same
|
||||
// frame again with a longer duration. However, this means we won't
|
||||
// fail to get the frame in and drop frames.
|
||||
|
||||
// XXX The timestamp for the frame should be based on the Capture time,
|
||||
// not the MSG time, and MSG should never, ever block on a (realtime)
|
||||
// video frame (or even really for streaming - audio yes, video probably no).
|
||||
// Note that MediaPipeline currently ignores the timestamps from MSG
|
||||
uint32_t len = mSources.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (mSources[i]) {
|
||||
AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -106,7 +122,7 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
|
||||
// this means that no *real* frame can be inserted during this period.
|
||||
void
|
||||
MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
SourceMediaStream *aSource,
|
||||
SourceMediaStream* aSource,
|
||||
TrackID aID,
|
||||
StreamTime aDesiredTime,
|
||||
TrackTicks &aLastEndTime)
|
||||
@ -118,12 +134,10 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
// So mState could be kReleased here. We really don't care about the state,
|
||||
// though.
|
||||
|
||||
// Note: we're not giving up mImage here
|
||||
nsRefPtr<layers::Image> image = mImage;
|
||||
TrackTicks target = aSource->TimeToTicksRoundUp(USECS_PER_S, aDesiredTime);
|
||||
TrackTicks delta = target - aLastEndTime;
|
||||
LOGFRAME(("NotifyPull, desired = %ld, target = %ld, delta = %ld %s", (int64_t) aDesiredTime,
|
||||
(int64_t) target, (int64_t) delta, image ? "" : "<null>"));
|
||||
(int64_t) target, (int64_t) delta, mImage ? "" : "<null>"));
|
||||
|
||||
// Bug 846188 We may want to limit incoming frames to the requested frame rate
|
||||
// mFps - if you want 30FPS, and the camera gives you 60FPS, this could
|
||||
@ -137,18 +151,15 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
// Doing so means a negative delta and thus messes up handling of the graph
|
||||
if (delta > 0) {
|
||||
// nullptr images are allowed
|
||||
IntSize size(image ? mWidth : 0, image ? mHeight : 0);
|
||||
segment.AppendFrame(image.forget(), delta, size);
|
||||
// This can fail if either a) we haven't added the track yet, or b)
|
||||
// we've removed or finished the track.
|
||||
if (aSource->AppendToTrack(aID, &(segment))) {
|
||||
if (AppendToTrack(aSource, mImage, aID, delta)) {
|
||||
aLastEndTime = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
bool MediaEngineWebRTCVideoSource::SatisfyConstraintSet(const MediaTrackConstraintSet &aConstraints,
|
||||
bool
|
||||
MediaEngineWebRTCVideoSource::SatisfiesConstraintSet(const MediaTrackConstraintSet &aConstraints,
|
||||
const webrtc::CaptureCapability& aCandidate) {
|
||||
if (!MediaEngineCameraVideoSource::IsWithin(aCandidate.width, aConstraints.mWidth) ||
|
||||
!MediaEngineCameraVideoSource::IsWithin(aCandidate.height, aConstraints.mHeight)) {
|
||||
@ -160,6 +171,41 @@ bool MediaEngineWebRTCVideoSource::SatisfyConstraintSet(const MediaTrackConstrai
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef nsTArray<uint8_t> CapabilitySet;
|
||||
|
||||
// SatisfiesConstraintSets (plural) answers for the capture device as a whole
|
||||
// whether it can satisfy an accumulated number of capabilitySets.
|
||||
|
||||
bool
|
||||
MediaEngineWebRTCVideoSource::SatisfiesConstraintSets(
|
||||
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 uniqueId(mUniqueId);
|
||||
int num = mViECapture->NumberOfCapabilities(uniqueId.get(), kMaxUniqueIdLength);
|
||||
if (num <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CapabilitySet candidateSet;
|
||||
for (int i = 0; i < num; i++) {
|
||||
candidateSet.AppendElement(i);
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < aConstraintSets.Length(); j++) {
|
||||
for (size_t i = 0; i < candidateSet.Length(); ) {
|
||||
webrtc::CaptureCapability cap;
|
||||
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength,
|
||||
candidateSet[i], cap);
|
||||
if (!SatisfiesConstraintSet(*aConstraintSets[j], cap)) {
|
||||
candidateSet.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !!candidateSet.Length();
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCVideoSource::ChooseCapability(
|
||||
const VideoTrackConstraintsN &aConstraints,
|
||||
@ -177,9 +223,7 @@ MediaEngineWebRTCVideoSource::ChooseCapability(
|
||||
LOG(("ChooseCapability: prefs: %dx%d @%d-%dfps",
|
||||
aPrefs.mWidth, aPrefs.mHeight, aPrefs.mFPS, aPrefs.mMinFPS));
|
||||
|
||||
typedef nsTArray<uint8_t> SourceSet;
|
||||
|
||||
SourceSet candidateSet;
|
||||
CapabilitySet candidateSet;
|
||||
for (int i = 0; i < num; i++) {
|
||||
candidateSet.AppendElement(i);
|
||||
}
|
||||
@ -190,14 +234,14 @@ MediaEngineWebRTCVideoSource::ChooseCapability(
|
||||
webrtc::CaptureCapability cap;
|
||||
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength,
|
||||
candidateSet[i], cap);
|
||||
if (!SatisfyConstraintSet(aConstraints.mRequired, cap)) {
|
||||
if (!SatisfiesConstraintSet(aConstraints.mRequired, cap)) {
|
||||
candidateSet.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
SourceSet tailSet;
|
||||
CapabilitySet tailSet;
|
||||
|
||||
// Then apply advanced (formerly known as optional) constraints.
|
||||
|
||||
@ -205,12 +249,12 @@ MediaEngineWebRTCVideoSource::ChooseCapability(
|
||||
auto &array = aConstraints.mAdvanced.Value();
|
||||
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
SourceSet rejects;
|
||||
CapabilitySet rejects;
|
||||
for (uint32_t j = 0; j < candidateSet.Length();) {
|
||||
webrtc::CaptureCapability cap;
|
||||
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength,
|
||||
candidateSet[j], cap);
|
||||
if (!SatisfyConstraintSet(array[i], cap)) {
|
||||
if (!SatisfiesConstraintSet(array[i], cap)) {
|
||||
rejects.AppendElement(candidateSet[j]);
|
||||
candidateSet.RemoveElementAt(j);
|
||||
} else {
|
||||
@ -363,6 +407,8 @@ MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
mImageContainer = layers::LayerManager::CreateImageContainer();
|
||||
|
||||
mState = kStarted;
|
||||
mTrackID = aID;
|
||||
|
||||
error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
|
||||
if (error == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -39,6 +39,40 @@ namespace mozilla {
|
||||
|
||||
#ifdef MOZ_CHILD_PERMISSIONS
|
||||
|
||||
static bool
|
||||
CheckAppTypeHelper(mozIApplication* aApp,
|
||||
AssertAppProcessType aType,
|
||||
const char* aCapability,
|
||||
bool aIsBrowserElement)
|
||||
{
|
||||
bool aValid = false;
|
||||
|
||||
// isBrowser frames inherit their app descriptor to identify their
|
||||
// data storage, but they don't inherit the capability associated
|
||||
// with that descriptor.
|
||||
if (aApp && (aType == ASSERT_APP_HAS_PERMISSION || !aIsBrowserElement)) {
|
||||
switch (aType) {
|
||||
case ASSERT_APP_HAS_PERMISSION:
|
||||
case ASSERT_APP_PROCESS_PERMISSION:
|
||||
if (!NS_SUCCEEDED(aApp->HasPermission(aCapability, &aValid))) {
|
||||
aValid = false;
|
||||
}
|
||||
break;
|
||||
case ASSERT_APP_PROCESS_MANIFEST_URL: {
|
||||
nsAutoString manifestURL;
|
||||
if (NS_SUCCEEDED(aApp->GetManifestURL(manifestURL)) &&
|
||||
manifestURL.EqualsASCII(aCapability)) {
|
||||
aValid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return aValid;
|
||||
}
|
||||
|
||||
bool
|
||||
AssertAppProcess(PBrowserParent* aActor,
|
||||
AssertAppProcessType aType,
|
||||
@ -51,32 +85,24 @@ AssertAppProcess(PBrowserParent* aActor,
|
||||
|
||||
TabParent* tab = static_cast<TabParent*>(aActor);
|
||||
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
|
||||
bool aValid = false;
|
||||
|
||||
// isBrowser frames inherit their app descriptor to identify their
|
||||
// data storage, but they don't inherit the capability associated
|
||||
// with that descriptor.
|
||||
if (app && (aType == ASSERT_APP_HAS_PERMISSION || !tab->IsBrowserElement())) {
|
||||
switch (aType) {
|
||||
case ASSERT_APP_HAS_PERMISSION:
|
||||
case ASSERT_APP_PROCESS_PERMISSION:
|
||||
if (!NS_SUCCEEDED(app->HasPermission(aCapability, &aValid))) {
|
||||
aValid = false;
|
||||
}
|
||||
break;
|
||||
case ASSERT_APP_PROCESS_MANIFEST_URL: {
|
||||
nsAutoString manifestURL;
|
||||
if (NS_SUCCEEDED(app->GetManifestURL(manifestURL)) &&
|
||||
manifestURL.EqualsASCII(aCapability)) {
|
||||
aValid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
return CheckAppTypeHelper(app, aType, aCapability, tab->IsBrowserElement());
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckAppStatusHelper(mozIApplication* aApp,
|
||||
unsigned short aStatus)
|
||||
{
|
||||
bool valid = false;
|
||||
|
||||
if (aApp) {
|
||||
unsigned short appStatus = 0;
|
||||
if (NS_SUCCEEDED(aApp->GetAppStatus(&appStatus))) {
|
||||
valid = appStatus == aStatus;
|
||||
}
|
||||
}
|
||||
return aValid;
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -91,16 +117,26 @@ AssertAppStatus(PBrowserParent* aActor,
|
||||
TabParent* tab = static_cast<TabParent*>(aActor);
|
||||
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
|
||||
|
||||
bool valid = false;
|
||||
return CheckAppStatusHelper(app, aStatus);
|
||||
}
|
||||
|
||||
if (app) {
|
||||
unsigned short appStatus = 0;
|
||||
if (NS_SUCCEEDED(app->GetAppStatus(&appStatus))) {
|
||||
valid = appStatus == aStatus;
|
||||
}
|
||||
}
|
||||
bool
|
||||
AssertAppProcess(TabContext& aContext,
|
||||
AssertAppProcessType aType,
|
||||
const char* aCapability)
|
||||
{
|
||||
|
||||
return valid;
|
||||
nsCOMPtr<mozIApplication> app = aContext.GetOwnOrContainingApp();
|
||||
return CheckAppTypeHelper(app, aType, aCapability, aContext.IsBrowserElement());
|
||||
}
|
||||
|
||||
bool
|
||||
AssertAppStatus(TabContext& aContext,
|
||||
unsigned short aStatus)
|
||||
{
|
||||
|
||||
nsCOMPtr<mozIApplication> app = aContext.GetOwnOrContainingApp();
|
||||
return CheckAppStatusHelper(app, aStatus);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -108,10 +144,10 @@ AssertAppProcess(PContentParent* aActor,
|
||||
AssertAppProcessType aType,
|
||||
const char* aCapability)
|
||||
{
|
||||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
aActor->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); ++i) {
|
||||
if (AssertAppProcess(browsers[i], aType, aCapability)) {
|
||||
nsTArray<TabContext> contextArray =
|
||||
static_cast<ContentParent*>(aActor)->GetManagedTabContext();
|
||||
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
|
||||
if (AssertAppProcess(contextArray[i], aType, aCapability)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -130,10 +166,10 @@ bool
|
||||
AssertAppStatus(PContentParent* aActor,
|
||||
unsigned short aStatus)
|
||||
{
|
||||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
aActor->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); ++i) {
|
||||
if (AssertAppStatus(browsers[i], aStatus)) {
|
||||
nsTArray<TabContext> contextArray =
|
||||
static_cast<ContentParent*>(aActor)->GetManagedTabContext();
|
||||
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
|
||||
if (AssertAppStatus(contextArray[i], aStatus)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -170,14 +206,13 @@ AssertAppPrincipal(PContentParent* aActor,
|
||||
bool inBrowserElement = aPrincipal->GetIsInBrowserElement();
|
||||
|
||||
// Check if the permission's appId matches a child we manage.
|
||||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
aActor->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); ++i) {
|
||||
TabParent* tab = static_cast<TabParent*>(browsers[i]);
|
||||
if (tab->OwnOrContainingAppId() == principalAppId) {
|
||||
nsTArray<TabContext> contextArray =
|
||||
static_cast<ContentParent*>(aActor)->GetManagedTabContext();
|
||||
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
|
||||
if (contextArray[i].OwnOrContainingAppId() == principalAppId) {
|
||||
// If the child only runs inBrowserElement content and the principal claims
|
||||
// it's not in a browser element, it's lying.
|
||||
if (!tab->IsBrowserElement() || inBrowserElement) {
|
||||
if (!contextArray[i].IsBrowserElement() || inBrowserElement) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@ -287,6 +322,21 @@ AssertAppStatus(mozilla::dom::PBrowserParent* aActor,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AssertAppProcess(const mozilla::dom::TabContext& aContext,
|
||||
AssertAppProcessType aType,
|
||||
const char* aCapability)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AssertAppStatus(const mozilla::dom::TabContext& aContext,
|
||||
unsigned short aStatus)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AssertAppProcess(mozilla::dom::PContentParent* aActor,
|
||||
|
@ -15,6 +15,7 @@ class nsIPrincipal;
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class TabContext;
|
||||
class PBrowserParent;
|
||||
class PContentParent;
|
||||
}
|
||||
@ -47,6 +48,24 @@ bool
|
||||
AssertAppStatus(mozilla::dom::PBrowserParent* aActor,
|
||||
unsigned short aStatus);
|
||||
|
||||
/**
|
||||
* Return true if the specified browser has the specified capability.
|
||||
* If this returns false, the browser didn't have the capability and
|
||||
* will be killed.
|
||||
*/
|
||||
bool
|
||||
AssertAppProcess(const mozilla::dom::TabContext& aContext,
|
||||
AssertAppProcessType aType,
|
||||
const char* aCapability);
|
||||
|
||||
/**
|
||||
* Return true if the specified app has the specified status.
|
||||
* If this returns false, the browser will be killed.
|
||||
*/
|
||||
bool
|
||||
AssertAppStatus(const mozilla::dom::TabContext& aContext,
|
||||
unsigned short aStatus);
|
||||
|
||||
/**
|
||||
* Return true if any of the PBrowsers loaded in this content process
|
||||
* has the specified capability. If this returns false, the process
|
||||
|
@ -81,16 +81,18 @@ ContentBridgeChild::SendPBlobConstructor(PBlobChild* actor,
|
||||
|
||||
bool
|
||||
ContentBridgeChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return PContentBridgeChild::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
@ -121,15 +123,17 @@ ContentBridgeChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
|
||||
}
|
||||
|
||||
PBrowserChild*
|
||||
ContentBridgeChild::AllocPBrowserChild(const IPCTabContext &aContext,
|
||||
ContentBridgeChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
const IPCTabContext &aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentChild::AllocPBrowserChild(aContext,
|
||||
return nsIContentChild::AllocPBrowserChild(aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
@ -142,16 +146,18 @@ ContentBridgeChild::DeallocPBrowserChild(PBrowserChild* aChild)
|
||||
|
||||
bool
|
||||
ContentBridgeChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return ContentChild::GetSingleton()->RecvPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
|
@ -39,25 +39,28 @@ public:
|
||||
jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual ~ContentBridgeChild();
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPBrowserChild(PBrowserChild*) MOZ_OVERRIDE;
|
||||
virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -87,16 +87,18 @@ ContentBridgeParent::SendPBlobConstructor(PBlobParent* actor,
|
||||
|
||||
PBrowserParent*
|
||||
ContentBridgeParent::SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return PContentBridgeParent::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
@ -126,15 +128,17 @@ ContentBridgeParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
|
||||
}
|
||||
|
||||
PBrowserParent*
|
||||
ContentBridgeParent::AllocPBrowserParent(const IPCTabContext &aContext,
|
||||
ContentBridgeParent::AllocPBrowserParent(const TabId& aTabId,
|
||||
const IPCTabContext &aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentParent::AllocPBrowserParent(aContext,
|
||||
return nsIContentParent::AllocPBrowserParent(aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/dom/PContentBridgeParent.h"
|
||||
#include "mozilla/dom/nsIContentParent.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -33,15 +34,16 @@ public:
|
||||
|
||||
virtual PBrowserParent*
|
||||
SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
|
||||
jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
|
||||
|
||||
virtual uint64_t ChildID() MOZ_OVERRIDE
|
||||
virtual ContentParentId ChildID() MOZ_OVERRIDE
|
||||
{
|
||||
return mChildID;
|
||||
}
|
||||
@ -57,7 +59,7 @@ public:
|
||||
protected:
|
||||
virtual ~ContentBridgeParent();
|
||||
|
||||
void SetChildID(uint64_t aId)
|
||||
void SetChildID(ContentParentId aId)
|
||||
{
|
||||
mChildID = aId;
|
||||
}
|
||||
@ -86,9 +88,10 @@ protected:
|
||||
DeallocPJavaScriptParent(jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserParent*
|
||||
AllocPBrowserParent(const IPCTabContext &aContext,
|
||||
AllocPBrowserParent(const TabId& aTabId,
|
||||
const IPCTabContext &aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent*) MOZ_OVERRIDE;
|
||||
@ -103,7 +106,7 @@ protected:
|
||||
protected: // members
|
||||
nsRefPtr<ContentBridgeParent> mSelfRef;
|
||||
Transport* mTransport; // owned
|
||||
uint64_t mChildID;
|
||||
ContentParentId mChildID;
|
||||
bool mIsForApp;
|
||||
bool mIsForBrowser;
|
||||
|
||||
|
@ -1109,40 +1109,45 @@ ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *aChild)
|
||||
}
|
||||
|
||||
PBrowserChild*
|
||||
ContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
ContentChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentChild::AllocPBrowserChild(aContext,
|
||||
return nsIContentChild::AllocPBrowserChild(aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return PContentChild::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aID,
|
||||
aCpID,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
@ -1166,7 +1171,7 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
|
||||
// Redo InitProcessAttributes() when the app or browser is really
|
||||
// launching so the attributes will be correct.
|
||||
mID = aID;
|
||||
mID = aCpID;
|
||||
mIsForApp = aIsForApp;
|
||||
mIsForBrowser = aIsForBrowser;
|
||||
InitProcessAttributes();
|
||||
|
@ -131,9 +131,10 @@ public:
|
||||
AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser);
|
||||
virtual bool DeallocPBrowserChild(PBrowserChild*);
|
||||
@ -354,7 +355,7 @@ public:
|
||||
// cache the value
|
||||
nsString &GetIndexedDBPath();
|
||||
|
||||
uint64_t GetID() { return mID; }
|
||||
ContentParentId GetID() { return mID; }
|
||||
|
||||
bool IsForApp() { return mIsForApp; }
|
||||
bool IsForBrowser() { return mIsForBrowser; }
|
||||
@ -370,16 +371,18 @@ public:
|
||||
DeallocPFileDescriptorSetChild(PFileDescriptorSetChild*) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool SendPBrowserConstructor(PBrowserChild* actor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual PDocAccessibleChild* AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&) MOZ_OVERRIDE;
|
||||
@ -412,7 +415,7 @@ private:
|
||||
* We expect our content parent to set this ID immediately after opening a
|
||||
* channel to us.
|
||||
*/
|
||||
uint64_t mID;
|
||||
ContentParentId mID;
|
||||
|
||||
AppInfo mAppInfo;
|
||||
|
||||
|
@ -131,6 +131,7 @@
|
||||
#include "gfxPrefs.h"
|
||||
#include "prio.h"
|
||||
#include "private/pprio.h"
|
||||
#include "ContentProcessManager.h"
|
||||
|
||||
#if defined(ANDROID) || defined(LINUX)
|
||||
#include "nsSystemInfo.h"
|
||||
@ -845,17 +846,14 @@ ContentParent::PreallocatedProcessReady()
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef std::map<ContentParent*, std::set<ContentParent*> > GrandchildMap;
|
||||
static GrandchildMap sGrandchildProcessMap;
|
||||
|
||||
std::map<uint64_t, ContentParent*> sContentParentMap;
|
||||
|
||||
bool
|
||||
ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
|
||||
const hal::ProcessPriority& aPriority,
|
||||
uint64_t* aId,
|
||||
const TabId& aOpenerTabId,
|
||||
ContentParentId* aCpId,
|
||||
bool* aIsForApp,
|
||||
bool* aIsForBrowser)
|
||||
bool* aIsForBrowser,
|
||||
TabId* aTabId)
|
||||
{
|
||||
#if 0
|
||||
if (!CanOpenBrowser(aContext)) {
|
||||
@ -884,73 +882,51 @@ ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
|
||||
}
|
||||
|
||||
if (!cp) {
|
||||
*aId = 0;
|
||||
*aCpId = 0;
|
||||
*aIsForApp = false;
|
||||
*aIsForBrowser = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
*aId = cp->ChildID();
|
||||
*aCpId = cp->ChildID();
|
||||
*aIsForApp = cp->IsForApp();
|
||||
*aIsForBrowser = cp->IsForBrowser();
|
||||
sContentParentMap[*aId] = cp;
|
||||
auto iter = sGrandchildProcessMap.find(this);
|
||||
if (iter == sGrandchildProcessMap.end()) {
|
||||
std::set<ContentParent*> children;
|
||||
children.insert(cp);
|
||||
sGrandchildProcessMap[this] = children;
|
||||
} else {
|
||||
iter->second.insert(cp);
|
||||
|
||||
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
|
||||
cpm->AddContentProcess(cp, this->ChildID());
|
||||
|
||||
if (cpm->AddGrandchildProcess(this->ChildID(), cp->ChildID())) {
|
||||
// Pre-allocate a TabId here to save one time IPC call at app startup.
|
||||
*aTabId = AllocateTabId(aOpenerTabId,
|
||||
aContext,
|
||||
cp->ChildID());
|
||||
return (*aTabId != 0);
|
||||
}
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::AnswerBridgeToChildProcess(const uint64_t& id)
|
||||
ContentParent::AnswerBridgeToChildProcess(const ContentParentId& aCpId)
|
||||
{
|
||||
ContentParent* cp = sContentParentMap[id];
|
||||
auto iter = sGrandchildProcessMap.find(this);
|
||||
if (iter != sGrandchildProcessMap.end() &&
|
||||
iter->second.find(cp) != iter->second.end()) {
|
||||
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
|
||||
ContentParent* cp = cpm->GetContentProcessById(aCpId);
|
||||
|
||||
if (cp) {
|
||||
ContentParentId parentId;
|
||||
if (cpm->GetParentProcessId(cp->ChildID(), &parentId) &&
|
||||
parentId == this->ChildID()) {
|
||||
return PContentBridge::Bridge(this, cp);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
// You can't bridge to a process you didn't open!
|
||||
KillHard();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
ContentParent* aOpenerContentParent)
|
||||
static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement)
|
||||
{
|
||||
if (!sCanLaunchSubprocesses) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
|
||||
bool isInContentProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
|
||||
|
||||
if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
|
||||
nsRefPtr<TabParent> tp;
|
||||
nsRefPtr<nsIContentParent> constructorSender;
|
||||
if (isInContentProcess) {
|
||||
MOZ_ASSERT(aContext.IsBrowserElement());
|
||||
constructorSender =
|
||||
CreateContentBridgeParent(aContext, initialPriority);
|
||||
} else {
|
||||
if (aOpenerContentParent) {
|
||||
constructorSender = aOpenerContentParent;
|
||||
} else {
|
||||
constructorSender =
|
||||
GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(),
|
||||
initialPriority);
|
||||
}
|
||||
}
|
||||
if (constructorSender) {
|
||||
uint32_t chromeFlags = 0;
|
||||
|
||||
// Propagate the private-browsing status of the element's parent
|
||||
// docshell to the remote docshell, via the chrome flags.
|
||||
nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
|
||||
@ -965,6 +941,53 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
NS_WARNING("Remote frame has no docshell");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return docShell;
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
ContentParent* aOpenerContentParent)
|
||||
{
|
||||
if (!sCanLaunchSubprocesses) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
|
||||
bool isInContentProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
|
||||
TabId tabId;
|
||||
|
||||
nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
|
||||
TabId openerTabId;
|
||||
if (docShell) {
|
||||
openerTabId = TabParent::GetTabIdFrom(docShell);
|
||||
}
|
||||
|
||||
if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
|
||||
nsRefPtr<TabParent> tp;
|
||||
nsRefPtr<nsIContentParent> constructorSender;
|
||||
if (isInContentProcess) {
|
||||
MOZ_ASSERT(aContext.IsBrowserElement());
|
||||
constructorSender = CreateContentBridgeParent(aContext,
|
||||
initialPriority,
|
||||
openerTabId,
|
||||
&tabId);
|
||||
} else {
|
||||
if (aOpenerContentParent) {
|
||||
constructorSender = aOpenerContentParent;
|
||||
} else {
|
||||
constructorSender =
|
||||
GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(),
|
||||
initialPriority);
|
||||
}
|
||||
tabId = AllocateTabId(openerTabId,
|
||||
aContext.AsIPCTabContext(),
|
||||
constructorSender->ChildID());
|
||||
}
|
||||
if (constructorSender) {
|
||||
uint32_t chromeFlags = 0;
|
||||
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
|
||||
if (loadContext && loadContext->UsePrivateBrowsing()) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
|
||||
@ -975,13 +998,17 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
|
||||
}
|
||||
|
||||
nsRefPtr<TabParent> tp(new TabParent(constructorSender,
|
||||
if (tabId == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<TabParent> tp(new TabParent(constructorSender, tabId,
|
||||
aContext, chromeFlags));
|
||||
tp->SetOwnerElement(aFrameElement);
|
||||
|
||||
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases this ref.
|
||||
tp.forget().take(),
|
||||
tabId,
|
||||
aContext.AsIPCTabContext(),
|
||||
chromeFlags,
|
||||
constructorSender->ChildID(),
|
||||
@ -1001,7 +1028,10 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
nsAutoString manifestURL;
|
||||
|
||||
if (isInContentProcess) {
|
||||
parent = CreateContentBridgeParent(aContext, initialPriority);
|
||||
parent = CreateContentBridgeParent(aContext,
|
||||
initialPriority,
|
||||
openerTabId,
|
||||
&tabId);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp();
|
||||
@ -1049,6 +1079,9 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
parentAppStatus == nsIPrincipal::APP_STATUS_CERTIFIED) {
|
||||
// Check if we can re-use the process of the parent app.
|
||||
p = sAppContentParents->Get(parentAppManifestURL);
|
||||
tabId = AllocateTabId(openerTabId,
|
||||
aContext.AsIPCTabContext(),
|
||||
p->ChildID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1070,21 +1103,25 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
&tookPreallocated);
|
||||
MOZ_ASSERT(p);
|
||||
sAppContentParents->Put(manifestURL, p);
|
||||
tabId = AllocateTabId(openerTabId,
|
||||
aContext.AsIPCTabContext(),
|
||||
p->ChildID());
|
||||
}
|
||||
parent = static_cast<nsIContentParent*>(p);
|
||||
}
|
||||
|
||||
if (!parent) {
|
||||
if (!parent || (tabId == 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t chromeFlags = 0;
|
||||
|
||||
nsRefPtr<TabParent> tp = new TabParent(parent, aContext, chromeFlags);
|
||||
nsRefPtr<TabParent> tp = new TabParent(parent, tabId, aContext, chromeFlags);
|
||||
tp->SetOwnerElement(aFrameElement);
|
||||
PBrowserParent* browser = parent->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases this ref.
|
||||
nsRefPtr<TabParent>(tp).forget().take(),
|
||||
tabId,
|
||||
aContext.AsIPCTabContext(),
|
||||
chromeFlags,
|
||||
parent->ChildID(),
|
||||
@ -1127,27 +1164,33 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
|
||||
/*static*/ ContentBridgeParent*
|
||||
ContentParent::CreateContentBridgeParent(const TabContext& aContext,
|
||||
const hal::ProcessPriority& aPriority)
|
||||
const hal::ProcessPriority& aPriority,
|
||||
const TabId& aOpenerTabId,
|
||||
/*out*/ TabId* aTabId)
|
||||
{
|
||||
MOZ_ASSERT(aTabId);
|
||||
|
||||
ContentChild* child = ContentChild::GetSingleton();
|
||||
uint64_t id;
|
||||
ContentParentId cpId;
|
||||
bool isForApp;
|
||||
bool isForBrowser;
|
||||
if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(),
|
||||
aPriority,
|
||||
&id,
|
||||
aOpenerTabId,
|
||||
&cpId,
|
||||
&isForApp,
|
||||
&isForBrowser)) {
|
||||
&isForBrowser,
|
||||
aTabId)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (id == 0) {
|
||||
if (cpId == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!child->CallBridgeToChildProcess(id)) {
|
||||
if (!child->CallBridgeToChildProcess(cpId)) {
|
||||
return nullptr;
|
||||
}
|
||||
ContentBridgeParent* parent = child->GetLastBridge();
|
||||
parent->SetChildID(id);
|
||||
parent->SetChildID(cpId);
|
||||
parent->SetIsForApp(isForApp);
|
||||
parent->SetIsForBrowser(isForBrowser);
|
||||
return parent;
|
||||
@ -1476,13 +1519,6 @@ ContentParent::MarkAsDead()
|
||||
}
|
||||
|
||||
mIsAlive = false;
|
||||
|
||||
sGrandchildProcessMap.erase(this);
|
||||
for (auto iter = sGrandchildProcessMap.begin();
|
||||
iter != sGrandchildProcessMap.end();
|
||||
iter++) {
|
||||
iter->second.erase(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1720,17 +1756,17 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
|
||||
|
||||
// Destroy any processes created by this ContentParent
|
||||
auto iter = sGrandchildProcessMap.find(this);
|
||||
if (iter != sGrandchildProcessMap.end()) {
|
||||
for(auto child = iter->second.begin();
|
||||
child != iter->second.end();
|
||||
child++) {
|
||||
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
|
||||
nsTArray<ContentParentId> childIDArray =
|
||||
cpm->GetAllChildProcessById(this->ChildID());
|
||||
for(uint32_t i = 0; i < childIDArray.Length(); i++) {
|
||||
ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(*child, &ContentParent::ShutDownProcess,
|
||||
NewRunnableMethod(cp, &ContentParent::ShutDownProcess,
|
||||
/* closeWithError */ false));
|
||||
}
|
||||
}
|
||||
cpm->RemoveContentProcess(this->ChildID());
|
||||
}
|
||||
|
||||
void
|
||||
@ -1893,6 +1929,8 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
||||
InitInternal(aInitialPriority,
|
||||
true, /* Setup off-main thread compositing */
|
||||
true /* Send registered chrome */);
|
||||
|
||||
ContentProcessManager::GetSingleton()->AddContentProcess(this);
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
@ -1970,6 +2008,8 @@ ContentParent::ContentParent(ContentParent* aTemplate,
|
||||
InitInternal(priority,
|
||||
false, /* Setup Off-main thread compositing */
|
||||
false /* Send registered chrome */);
|
||||
|
||||
ContentProcessManager::GetSingleton()->AddContentProcess(this);
|
||||
}
|
||||
#endif // MOZ_NUWA_PROCESS
|
||||
|
||||
@ -2780,10 +2820,10 @@ ContentParent::AllocPSharedBufferManagerParent(mozilla::ipc::Transport* aTranspo
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetProcessAttributes(uint64_t* aId,
|
||||
ContentParent::RecvGetProcessAttributes(ContentParentId* aCpId,
|
||||
bool* aIsForApp, bool* aIsForBrowser)
|
||||
{
|
||||
*aId = mChildID;
|
||||
*aCpId = mChildID;
|
||||
*aIsForApp = IsForApp();
|
||||
*aIsForBrowser = mIsForBrowser;
|
||||
|
||||
@ -2831,15 +2871,17 @@ ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
|
||||
}
|
||||
|
||||
PBrowserParent*
|
||||
ContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
|
||||
ContentParent::AllocPBrowserParent(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentParent::AllocPBrowserParent(aContext,
|
||||
return nsIContentParent::AllocPBrowserParent(aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aId,
|
||||
aCpId,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
@ -3825,16 +3867,18 @@ ContentParent::RecvSystemMessageHandled()
|
||||
|
||||
PBrowserParent*
|
||||
ContentParent::SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return PContentParent::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aId,
|
||||
aCpId,
|
||||
aIsForApp,
|
||||
aIsForBrowser);
|
||||
}
|
||||
@ -4133,6 +4177,66 @@ ContentParent::NotifyUpdatedDictionaries()
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ TabId
|
||||
ContentParent::AllocateTabId(const TabId& aOpenerTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aCpId)
|
||||
{
|
||||
TabId tabId;
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
|
||||
tabId = cpm->AllocateTabId(aOpenerTabId, aContext, aCpId);
|
||||
}
|
||||
else {
|
||||
ContentChild::GetSingleton()->SendAllocateTabId(aOpenerTabId,
|
||||
aContext,
|
||||
aCpId,
|
||||
&tabId);
|
||||
}
|
||||
return tabId;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
ContentParent::DeallocateTabId(const TabId& aTabId,
|
||||
const ContentParentId& aCpId)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
ContentProcessManager::GetSingleton()->DeallocateTabId(aCpId,
|
||||
aTabId);
|
||||
}
|
||||
else {
|
||||
ContentChild::GetSingleton()->SendDeallocateTabId(aTabId);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAllocateTabId(const TabId& aOpenerTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aCpId,
|
||||
TabId* aTabId)
|
||||
{
|
||||
*aTabId = AllocateTabId(aOpenerTabId, aContext, aCpId);
|
||||
if (!(*aTabId)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvDeallocateTabId(const TabId& aTabId)
|
||||
{
|
||||
DeallocateTabId(aTabId, this->ChildID());
|
||||
return true;
|
||||
}
|
||||
|
||||
nsTArray<TabContext>
|
||||
ContentParent::GetManagedTabContext()
|
||||
{
|
||||
return Move(ContentProcessManager::GetSingleton()->
|
||||
GetTabContextByContentProcess(this->ChildID()));
|
||||
}
|
||||
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -143,10 +143,12 @@ public:
|
||||
|
||||
virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
|
||||
const hal::ProcessPriority& aPriority,
|
||||
uint64_t* aId,
|
||||
const TabId& aOpenerTabId,
|
||||
ContentParentId* aCpId,
|
||||
bool* aIsForApp,
|
||||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool AnswerBridgeToChildProcess(const uint64_t& id) MOZ_OVERRIDE;
|
||||
bool* aIsForBrowser,
|
||||
TabId* aTabId) MOZ_OVERRIDE;
|
||||
virtual bool AnswerBridgeToChildProcess(const ContentParentId& aCpId) MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
|
||||
|
||||
@ -179,6 +181,13 @@ public:
|
||||
TestShellParent* GetTestShellSingleton();
|
||||
jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
|
||||
|
||||
static TabId
|
||||
AllocateTabId(const TabId& aOpenerTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aCpId);
|
||||
static void
|
||||
DeallocateTabId(const TabId& aTabId, const ContentParentId& aCpId);
|
||||
|
||||
void ReportChildAlreadyBlocked();
|
||||
bool RequestRunToCompletion();
|
||||
|
||||
@ -217,7 +226,7 @@ public:
|
||||
*/
|
||||
void KillHard();
|
||||
|
||||
uint64_t ChildID() MOZ_OVERRIDE { return mChildID; }
|
||||
ContentParentId ChildID() MOZ_OVERRIDE { return mChildID; }
|
||||
const nsString& AppManifestURL() const { return mAppManifestURL; }
|
||||
|
||||
bool IsPreallocated();
|
||||
@ -282,6 +291,14 @@ public:
|
||||
PBlobParent* aActor,
|
||||
const BlobConstructorParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvAllocateTabId(const TabId& aOpenerTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aCpId,
|
||||
TabId* aTabId) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvDeallocateTabId(const TabId& aTabId) MOZ_OVERRIDE;
|
||||
|
||||
nsTArray<TabContext> GetManagedTabContext();
|
||||
protected:
|
||||
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
@ -310,15 +327,18 @@ private:
|
||||
static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement);
|
||||
|
||||
static ContentBridgeParent* CreateContentBridgeParent(const TabContext& aContext,
|
||||
const hal::ProcessPriority& aPriority);
|
||||
const hal::ProcessPriority& aPriority,
|
||||
const TabId& aOpenerTabId,
|
||||
/*out*/ TabId* aTabId);
|
||||
|
||||
// Hide the raw constructor methods since we don't want client code
|
||||
// using them.
|
||||
virtual PBrowserParent* SendPBrowserConstructor(
|
||||
PBrowserParent* actor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
using PContentParent::SendPTestShellConstructor;
|
||||
@ -409,7 +429,7 @@ private:
|
||||
AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvGetProcessAttributes(uint64_t* aId,
|
||||
virtual bool RecvGetProcessAttributes(ContentParentId* aCpId,
|
||||
bool* aIsForApp,
|
||||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline,
|
||||
@ -420,9 +440,10 @@ private:
|
||||
virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) MOZ_OVERRIDE;
|
||||
virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
|
||||
virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent* frame) MOZ_OVERRIDE;
|
||||
@ -692,7 +713,7 @@ private:
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
ContentParent* mOpener;
|
||||
|
||||
uint64_t mChildID;
|
||||
ContentParentId mChildID;
|
||||
int32_t mGeolocationWatchID;
|
||||
|
||||
nsString mAppManifestURL;
|
||||
|
276
dom/ipc/ContentProcessManager.cpp
Normal file
276
dom/ipc/ContentProcessManager.cpp
Normal file
@ -0,0 +1,276 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ContentProcessManager.h"
|
||||
#include "ContentParent.h"
|
||||
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
// XXX need another bug to move this to a common header.
|
||||
#ifdef DISABLE_ASSERTS_FOR_FUZZING
|
||||
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
|
||||
#else
|
||||
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static uint64_t gTabId = 0;
|
||||
|
||||
/* static */
|
||||
StaticAutoPtr<ContentProcessManager>
|
||||
ContentProcessManager::sSingleton;
|
||||
|
||||
/* static */ ContentProcessManager*
|
||||
ContentProcessManager::GetSingleton()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
if (!sSingleton) {
|
||||
sSingleton = new ContentProcessManager();
|
||||
ClearOnShutdown(&sSingleton);
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
void
|
||||
ContentProcessManager::AddContentProcess(ContentParent* aChildCp,
|
||||
const ContentParentId& aParentCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aChildCp);
|
||||
|
||||
ContentProcessInfo info;
|
||||
info.mCp = aChildCp;
|
||||
info.mParentCpId = aParentCpId;
|
||||
mContentParentMap[aChildCp->ChildID()] = info;
|
||||
}
|
||||
|
||||
void
|
||||
ContentProcessManager::RemoveContentProcess(const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mContentParentMap.find(aChildCpId) != mContentParentMap.end());
|
||||
|
||||
mContentParentMap.erase(aChildCpId);
|
||||
for (auto iter = mContentParentMap.begin();
|
||||
iter != mContentParentMap.end();
|
||||
++iter) {
|
||||
if (!iter->second.mChildrenCpId.empty()) {
|
||||
iter->second.mChildrenCpId.erase(aChildCpId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentProcessManager::AddGrandchildProcess(const ContentParentId& aParentCpId,
|
||||
const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto iter = mContentParentMap.find(aParentCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING("Parent process should be already in map!");
|
||||
return false;
|
||||
}
|
||||
iter->second.mChildrenCpId.insert(aChildCpId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentProcessManager::GetParentProcessId(const ContentParentId& aChildCpId,
|
||||
/*out*/ ContentParentId* aParentCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
*aParentCpId = iter->second.mParentCpId;
|
||||
return true;
|
||||
}
|
||||
|
||||
ContentParent*
|
||||
ContentProcessManager::GetContentProcessById(const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second.mCp;
|
||||
}
|
||||
|
||||
nsTArray<ContentParentId>
|
||||
ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<ContentParentId> cpIdArray;
|
||||
auto iter = mContentParentMap.find(aParentCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return Move(cpIdArray);
|
||||
}
|
||||
|
||||
for (auto cpIter = iter->second.mChildrenCpId.begin();
|
||||
cpIter != iter->second.mChildrenCpId.end();
|
||||
++cpIter) {
|
||||
cpIdArray.AppendElement(*cpIter);
|
||||
}
|
||||
|
||||
return Move(cpIdArray);
|
||||
}
|
||||
|
||||
TabId
|
||||
ContentProcessManager::AllocateTabId(const TabId& aOpenerTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return TabId(0);
|
||||
}
|
||||
|
||||
struct RemoteFrameInfo info;
|
||||
|
||||
const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
|
||||
// If it's a PopupIPCTabContext, it's the case that a TabChild want to
|
||||
// open a new tab. aOpenerTabId has to be it's parent frame's opener id.
|
||||
if (appBrowser.type() == IPCTabAppBrowserContext::TPopupIPCTabContext) {
|
||||
auto remoteFrameIter = iter->second.mRemoteFrames.find(aOpenerTabId);
|
||||
if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
|
||||
ASSERT_UNLESS_FUZZING("Failed to find parent frame's opener id.");
|
||||
return TabId(0);
|
||||
}
|
||||
|
||||
info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
|
||||
|
||||
const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
|
||||
MOZ_ASSERT(ipcContext.opener().type() == PBrowserOrId::TTabId);
|
||||
|
||||
remoteFrameIter = iter->second.mRemoteFrames.find(ipcContext.opener().get_TabId());
|
||||
if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
|
||||
ASSERT_UNLESS_FUZZING("Failed to find tab id.");
|
||||
return TabId(0);
|
||||
}
|
||||
|
||||
info.mContext = remoteFrameIter->second.mContext;
|
||||
}
|
||||
else {
|
||||
MaybeInvalidTabContext tc(aContext);
|
||||
if (!tc.IsValid()) {
|
||||
NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
|
||||
"the child process. (%s)",
|
||||
tc.GetInvalidReason()).get());
|
||||
return TabId(0);
|
||||
}
|
||||
info.mOpenerTabId = aOpenerTabId;
|
||||
info.mContext = tc.GetTabContext();
|
||||
}
|
||||
|
||||
mUniqueId = ++gTabId;
|
||||
iter->second.mRemoteFrames[mUniqueId] = info;
|
||||
|
||||
return mUniqueId;
|
||||
}
|
||||
|
||||
void
|
||||
ContentProcessManager::DeallocateTabId(const ContentParentId& aChildCpId,
|
||||
const TabId& aChildTabId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return;
|
||||
}
|
||||
|
||||
auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
|
||||
if (remoteFrameIter != iter->second.mRemoteFrames.end()) {
|
||||
iter->second.mRemoteFrames.erase(aChildTabId);
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<uint64_t>
|
||||
ContentProcessManager::GetAppIdsByContentProcess(const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<uint64_t> appIdArray;
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return Move(appIdArray);
|
||||
}
|
||||
|
||||
for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
|
||||
remoteFrameIter != iter->second.mRemoteFrames.end();
|
||||
++remoteFrameIter) {
|
||||
appIdArray.AppendElement(remoteFrameIter->second.mContext.OwnOrContainingAppId());
|
||||
}
|
||||
|
||||
return Move(appIdArray);
|
||||
}
|
||||
|
||||
nsTArray<TabContext>
|
||||
ContentProcessManager::GetTabContextByContentProcess(const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<TabContext> tabContextArray;
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return Move(tabContextArray);
|
||||
}
|
||||
|
||||
for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
|
||||
remoteFrameIter != iter->second.mRemoteFrames.end();
|
||||
++remoteFrameIter) {
|
||||
tabContextArray.AppendElement(remoteFrameIter->second.mContext);
|
||||
}
|
||||
|
||||
return Move(tabContextArray);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
|
||||
const TabId& aChildTabId,
|
||||
/*out*/TabId* aOpenerTabId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto remoteFrameIter = iter->second.mRemoteFrames.find(aChildTabId);
|
||||
if (NS_WARN_IF(remoteFrameIter == iter->second.mRemoteFrames.end())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
|
||||
*aOpenerTabId = remoteFrameIter->second.mOpenerTabId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
122
dom/ipc/ContentProcessManager.h
Normal file
122
dom/ipc/ContentProcessManager.h
Normal file
@ -0,0 +1,122 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ContentProcessManager_h
|
||||
#define mozilla_dom_ContentProcessManager_h
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
|
||||
struct RemoteFrameInfo
|
||||
{
|
||||
TabId mOpenerTabId;
|
||||
TabContext mContext;
|
||||
};
|
||||
|
||||
struct ContentProcessInfo
|
||||
{
|
||||
ContentParent* mCp;
|
||||
ContentParentId mParentCpId;
|
||||
std::set<ContentParentId> mChildrenCpId;
|
||||
std::map<TabId, RemoteFrameInfo> mRemoteFrames;
|
||||
};
|
||||
|
||||
class ContentProcessManager MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
static ContentProcessManager* GetSingleton();
|
||||
~ContentProcessManager() {MOZ_COUNT_DTOR(ContentProcessManager);};
|
||||
|
||||
/**
|
||||
* Add a new content process into the map.
|
||||
* If aParentCpId is not 0, it's a nested content process.
|
||||
*/
|
||||
void AddContentProcess(ContentParent* aChildCp,
|
||||
const ContentParentId& aParentCpId = ContentParentId(0));
|
||||
/**
|
||||
* Remove the content process by id.
|
||||
*/
|
||||
void RemoveContentProcess(const ContentParentId& aChildCpId);
|
||||
/**
|
||||
* Add a grandchild content process into the map.
|
||||
* aParentCpId must be already added in the map by AddContentProcess().
|
||||
*/
|
||||
bool AddGrandchildProcess(const ContentParentId& aParentCpId,
|
||||
const ContentParentId& aChildCpId);
|
||||
/**
|
||||
* Get the parent process's id by child process's id.
|
||||
* Used to check if a child really belongs to the parent.
|
||||
*/
|
||||
bool GetParentProcessId(const ContentParentId& aChildCpId,
|
||||
/*out*/ ContentParentId* aParentCpId);
|
||||
/**
|
||||
* Return the ContentParent pointer by id.
|
||||
*/
|
||||
ContentParent* GetContentProcessById(const ContentParentId& aChildCpId);
|
||||
|
||||
/**
|
||||
* Return a list of all child process's id.
|
||||
*/
|
||||
nsTArray<ContentParentId>
|
||||
GetAllChildProcessById(const ContentParentId& aParentCpId);
|
||||
|
||||
/**
|
||||
* Allocate a tab id for the given content process's id.
|
||||
* Used when a content process wants to create a new tab. aOpenerTabId and
|
||||
* aContext are saved in RemoteFrameInfo, which is a part of ContentProcessInfo.
|
||||
* We can use the tab id and process id to locate the TabContext for future use.
|
||||
*/
|
||||
TabId AllocateTabId(const TabId& aOpenerTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const ContentParentId& aChildCpId);
|
||||
|
||||
/**
|
||||
* Remove the RemoteFrameInfo by the given process and tab id.
|
||||
*/
|
||||
void DeallocateTabId(const ContentParentId& aChildCpId,
|
||||
const TabId& aChildTabId);
|
||||
|
||||
/**
|
||||
* Get all app ids which are inside the given content process.
|
||||
* XXX Currently not used. Plan to be used for bug 1020186.
|
||||
*/
|
||||
nsTArray<uint64_t>
|
||||
GetAppIdsByContentProcess(const ContentParentId& aChildCpId);
|
||||
|
||||
/**
|
||||
* Get all TabContext which are inside the given content process.
|
||||
* Used for AppProcessChecker to cehck app status.
|
||||
*/
|
||||
nsTArray<TabContext>
|
||||
GetTabContextByContentProcess(const ContentParentId& aChildCpId);
|
||||
|
||||
/**
|
||||
* Query a tab's opener id by the given process and tab id.
|
||||
* XXX Currently not used. Plan to be used for bug 1020179.
|
||||
*/
|
||||
bool GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
|
||||
const TabId& aChildTabId,
|
||||
/*out*/ TabId* aOpenerTabId);
|
||||
|
||||
private:
|
||||
static StaticAutoPtr<ContentProcessManager> sSingleton;
|
||||
TabId mUniqueId;
|
||||
std::map<ContentParentId, ContentProcessInfo> mContentParentMap;
|
||||
|
||||
ContentProcessManager() {MOZ_COUNT_CTOR(ContentProcessManager);};
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif
|
74
dom/ipc/IdType.h
Normal file
74
dom/ipc/IdType.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_IdType_h
|
||||
#define mozilla_dom_IdType_h
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
namespace IPC {
|
||||
template<typename T> struct ParamTraits;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
class TabParent;
|
||||
|
||||
|
||||
template<typename T>
|
||||
class IdType
|
||||
{
|
||||
|
||||
friend struct IPC::ParamTraits<IdType<T>>;
|
||||
|
||||
public:
|
||||
IdType() : mId(0) {}
|
||||
explicit IdType(uint64_t aId) : mId(aId) {}
|
||||
|
||||
operator uint64_t() const { return mId; }
|
||||
|
||||
IdType& operator=(uint64_t aId)
|
||||
{
|
||||
mId = aId;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator<(const IdType& rhs)
|
||||
{
|
||||
return mId < rhs.mId;
|
||||
}
|
||||
private:
|
||||
uint64_t mId;
|
||||
};
|
||||
|
||||
typedef IdType<TabParent> TabId;
|
||||
typedef IdType<ContentParent> ContentParentId;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<typename T>
|
||||
struct ParamTraits<mozilla::dom::IdType<T>>
|
||||
{
|
||||
typedef mozilla::dom::IdType<T> paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mId);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->mId);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
21
dom/ipc/PBrowserOrId.ipdlh
Normal file
21
dom/ipc/PBrowserOrId.ipdlh
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=c: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBrowser;
|
||||
|
||||
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
union PBrowserOrId
|
||||
{
|
||||
nullable PBrowser;
|
||||
TabId;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -67,6 +67,8 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
||||
using mozilla::dom::quota::PersistenceType from "mozilla/dom/quota/PersistenceType.h";
|
||||
using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
|
||||
using gfxIntSize from "nsSize.h";
|
||||
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
|
||||
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
|
||||
|
||||
union ChromeRegistryItem
|
||||
{
|
||||
@ -385,8 +387,8 @@ both:
|
||||
// access to (in the form of a TabChild).
|
||||
//
|
||||
// Keep the last 3 attributes in sync with GetProcessAttributes!
|
||||
async PBrowser(IPCTabContext context, uint32_t chromeFlags,
|
||||
uint64_t id, bool isForApp, bool isForBrowser);
|
||||
async PBrowser(TabId tabId, IPCTabContext context, uint32_t chromeFlags,
|
||||
ContentParentId cpId, bool isForApp, bool isForBrowser);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
||||
@ -520,15 +522,16 @@ parent:
|
||||
* Keep the return values in sync with PBrowser()!
|
||||
*/
|
||||
sync GetProcessAttributes()
|
||||
returns (uint64_t id, bool isForApp, bool isForBrowser);
|
||||
returns (ContentParentId cpId, bool isForApp, bool isForBrowser);
|
||||
sync GetXPCOMProcessAttributes()
|
||||
returns (bool isOffline, nsString[] dictionaries,
|
||||
ClipboardCapabilities clipboardCaps);
|
||||
|
||||
sync CreateChildProcess(IPCTabContext context,
|
||||
ProcessPriority priority)
|
||||
returns (uint64_t id, bool isForApp, bool isForBrowser);
|
||||
intr BridgeToChildProcess(uint64_t id);
|
||||
ProcessPriority priority,
|
||||
TabId openerTabId)
|
||||
returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId);
|
||||
intr BridgeToChildProcess(ContentParentId cpId);
|
||||
|
||||
async PJavaScript();
|
||||
|
||||
@ -743,6 +746,14 @@ parent:
|
||||
returns (int32_t refCnt, int32_t dBRefCnt, int32_t sliceRefCnt,
|
||||
bool result);
|
||||
|
||||
/**
|
||||
* Tell the chrome process there is an creation of PBrowser.
|
||||
* return a system-wise unique Id.
|
||||
*/
|
||||
sync AllocateTabId(TabId openerTabId, IPCTabContext context, ContentParentId cpId)
|
||||
returns (TabId tabId);
|
||||
async DeallocateTabId(TabId tabId);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData,
|
||||
CpowEntry[] aCpows, Principal aPrincipal);
|
||||
|
@ -14,6 +14,8 @@ include JavaScriptTypes;
|
||||
include PTabContext;
|
||||
|
||||
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
|
||||
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
|
||||
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -41,8 +43,8 @@ parent:
|
||||
both:
|
||||
// Both the parent and the child can construct the PBrowser.
|
||||
// See the comment in PContent::PBrowser().
|
||||
async PBrowser(IPCTabContext context, uint32_t chromeFlags,
|
||||
uint64_t id, bool isForApp, bool isForBrowser);
|
||||
async PBrowser(TabId tabId, IPCTabContext context, uint32_t chromeFlags,
|
||||
ContentParentId cpId, bool isForApp, bool isForBrowser);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBrowser;
|
||||
|
||||
include PBrowserOrId;
|
||||
|
||||
using mozilla::layout::ScrollingBehavior from "mozilla/layout/RenderFrameUtils.h";
|
||||
|
||||
@ -27,7 +27,7 @@ namespace dom {
|
||||
// it.
|
||||
struct PopupIPCTabContext
|
||||
{
|
||||
PBrowser opener;
|
||||
PBrowserOrId opener;
|
||||
bool isBrowserElement;
|
||||
};
|
||||
|
||||
|
@ -472,14 +472,15 @@ ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
|
||||
ContentParent* aContentParent)
|
||||
{
|
||||
nsRefPtr<ParticularProcessPriorityManager> pppm;
|
||||
mParticularManagers.Get(aContentParent->ChildID(), &pppm);
|
||||
uint64_t cpId = aContentParent->ChildID();
|
||||
mParticularManagers.Get(cpId, &pppm);
|
||||
if (!pppm) {
|
||||
pppm = new ParticularProcessPriorityManager(aContentParent);
|
||||
pppm->Init();
|
||||
mParticularManagers.Put(aContentParent->ChildID(), pppm);
|
||||
mParticularManagers.Put(cpId, pppm);
|
||||
|
||||
FireTestOnlyObserverNotification("process-created",
|
||||
nsPrintfCString("%lld", aContentParent->ChildID()));
|
||||
nsPrintfCString("%lld", cpId));
|
||||
}
|
||||
|
||||
return pppm.forget();
|
||||
|
@ -733,11 +733,11 @@ private:
|
||||
StaticRefPtr<TabChild> sPreallocatedTab;
|
||||
|
||||
/*static*/
|
||||
std::map<uint64_t, nsRefPtr<TabChild> >&
|
||||
std::map<TabId, nsRefPtr<TabChild>>&
|
||||
TabChild::NestedTabChildMap()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
static std::map<uint64_t, nsRefPtr<TabChild> > sNestedTabChildMap;
|
||||
static std::map<TabId, nsRefPtr<TabChild>> sNestedTabChildMap;
|
||||
return sNestedTabChildMap;
|
||||
}
|
||||
|
||||
@ -750,6 +750,7 @@ TabChild::PreloadSlowThings()
|
||||
// not connected to any manager. Any attempt to use the TabChild
|
||||
// in IPC will crash.
|
||||
nsRefPtr<TabChild> tab(new TabChild(nullptr,
|
||||
TabId(0),
|
||||
TabContext(), /* chromeFlags */ 0));
|
||||
if (!NS_SUCCEEDED(tab->Init()) ||
|
||||
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
|
||||
@ -780,6 +781,7 @@ TabChild::PreloadSlowThings()
|
||||
|
||||
/*static*/ already_AddRefed<TabChild>
|
||||
TabChild::Create(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
const TabContext &aContext,
|
||||
uint32_t aChromeFlags)
|
||||
{
|
||||
@ -793,18 +795,20 @@ TabChild::Create(nsIContentChild* aManager,
|
||||
MOZ_ASSERT(!child->mTriedBrowserInit);
|
||||
|
||||
child->mManager = aManager;
|
||||
child->SetTabId(aTabId);
|
||||
child->SetTabContext(aContext);
|
||||
child->NotifyTabContextUpdated();
|
||||
return child.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> iframe = new TabChild(aManager,
|
||||
nsRefPtr<TabChild> iframe = new TabChild(aManager, aTabId,
|
||||
aContext, aChromeFlags);
|
||||
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
TabChild::TabChild(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags)
|
||||
: TabContext(aContext)
|
||||
@ -827,8 +831,8 @@ TabChild::TabChild(nsIContentChild* aManager,
|
||||
, mIgnoreKeyPressEvent(false)
|
||||
, mActiveElementManager(new ActiveElementManager())
|
||||
, mHasValidInnerSize(false)
|
||||
, mUniqueId(0)
|
||||
, mDestroyed(false)
|
||||
, mUniqueId(aTabId)
|
||||
{
|
||||
if (!sActiveDurationMsSet) {
|
||||
Preferences::AddIntVarCache(&sActiveDurationMs,
|
||||
@ -836,6 +840,12 @@ TabChild::TabChild(nsIContentChild* aManager,
|
||||
sActiveDurationMs);
|
||||
sActiveDurationMsSet = true;
|
||||
}
|
||||
|
||||
// preloaded TabChild should not be added to child map
|
||||
if (mUniqueId) {
|
||||
MOZ_ASSERT(NestedTabChildMap().find(mUniqueId) == NestedTabChildMap().end());
|
||||
NestedTabChildMap()[mUniqueId] = this;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1433,26 +1443,36 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
nsRefPtr<TabChild> newChild =
|
||||
new TabChild(ContentChild::GetSingleton(),
|
||||
/* TabContext */ *this, /* chromeFlags */ 0);
|
||||
if (!NS_SUCCEEDED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
const TabId openerTabId = GetTabId();
|
||||
|
||||
// We must use PopupIPCTabContext here; ContentParent will not accept the
|
||||
// result of this->AsIPCTabContext() (which will be a
|
||||
// BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
|
||||
// reasons.
|
||||
PopupIPCTabContext context;
|
||||
context.openerChild() = this;
|
||||
context.opener() = openerTabId;
|
||||
context.isBrowserElement() = IsBrowserElement();
|
||||
|
||||
ContentChild* cc = static_cast<ContentChild*>(Manager());
|
||||
IPCTabContext ipcContext(context, mScrolling);
|
||||
|
||||
TabId tabId;
|
||||
cc->SendAllocateTabId(openerTabId,
|
||||
ipcContext,
|
||||
cc->GetID(),
|
||||
&tabId);
|
||||
|
||||
nsRefPtr<TabChild> newChild = new TabChild(ContentChild::GetSingleton(), tabId,
|
||||
/* TabContext */ *this, /* chromeFlags */ 0);
|
||||
if (NS_FAILED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
context.opener() = this;
|
||||
unused << Manager()->SendPBrowserConstructor(
|
||||
// We release this ref in DeallocPBrowserChild
|
||||
nsRefPtr<TabChild>(newChild).forget().take(),
|
||||
IPCTabContext(context, mScrolling), /* chromeFlags */ 0,
|
||||
tabId, IPCTabContext(context, mScrolling), /* chromeFlags */ 0,
|
||||
cc->GetID(), cc->IsForApp(), cc->IsForBrowser());
|
||||
|
||||
nsAutoCString spec;
|
||||
@ -1562,8 +1582,8 @@ TabChild::ActorDestroy(ActorDestroyReason why)
|
||||
CompositorChild* compositorChild = static_cast<CompositorChild*>(CompositorChild::Get());
|
||||
compositorChild->CancelNotifyAfterRemotePaint(this);
|
||||
|
||||
if (Id() != 0) {
|
||||
NestedTabChildMap().erase(Id());
|
||||
if (GetTabId() != 0) {
|
||||
NestedTabChildMap().erase(GetTabId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "nsIWebBrowserChrome3.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
|
||||
class nsICachedFileDescriptorListener;
|
||||
class nsIDOMWindowUtils;
|
||||
@ -254,7 +255,7 @@ class TabChild MOZ_FINAL : public TabChildBase,
|
||||
typedef mozilla::layers::ActiveElementManager ActiveElementManager;
|
||||
|
||||
public:
|
||||
static std::map<uint64_t, nsRefPtr<TabChild> >& NestedTabChildMap();
|
||||
static std::map<TabId, nsRefPtr<TabChild>>& NestedTabChildMap();
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -266,28 +267,15 @@ public:
|
||||
|
||||
/** Return a TabChild with the given attributes. */
|
||||
static already_AddRefed<TabChild>
|
||||
Create(nsIContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags);
|
||||
Create(nsIContentChild* aManager, const TabId& aTabId, const TabContext& aContext, uint32_t aChromeFlags);
|
||||
|
||||
bool IsRootContentDocument();
|
||||
|
||||
const uint64_t Id() const {
|
||||
const TabId GetTabId() const {
|
||||
MOZ_ASSERT(mUniqueId != 0);
|
||||
return mUniqueId;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
GetTabChildId(TabChild* aTabChild)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (aTabChild->Id() != 0) {
|
||||
return aTabChild->Id();
|
||||
}
|
||||
static uint64_t sId = 0;
|
||||
sId++;
|
||||
aTabChild->mUniqueId = sId;
|
||||
NestedTabChildMap()[sId] = aTabChild;
|
||||
return sId;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIWEBBROWSERCHROME
|
||||
NS_DECL_NSIWEBBROWSERCHROME2
|
||||
@ -516,7 +504,10 @@ private:
|
||||
*
|
||||
* |aIsBrowserElement| indicates whether we're a browser (but not an app).
|
||||
*/
|
||||
TabChild(nsIContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags);
|
||||
TabChild(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
@ -564,6 +555,14 @@ private:
|
||||
void SendPendingTouchPreventedResponse(bool aPreventDefault,
|
||||
const ScrollableLayerGuid& aGuid);
|
||||
|
||||
void SetTabId(const TabId& aTabId)
|
||||
{
|
||||
MOZ_ASSERT(mUniqueId == 0);
|
||||
|
||||
mUniqueId = aTabId;
|
||||
NestedTabChildMap()[mUniqueId] = this;
|
||||
}
|
||||
|
||||
class CachedFileDescriptorInfo;
|
||||
class CachedFileDescriptorCallbackRunnable;
|
||||
|
||||
@ -606,8 +605,8 @@ private:
|
||||
bool mIgnoreKeyPressEvent;
|
||||
nsRefPtr<ActiveElementManager> mActiveElementManager;
|
||||
bool mHasValidInnerSize;
|
||||
uint64_t mUniqueId;
|
||||
bool mDestroyed;
|
||||
TabId mUniqueId;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
};
|
||||
|
@ -256,8 +256,8 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||
const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
|
||||
|
||||
TabContext *context;
|
||||
if (ipcContext.openerParent()) {
|
||||
context = static_cast<TabParent*>(ipcContext.openerParent());
|
||||
if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
|
||||
context = static_cast<TabParent*>(ipcContext.opener().get_PBrowserParent());
|
||||
if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
|
||||
// If the TabParent corresponds to a browser element, then it can only
|
||||
// open other browser elements, for security reasons. We should have
|
||||
@ -267,8 +267,13 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||
"open a non-browser tab.";
|
||||
return;
|
||||
}
|
||||
} else if (ipcContext.openerChild()) {
|
||||
context = static_cast<TabChild*>(ipcContext.openerChild());
|
||||
} else if (ipcContext.opener().type() == PBrowserOrId::TPBrowserChild) {
|
||||
context = static_cast<TabChild*>(ipcContext.opener().get_PBrowserChild());
|
||||
} else if (ipcContext.opener().type() == PBrowserOrId::TTabId) {
|
||||
// We should never get here because this PopupIPCTabContext is only
|
||||
// used for allocating a new tab id, not for allocating a PBrowser.
|
||||
mInvalidReason = "Child process tried to open an tab without the opener information.";
|
||||
return;
|
||||
} else {
|
||||
// This should be unreachable because PopupIPCTabContext::opener is not a
|
||||
// nullable field.
|
||||
|
@ -218,7 +218,10 @@ NS_IMPL_ISUPPORTS(TabParent,
|
||||
nsISecureBrowserUI,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
TabParent::TabParent(nsIContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags)
|
||||
TabParent::TabParent(nsIContentParent* aManager,
|
||||
const TabId& aTabId,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags)
|
||||
: TabContext(aContext)
|
||||
, mFrameElement(nullptr)
|
||||
, mIMESelectionAnchor(0)
|
||||
@ -242,6 +245,7 @@ TabParent::TabParent(nsIContentParent* aManager, const TabContext& aContext, uin
|
||||
, mAppPackageFileDescriptorSent(false)
|
||||
, mSendOfflineStatus(true)
|
||||
, mChromeFlags(aChromeFlags)
|
||||
, mTabId(aTabId)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
}
|
||||
@ -318,7 +322,13 @@ TabParent::Recv__delete__()
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
Manager()->AsContentParent()->NotifyTabDestroyed(this, mMarkedDestroying);
|
||||
ContentParent::DeallocateTabId(mTabId,
|
||||
Manager()->AsContentParent()->ChildID());
|
||||
}
|
||||
else {
|
||||
ContentParent::DeallocateTabId(mTabId, ContentParentId(0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1648,6 +1658,16 @@ TabParent::GetFrom(nsIContent* aContent)
|
||||
return GetFrom(frameLoader);
|
||||
}
|
||||
|
||||
/*static*/ TabId
|
||||
TabParent::GetTabIdFrom(nsIDocShell *docShell)
|
||||
{
|
||||
nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
|
||||
if (tabChild) {
|
||||
return static_cast<TabChild*>(tabChild.get())->GetTabId();
|
||||
}
|
||||
return TabId(0);
|
||||
}
|
||||
|
||||
RenderFrameParent*
|
||||
TabParent::GetRenderFrame()
|
||||
{
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
#include "mozilla/dom/PFilePickerParent.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
@ -28,6 +29,7 @@ class nsIURI;
|
||||
class nsIWidget;
|
||||
class nsILoadContext;
|
||||
class CpowHolder;
|
||||
class nsIDocShell;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -67,7 +69,10 @@ public:
|
||||
// nsITabParent
|
||||
NS_DECL_NSITABPARENT
|
||||
|
||||
TabParent(nsIContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags);
|
||||
TabParent(nsIContentParent* aManager,
|
||||
const TabId& aTabId,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags);
|
||||
Element* GetOwnerElement() const { return mFrameElement; }
|
||||
void SetOwnerElement(Element* aElement);
|
||||
|
||||
@ -322,6 +327,7 @@ public:
|
||||
|
||||
static TabParent* GetFrom(nsFrameLoader* aFrameLoader);
|
||||
static TabParent* GetFrom(nsIContent* aContent);
|
||||
static TabId GetTabIdFrom(nsIDocShell* docshell);
|
||||
|
||||
nsIContentParent* Manager() { return mManager; }
|
||||
|
||||
@ -333,6 +339,11 @@ public:
|
||||
|
||||
already_AddRefed<nsIWidget> GetWidget() const;
|
||||
|
||||
const TabId GetTabId() const
|
||||
{
|
||||
return mTabId;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
@ -435,6 +446,8 @@ private:
|
||||
uint32_t mChromeFlags;
|
||||
|
||||
nsCOMPtr<nsILoadContext> mLoadContext;
|
||||
|
||||
TabId mTabId;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -11,6 +11,7 @@ EXPORTS += [
|
||||
EXPORTS.mozilla.dom.ipc += [
|
||||
'BlobChild.h',
|
||||
'BlobParent.h',
|
||||
'IdType.h',
|
||||
'nsIRemoteBlob.h',
|
||||
]
|
||||
|
||||
@ -20,6 +21,7 @@ EXPORTS.mozilla.dom += [
|
||||
'ContentChild.h',
|
||||
'ContentParent.h',
|
||||
'ContentProcess.h',
|
||||
'ContentProcessManager.h',
|
||||
'CPOWManagerGetter.h',
|
||||
'CrashReporterChild.h',
|
||||
'CrashReporterParent.h',
|
||||
@ -47,6 +49,7 @@ UNIFIED_SOURCES += [
|
||||
'ContentBridgeParent.cpp',
|
||||
'ContentParent.cpp',
|
||||
'ContentProcess.cpp',
|
||||
'ContentProcessManager.cpp',
|
||||
'CrashReporterParent.cpp',
|
||||
'FilePickerParent.cpp',
|
||||
'nsIContentChild.cpp',
|
||||
@ -77,6 +80,7 @@ IPDL_SOURCES += [
|
||||
'PBlob.ipdl',
|
||||
'PBlobStream.ipdl',
|
||||
'PBrowser.ipdl',
|
||||
'PBrowserOrId.ipdlh',
|
||||
'PColorPicker.ipdl',
|
||||
'PContent.ipdl',
|
||||
'PContentBridge.ipdl',
|
||||
|
@ -50,9 +50,10 @@ nsIContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild)
|
||||
}
|
||||
|
||||
PBrowserChild*
|
||||
nsIContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
nsIContentChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
@ -69,7 +70,7 @@ nsIContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> child =
|
||||
TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
|
||||
TabChild::Create(this, aTabId, tc.GetTabContext(), aChromeFlags);
|
||||
|
||||
// The ref here is released in DeallocPBrowserChild.
|
||||
return child.forget().take();
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef mozilla_dom_nsIContentChild_h
|
||||
#define mozilla_dom_nsIContentChild_h
|
||||
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "mozilla/dom/CPOWManagerGetter.h"
|
||||
@ -52,18 +54,20 @@ public:
|
||||
|
||||
virtual bool
|
||||
SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) = 0;
|
||||
protected:
|
||||
virtual jsipc::PJavaScriptChild* AllocPJavaScriptChild();
|
||||
virtual bool DeallocPJavaScriptChild(jsipc::PJavaScriptChild*);
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aID,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser);
|
||||
virtual bool DeallocPBrowserChild(PBrowserChild*);
|
||||
|
@ -24,6 +24,13 @@
|
||||
|
||||
using namespace mozilla::jsipc;
|
||||
|
||||
// XXX need another bug to move this to a common header.
|
||||
#ifdef DISABLE_ASSERTS_FOR_FUZZING
|
||||
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
|
||||
#else
|
||||
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -74,14 +81,19 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
|
||||
// (PopupIPCTabContext lets the child process prove that it has access to
|
||||
// the app it's trying to open.)
|
||||
if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
|
||||
NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
|
||||
ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
|
||||
TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
|
||||
if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
|
||||
ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type. Aborting AllocPBrowserParent.");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto opener = static_cast<TabParent*>(popupContext.opener().get_PBrowserParent());
|
||||
if (!opener) {
|
||||
NS_ERROR("Got null opener from child; aborting AllocPBrowserParent.");
|
||||
ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -89,7 +101,7 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
|
||||
// isBrowser. Allocating a !isBrowser frame with same app ID would allow
|
||||
// the content to access data it's not supposed to.
|
||||
if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
|
||||
NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
|
||||
ASSERT_UNLESS_FUZZING("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -105,14 +117,14 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
|
||||
}
|
||||
|
||||
PBrowserParent*
|
||||
nsIContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
|
||||
nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
unused << aChromeFlags;
|
||||
unused << aId;
|
||||
unused << aCpId;
|
||||
unused << aIsForApp;
|
||||
unused << aIsForBrowser;
|
||||
|
||||
@ -122,7 +134,7 @@ nsIContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
|
||||
|
||||
MaybeInvalidTabContext tc(aContext);
|
||||
MOZ_ASSERT(tc.IsValid());
|
||||
TabParent* parent = new TabParent(this, tc.GetTabContext(), aChromeFlags);
|
||||
TabParent* parent = new TabParent(this, aTabId, tc.GetTabContext(), aChromeFlags);
|
||||
|
||||
// We release this ref in DeallocPBrowserParent()
|
||||
NS_ADDREF(parent);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef mozilla_dom_nsIContentParent_h
|
||||
#define mozilla_dom_nsIContentParent_h
|
||||
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsISupports.h"
|
||||
#include "mozilla/dom/CPOWManagerGetter.h"
|
||||
@ -49,7 +51,7 @@ public:
|
||||
|
||||
BlobParent* GetOrCreateActorForBlob(File* aBlob);
|
||||
|
||||
virtual uint64_t ChildID() = 0;
|
||||
virtual ContentParentId ChildID() = 0;
|
||||
virtual bool IsForApp() = 0;
|
||||
virtual bool IsForBrowser() = 0;
|
||||
|
||||
@ -59,9 +61,10 @@ public:
|
||||
|
||||
virtual PBrowserParent* SendPBrowserConstructor(
|
||||
PBrowserParent* actor,
|
||||
const TabId& aTabId,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser) NS_WARN_UNUSED_RESULT = 0;
|
||||
|
||||
@ -75,9 +78,10 @@ protected: // IPDL methods
|
||||
virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScriptParent();
|
||||
virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
|
||||
|
||||
virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
|
||||
virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const uint64_t& aId,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForApp,
|
||||
const bool& aIsForBrowser);
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent* frame);
|
||||
|
@ -287,7 +287,7 @@ public:
|
||||
uint64_t aWindowID,
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
nsTArray<nsCOMPtr<nsIMediaDevice> >* aDevices)
|
||||
nsTArray<nsRefPtr<MediaDevice>>* aDevices)
|
||||
: mDevices(aDevices)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
@ -338,7 +338,7 @@ public:
|
||||
private:
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsAutoPtr<nsTArray<nsCOMPtr<nsIMediaDevice> > > mDevices;
|
||||
nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
};
|
||||
@ -371,14 +371,6 @@ protected:
|
||||
*/
|
||||
NS_IMPL_ISUPPORTS(MediaDevice, nsIMediaDevice)
|
||||
|
||||
MediaDevice* MediaDevice::Create(MediaEngineVideoSource* source) {
|
||||
return new VideoDevice(source);
|
||||
}
|
||||
|
||||
MediaDevice* MediaDevice::Create(MediaEngineAudioSource* source) {
|
||||
return new AudioDevice(source);
|
||||
}
|
||||
|
||||
MediaDevice::MediaDevice(MediaEngineSource* aSource)
|
||||
: mHasFacingMode(false)
|
||||
, mSource(aSource) {
|
||||
@ -421,9 +413,50 @@ VideoDevice::VideoDevice(MediaEngineVideoSource* aSource)
|
||||
mMediaSource = aSource->GetMediaSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper functions that implement the constraints algorithm from
|
||||
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5
|
||||
*/
|
||||
|
||||
// Reminder: add handling for new constraints both here and in GetSources below!
|
||||
|
||||
bool
|
||||
VideoDevice::SatisfiesConstraintSets(
|
||||
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
// Interrogate device-inherent properties first.
|
||||
for (size_t i = 0; i < aConstraintSets.Length(); i++) {
|
||||
auto& c = *aConstraintSets[i];
|
||||
if (c.mFacingMode.WasPassed()) {
|
||||
nsString s;
|
||||
GetFacingMode(s);
|
||||
if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
|
||||
static_cast<uint32_t>(c.mFacingMode.Value())].value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nsString s;
|
||||
GetMediaSource(s);
|
||||
if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
|
||||
static_cast<uint32_t>(c.mMediaSource)].value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Forward request to underlying object to interrogate per-mode capabilities.
|
||||
return GetSource()->SatisfiesConstraintSets(aConstraintSets);
|
||||
}
|
||||
|
||||
AudioDevice::AudioDevice(MediaEngineAudioSource* aSource)
|
||||
: MediaDevice(aSource) {}
|
||||
|
||||
bool
|
||||
AudioDevice::SatisfiesConstraintSets(
|
||||
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
// TODO: Add audio-specific constraints
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaDevice::GetName(nsAString& aName)
|
||||
{
|
||||
@ -484,16 +517,16 @@ MediaDevice::GetMediaSource(nsAString& aMediaSource)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaEngineVideoSource*
|
||||
VideoDevice::Source*
|
||||
VideoDevice::GetSource()
|
||||
{
|
||||
return static_cast<MediaEngineVideoSource*>(&*mSource);
|
||||
return static_cast<Source*>(&*mSource);
|
||||
}
|
||||
|
||||
MediaEngineAudioSource*
|
||||
AudioDevice::Source*
|
||||
AudioDevice::GetSource()
|
||||
{
|
||||
return static_cast<MediaEngineAudioSource*>(&*mSource);
|
||||
return static_cast<Source*>(&*mSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -886,61 +919,24 @@ GetInvariant(const OwningBooleanOrMediaTrackConstraints &aUnion) {
|
||||
aUnion.GetAsMediaTrackConstraints() : empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper functions that implement the constraints algorithm from
|
||||
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5
|
||||
*/
|
||||
|
||||
// Reminder: add handling for new constraints both here and in GetSources below!
|
||||
|
||||
static bool SatisfyConstraintSet(const MediaEngineVideoSource *,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
nsIMediaDevice &aCandidate)
|
||||
{
|
||||
nsString s;
|
||||
if (aConstraints.mFacingMode.WasPassed()) {
|
||||
aCandidate.GetFacingMode(s);
|
||||
if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
|
||||
uint32_t(aConstraints.mFacingMode.Value())].value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
aCandidate.GetMediaSource(s);
|
||||
if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
|
||||
uint32_t(aConstraints.mMediaSource)].value)) {
|
||||
return false;
|
||||
}
|
||||
// TODO: Add more video-specific constraints
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SatisfyConstraintSet(const MediaEngineAudioSource *,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
nsIMediaDevice &aCandidate)
|
||||
{
|
||||
// TODO: Add audio-specific constraints
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef nsTArray<nsCOMPtr<nsIMediaDevice> > SourceSet;
|
||||
|
||||
// Source getter that constrains list returned
|
||||
|
||||
template<class SourceType, class ConstraintsType>
|
||||
static SourceSet *
|
||||
template<class DeviceType, class ConstraintsType>
|
||||
static void
|
||||
GetSources(MediaEngine *engine,
|
||||
ConstraintsType &aConstraints,
|
||||
void (MediaEngine::* aEnumerate)(MediaSourceType, nsTArray<nsRefPtr<SourceType> >*),
|
||||
void (MediaEngine::* aEnumerate)(MediaSourceType,
|
||||
nsTArray<nsRefPtr<typename DeviceType::Source> >*),
|
||||
nsTArray<nsRefPtr<DeviceType>>& aResult,
|
||||
const char* media_device_name = nullptr)
|
||||
{
|
||||
ScopedDeletePtr<SourceSet> result(new SourceSet);
|
||||
typedef nsTArray<nsRefPtr<DeviceType>> SourceSet;
|
||||
|
||||
const SourceType * const type = nullptr;
|
||||
nsString deviceName;
|
||||
// First collect sources
|
||||
SourceSet candidateSet;
|
||||
{
|
||||
nsTArray<nsRefPtr<SourceType> > sources;
|
||||
nsTArray<nsRefPtr<typename DeviceType::Source> > sources;
|
||||
// all MediaSourceEnums are contained in MediaSourceType
|
||||
(engine->*aEnumerate)((MediaSourceType)((int)aConstraints.mMediaSource), &sources);
|
||||
/**
|
||||
@ -953,11 +949,11 @@ static SourceSet *
|
||||
sources[i]->GetName(deviceName);
|
||||
if (media_device_name && strlen(media_device_name) > 0) {
|
||||
if (deviceName.EqualsASCII(media_device_name)) {
|
||||
candidateSet.AppendElement(MediaDevice::Create(sources[i]));
|
||||
candidateSet.AppendElement(new DeviceType(sources[i]));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
candidateSet.AppendElement(MediaDevice::Create(sources[i]));
|
||||
candidateSet.AppendElement(new DeviceType(sources[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -970,16 +966,22 @@ static SourceSet *
|
||||
// this media-type. The spec requires these to fail, so getting them out of
|
||||
// the way early provides a necessary invariant for the remaining algorithm
|
||||
// which maximizes code-reuse by ignoring constraints of the other type
|
||||
// (specifically, SatisfyConstraintSet is reused for the advanced algorithm
|
||||
// (specifically, SatisfiesConstraintSets is reused for the advanced algorithm
|
||||
// where the spec requires it to ignore constraints of the other type)
|
||||
return result.forget();
|
||||
return;
|
||||
}
|
||||
|
||||
// Now on to the actual algorithm: First apply required constraints.
|
||||
|
||||
// Stack constraintSets that pass, starting with the required one, because the
|
||||
// whole stack must be re-satisfied each time a capability-set is ruled out
|
||||
// (this avoids storing state and pushing algorithm into the lower-level code).
|
||||
nsTArray<const MediaTrackConstraintSet*> aggregateConstraints;
|
||||
aggregateConstraints.AppendElement(&c.mRequired);
|
||||
|
||||
for (uint32_t i = 0; i < candidateSet.Length();) {
|
||||
// Overloading instead of template specialization keeps things local
|
||||
if (!SatisfyConstraintSet(type, c.mRequired, *candidateSet[i])) {
|
||||
if (!candidateSet[i]->SatisfiesConstraintSets(aggregateConstraints)) {
|
||||
candidateSet.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
@ -1018,9 +1020,10 @@ static SourceSet *
|
||||
auto &array = c.mAdvanced.Value();
|
||||
|
||||
for (int i = 0; i < int(array.Length()); i++) {
|
||||
aggregateConstraints.AppendElement(&array[i]);
|
||||
SourceSet rejects;
|
||||
for (uint32_t j = 0; j < candidateSet.Length();) {
|
||||
if (!SatisfyConstraintSet(type, array[i], *candidateSet[j])) {
|
||||
if (!candidateSet[j]->SatisfiesConstraintSets(aggregateConstraints)) {
|
||||
rejects.AppendElement(candidateSet[j]);
|
||||
candidateSet.RemoveElementAt(j);
|
||||
} else {
|
||||
@ -1028,14 +1031,16 @@ static SourceSet *
|
||||
}
|
||||
}
|
||||
(candidateSet.Length()? tailSet : candidateSet).MoveElementsFrom(rejects);
|
||||
if (!candidateSet.Length()) {
|
||||
aggregateConstraints.RemoveElementAt(aggregateConstraints.Length() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Proper non-ordered handling of nonrequired constraints (Bug 907352)
|
||||
|
||||
result->MoveElementsFrom(candidateSet);
|
||||
result->MoveElementsFrom(tailSet);
|
||||
return result.forget();
|
||||
aResult.MoveElementsFrom(candidateSet);
|
||||
aResult.MoveElementsFrom(tailSet);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1193,29 +1198,28 @@ public:
|
||||
MOZ_ASSERT(mError);
|
||||
if (IsOn(mConstraints.mVideo)) {
|
||||
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
|
||||
ScopedDeletePtr<SourceSet> sources(GetSources(backend, constraints,
|
||||
&MediaEngine::EnumerateVideoDevices));
|
||||
nsTArray<nsRefPtr<VideoDevice>> sources;
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, sources);
|
||||
|
||||
if (!sources->Length()) {
|
||||
if (!sources.Length()) {
|
||||
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Pick the first available device.
|
||||
mVideoDevice = do_QueryObject((*sources)[0]);
|
||||
mVideoDevice = sources[0];
|
||||
LOG(("Selected video device"));
|
||||
}
|
||||
|
||||
if (IsOn(mConstraints.mAudio)) {
|
||||
AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio));
|
||||
ScopedDeletePtr<SourceSet> sources (GetSources(backend, constraints,
|
||||
&MediaEngine::EnumerateAudioDevices));
|
||||
nsTArray<nsRefPtr<AudioDevice>> sources;
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, sources);
|
||||
|
||||
if (!sources->Length()) {
|
||||
if (!sources.Length()) {
|
||||
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Pick the first available device.
|
||||
mAudioDevice = do_QueryObject((*sources)[0]);
|
||||
mAudioDevice = sources[0];
|
||||
LOG(("Selected audio device"));
|
||||
}
|
||||
|
||||
@ -1341,20 +1345,26 @@ public:
|
||||
else
|
||||
backend = mManager->GetBackend(mWindowId);
|
||||
|
||||
typedef nsTArray<nsRefPtr<MediaDevice>> SourceSet;
|
||||
|
||||
ScopedDeletePtr<SourceSet> final(new SourceSet);
|
||||
if (IsOn(mConstraints.mVideo)) {
|
||||
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
|
||||
ScopedDeletePtr<SourceSet> s(GetSources(backend, constraints,
|
||||
&MediaEngine::EnumerateVideoDevices,
|
||||
mLoopbackVideoDevice.get()));
|
||||
final->MoveElementsFrom(*s);
|
||||
nsTArray<nsRefPtr<VideoDevice>> s;
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, s,
|
||||
mLoopbackVideoDevice.get());
|
||||
for (uint32_t i = 0; i < s.Length(); i++) {
|
||||
final->AppendElement(s[i]);
|
||||
}
|
||||
}
|
||||
if (IsOn(mConstraints.mAudio)) {
|
||||
AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio));
|
||||
ScopedDeletePtr<SourceSet> s (GetSources(backend, constraints,
|
||||
&MediaEngine::EnumerateAudioDevices,
|
||||
mLoopbackAudioDevice.get()));
|
||||
final->MoveElementsFrom(*s);
|
||||
nsTArray<nsRefPtr<AudioDevice>> s;
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, s,
|
||||
mLoopbackAudioDevice.get());
|
||||
for (uint32_t i = 0; i < s.Length(); i++) {
|
||||
final->AppendElement(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
|
||||
|
@ -46,6 +46,7 @@ namespace dom {
|
||||
struct MediaStreamConstraints;
|
||||
class NavigatorUserMediaSuccessCallback;
|
||||
class NavigatorUserMediaErrorCallback;
|
||||
struct MediaTrackConstraintSet;
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
@ -501,9 +502,6 @@ public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMEDIADEVICE
|
||||
|
||||
static MediaDevice* Create(MediaEngineVideoSource* source);
|
||||
static MediaDevice* Create(MediaEngineAudioSource* source);
|
||||
|
||||
protected:
|
||||
virtual ~MediaDevice() {}
|
||||
explicit MediaDevice(MediaEngineSource* aSource);
|
||||
@ -518,17 +516,25 @@ protected:
|
||||
class VideoDevice : public MediaDevice
|
||||
{
|
||||
public:
|
||||
explicit VideoDevice(MediaEngineVideoSource* aSource);
|
||||
typedef MediaEngineVideoSource Source;
|
||||
|
||||
explicit VideoDevice(Source* aSource);
|
||||
NS_IMETHOD GetType(nsAString& aType);
|
||||
MediaEngineVideoSource* GetSource();
|
||||
Source* GetSource();
|
||||
bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
|
||||
};
|
||||
|
||||
class AudioDevice : public MediaDevice
|
||||
{
|
||||
public:
|
||||
explicit AudioDevice(MediaEngineAudioSource* aSource);
|
||||
typedef MediaEngineAudioSource Source;
|
||||
|
||||
explicit AudioDevice(Source* aSource);
|
||||
NS_IMETHOD GetType(nsAString& aType);
|
||||
MediaEngineAudioSource* GetSource();
|
||||
Source* GetSource();
|
||||
bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
|
||||
};
|
||||
|
||||
// we could add MediaManager if needed
|
||||
|
@ -4,52 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsRenderingContext.h"
|
||||
#include <string.h> // for strlen
|
||||
#include <algorithm> // for min
|
||||
#include "gfxColor.h" // for gfxRGBA
|
||||
#include "gfxMatrix.h" // for gfxMatrix
|
||||
#include "gfxPoint.h" // for gfxPoint, gfxSize
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxTypes.h" // for gfxFloat
|
||||
#include "mozilla/gfx/BasePoint.h" // for BasePoint
|
||||
#include "mozilla/mozalloc.h" // for operator delete[], etc
|
||||
#include "nsBoundingMetrics.h" // for nsBoundingMetrics
|
||||
#include "nsCharTraits.h" // for NS_IS_LOW_SURROGATE
|
||||
#include "nsDebug.h" // for NS_ERROR
|
||||
#include "nsPoint.h" // for nsPoint
|
||||
#include "nsRect.h" // for nsRect, nsIntRect
|
||||
#include "nsRegion.h" // for nsIntRegionRectIterator, etc
|
||||
|
||||
// Hard limit substring lengths to 8000 characters ... this lets us statically
|
||||
// size the cluster buffer array in FindSafeLength
|
||||
#define MAX_GFX_TEXT_BUF_SIZE 8000
|
||||
|
||||
/*static*/ int32_t
|
||||
nsRenderingContext::FindSafeLength(const char16_t *aString, uint32_t aLength,
|
||||
uint32_t aMaxChunkLength)
|
||||
{
|
||||
if (aLength <= aMaxChunkLength)
|
||||
return aLength;
|
||||
|
||||
int32_t len = aMaxChunkLength;
|
||||
|
||||
// Ensure that we don't break inside a surrogate pair
|
||||
while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
|
||||
len--;
|
||||
}
|
||||
if (len == 0) {
|
||||
// We don't want our caller to go into an infinite loop, so don't
|
||||
// return zero. It's hard to imagine how we could actually get here
|
||||
// unless there are languages that allow clusters of arbitrary size.
|
||||
// If there are and someone feeds us a 500+ character cluster, too
|
||||
// bad.
|
||||
return aMaxChunkLength;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// nsRenderingContext
|
||||
|
||||
void
|
||||
nsRenderingContext::Init(gfxContext *aThebesContext)
|
||||
@ -63,77 +17,3 @@ nsRenderingContext::Init(DrawTarget *aDrawTarget)
|
||||
{
|
||||
Init(new gfxContext(aDrawTarget));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// text
|
||||
//
|
||||
|
||||
void
|
||||
nsRenderingContext::SetTextRunRTL(bool aIsRTL)
|
||||
{
|
||||
mFontMetrics->SetTextRunRTL(aIsRTL);
|
||||
}
|
||||
|
||||
void
|
||||
nsRenderingContext::SetFont(nsFontMetrics *aFontMetrics)
|
||||
{
|
||||
mFontMetrics = aFontMetrics;
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsRenderingContext::GetMaxChunkLength()
|
||||
{
|
||||
return std::min(mFontMetrics->GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsRenderingContext::GetWidth(char16_t aC)
|
||||
{
|
||||
return GetWidth(&aC, 1);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsRenderingContext::GetWidth(const nsString& aString)
|
||||
{
|
||||
return GetWidth(aString.get(), aString.Length());
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsRenderingContext::GetWidth(const char16_t *aString, uint32_t aLength)
|
||||
{
|
||||
uint32_t maxChunkLength = GetMaxChunkLength();
|
||||
nscoord width = 0;
|
||||
while (aLength > 0) {
|
||||
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
width += mFontMetrics->GetWidth(aString, len, this);
|
||||
aLength -= len;
|
||||
aString += len;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
nsBoundingMetrics
|
||||
nsRenderingContext::GetBoundingMetrics(const char16_t* aString,
|
||||
uint32_t aLength)
|
||||
{
|
||||
uint32_t maxChunkLength = GetMaxChunkLength();
|
||||
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
// Assign directly in the first iteration. This ensures that
|
||||
// negative ascent/descent can be returned and the left bearing
|
||||
// is properly initialized.
|
||||
nsBoundingMetrics totalMetrics
|
||||
= mFontMetrics->GetBoundingMetrics(aString, len, this);
|
||||
aLength -= len;
|
||||
aString += len;
|
||||
|
||||
while (aLength > 0) {
|
||||
len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
nsBoundingMetrics metrics
|
||||
= mFontMetrics->GetBoundingMetrics(aString, len, this);
|
||||
totalMetrics += metrics;
|
||||
aLength -= len;
|
||||
aString += len;
|
||||
}
|
||||
return totalMetrics;
|
||||
}
|
||||
|
@ -6,31 +6,22 @@
|
||||
#ifndef NSRENDERINGCONTEXT__H__
|
||||
#define NSRENDERINGCONTEXT__H__
|
||||
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include <sys/types.h> // for int32_t
|
||||
#include "gfxContext.h" // for gfxContext
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsBoundingMetrics.h" // for nsBoundingMetrics
|
||||
#include "nsColor.h" // for nscolor
|
||||
#include "nsCoord.h" // for nscoord, NSToIntRound
|
||||
#include "nsFontMetrics.h" // for nsFontMetrics
|
||||
#include "nsISupports.h" // for NS_INLINE_DECL_REFCOUNTING, etc
|
||||
#include "nsString.h" // for nsString
|
||||
#include "nscore.h" // for char16_t
|
||||
#include "gfxContext.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsRefPtr.h"
|
||||
|
||||
class nsIntRegion;
|
||||
struct nsPoint;
|
||||
struct nsRect;
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
}
|
||||
}
|
||||
|
||||
class nsRenderingContext MOZ_FINAL
|
||||
{
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
|
||||
public:
|
||||
nsRenderingContext() {}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(nsRenderingContext)
|
||||
|
||||
void Init(gfxContext* aThebesContext);
|
||||
@ -40,31 +31,11 @@ public:
|
||||
gfxContext *ThebesContext() { return mThebes; }
|
||||
DrawTarget *GetDrawTarget() { return mThebes->GetDrawTarget(); }
|
||||
|
||||
// Text
|
||||
|
||||
void SetFont(nsFontMetrics *aFontMetrics);
|
||||
nsFontMetrics *FontMetrics() { return mFontMetrics; } // may be null
|
||||
|
||||
void SetTextRunRTL(bool aIsRTL);
|
||||
|
||||
nscoord GetWidth(char16_t aC);
|
||||
nscoord GetWidth(const nsString& aString);
|
||||
nscoord GetWidth(const char16_t *aString, uint32_t aLength);
|
||||
|
||||
nsBoundingMetrics GetBoundingMetrics(const char16_t *aString,
|
||||
uint32_t aLength);
|
||||
|
||||
int32_t GetMaxChunkLength();
|
||||
static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
|
||||
uint32_t aMaxChunkLength);
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~nsRenderingContext()
|
||||
{
|
||||
}
|
||||
~nsRenderingContext() {}
|
||||
|
||||
nsRefPtr<gfxContext> mThebes;
|
||||
nsRefPtr<nsFontMetrics> mFontMetrics;
|
||||
};
|
||||
|
||||
#endif // NSRENDERINGCONTEXT__H__
|
||||
|
13
js/src/jit-test/tests/ion/bug1066659.js
Normal file
13
js/src/jit-test/tests/ion/bug1066659.js
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
function reportCompare (expected, actual) {
|
||||
var actual_t = typeof actual;
|
||||
var output = "";
|
||||
output += "x" + actual_t + " ";
|
||||
expected != actual;
|
||||
output += undefined;
|
||||
}
|
||||
gczeal(7,1);
|
||||
for (var i=0; i<900; i++) {
|
||||
reportCompare("abc", function() {});
|
||||
reportCompare(null, 10);
|
||||
}
|
@ -119,6 +119,10 @@ class CompactBufferWriter
|
||||
MOZ_ASSERT(byte <= 0xFF);
|
||||
enoughMemory_ &= buffer_.append(byte);
|
||||
}
|
||||
void writeByteAt(uint32_t pos, uint32_t byte) {
|
||||
MOZ_ASSERT(byte <= 0xFF);
|
||||
buffer_[pos] = byte;
|
||||
}
|
||||
void writeUnsigned(uint32_t value) {
|
||||
do {
|
||||
uint8_t byte = ((value & 0x7F) << 1) | (value > 0x7F);
|
||||
@ -126,6 +130,15 @@ class CompactBufferWriter
|
||||
value >>= 7;
|
||||
} while (value);
|
||||
}
|
||||
void writeUnsignedAt(uint32_t pos, uint32_t value, uint32_t original) {
|
||||
MOZ_ASSERT(value <= original);
|
||||
do {
|
||||
uint8_t byte = ((value & 0x7F) << 1) | (original > 0x7F);
|
||||
writeByteAt(pos++, byte);
|
||||
value >>= 7;
|
||||
original >>= 7;
|
||||
} while (original);
|
||||
}
|
||||
void writeSigned(int32_t v) {
|
||||
bool isNegative = v < 0;
|
||||
uint32_t value = isNegative ? -v : v;
|
||||
|
@ -275,7 +275,7 @@ class RInstructionResults
|
||||
bool initialized_;
|
||||
|
||||
public:
|
||||
RInstructionResults(IonJSFrameLayout *fp);
|
||||
explicit RInstructionResults(IonJSFrameLayout *fp);
|
||||
RInstructionResults(RInstructionResults&& src);
|
||||
|
||||
RInstructionResults& operator=(RInstructionResults&& rhs);
|
||||
@ -310,7 +310,7 @@ struct MaybeReadFallback
|
||||
const NoGCValue unreadablePlaceholder_;
|
||||
const FallbackConsequence consequence;
|
||||
|
||||
MaybeReadFallback(const Value &placeholder = UndefinedValue())
|
||||
explicit MaybeReadFallback(const Value &placeholder = UndefinedValue())
|
||||
: maybeCx(nullptr),
|
||||
activation(nullptr),
|
||||
frame(nullptr),
|
||||
|
@ -233,7 +233,7 @@ class LSimdSignMaskX4 : public LInstructionHelper<1, 1, 0>
|
||||
class LSimdSwizzleBase : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LSimdSwizzleBase(const LAllocation &base)
|
||||
explicit LSimdSwizzleBase(const LAllocation &base)
|
||||
{
|
||||
setOperand(0, base);
|
||||
}
|
||||
@ -257,7 +257,7 @@ class LSimdSwizzleI : public LSimdSwizzleBase
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SimdSwizzleI);
|
||||
LSimdSwizzleI(const LAllocation &base) : LSimdSwizzleBase(base)
|
||||
explicit LSimdSwizzleI(const LAllocation &base) : LSimdSwizzleBase(base)
|
||||
{}
|
||||
};
|
||||
// Shuffles a float32x4 into another float32x4 vector.
|
||||
@ -265,7 +265,7 @@ class LSimdSwizzleF : public LSimdSwizzleBase
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SimdSwizzleF);
|
||||
LSimdSwizzleF(const LAllocation &base) : LSimdSwizzleBase(base)
|
||||
explicit LSimdSwizzleF(const LAllocation &base) : LSimdSwizzleBase(base)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -4203,7 +4203,7 @@ class LTypedObjectUnsizedLength : public LInstructionHelper<1, 1, 0>
|
||||
public:
|
||||
LIR_HEADER(TypedObjectUnsizedLength)
|
||||
|
||||
LTypedObjectUnsizedLength(const LAllocation &object) {
|
||||
explicit LTypedObjectUnsizedLength(const LAllocation &object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
const LAllocation *object() {
|
||||
|
@ -1234,12 +1234,13 @@ class LSnapshot : public TempObject
|
||||
};
|
||||
|
||||
struct SafepointNunboxEntry {
|
||||
uint32_t typeVreg;
|
||||
LAllocation type;
|
||||
LAllocation payload;
|
||||
|
||||
SafepointNunboxEntry() { }
|
||||
SafepointNunboxEntry(LAllocation type, LAllocation payload)
|
||||
: type(type), payload(payload)
|
||||
SafepointNunboxEntry(uint32_t typeVreg, LAllocation type, LAllocation payload)
|
||||
: typeVreg(typeVreg), type(type), payload(payload)
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -1322,7 +1323,6 @@ class LSafepoint : public TempObject
|
||||
, valueSlots_(alloc)
|
||||
#ifdef JS_NUNBOX32
|
||||
, nunboxParts_(alloc)
|
||||
, partialNunboxes_(0)
|
||||
#endif
|
||||
, slotsOrElementsSlots_(alloc)
|
||||
{
|
||||
@ -1441,8 +1441,8 @@ class LSafepoint : public TempObject
|
||||
|
||||
#ifdef JS_NUNBOX32
|
||||
|
||||
bool addNunboxParts(LAllocation type, LAllocation payload) {
|
||||
bool result = nunboxParts_.append(NunboxEntry(type, payload));
|
||||
bool addNunboxParts(uint32_t typeVreg, LAllocation type, LAllocation payload) {
|
||||
bool result = nunboxParts_.append(NunboxEntry(typeVreg, type, payload));
|
||||
if (result)
|
||||
assertInvariants();
|
||||
return result;
|
||||
@ -1454,52 +1454,49 @@ class LSafepoint : public TempObject
|
||||
return true;
|
||||
if (nunboxParts_[i].type == LUse(typeVreg, LUse::ANY)) {
|
||||
nunboxParts_[i].type = type;
|
||||
partialNunboxes_--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
partialNunboxes_++;
|
||||
|
||||
// vregs for nunbox pairs are adjacent, with the type coming first.
|
||||
uint32_t payloadVreg = typeVreg + 1;
|
||||
bool result = nunboxParts_.append(NunboxEntry(type, LUse(payloadVreg, LUse::ANY)));
|
||||
bool result = nunboxParts_.append(NunboxEntry(typeVreg, type, LUse(payloadVreg, LUse::ANY)));
|
||||
if (result)
|
||||
assertInvariants();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool hasNunboxType(LAllocation type) const {
|
||||
if (type.isArgument())
|
||||
return true;
|
||||
if (type.isStackSlot() && hasValueSlot(type.toStackSlot()->slot() + 1))
|
||||
return true;
|
||||
for (size_t i = 0; i < nunboxParts_.length(); i++) {
|
||||
if (nunboxParts_[i].type == type)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool addNunboxPayload(uint32_t payloadVreg, LAllocation payload) {
|
||||
for (size_t i = 0; i < nunboxParts_.length(); i++) {
|
||||
if (nunboxParts_[i].payload == payload)
|
||||
return true;
|
||||
if (nunboxParts_[i].payload == LUse(payloadVreg, LUse::ANY)) {
|
||||
partialNunboxes_--;
|
||||
nunboxParts_[i].payload = payload;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
partialNunboxes_++;
|
||||
|
||||
// vregs for nunbox pairs are adjacent, with the type coming first.
|
||||
uint32_t typeVreg = payloadVreg - 1;
|
||||
bool result = nunboxParts_.append(NunboxEntry(LUse(typeVreg, LUse::ANY), payload));
|
||||
bool result = nunboxParts_.append(NunboxEntry(typeVreg, LUse(typeVreg, LUse::ANY), payload));
|
||||
if (result)
|
||||
assertInvariants();
|
||||
return result;
|
||||
}
|
||||
|
||||
LAllocation findTypeAllocation(uint32_t typeVreg) {
|
||||
// Look for some allocation for the specified type vreg, to go with a
|
||||
// partial nunbox entry for the payload. Note that we don't need to
|
||||
// look at the value slots in the safepoint, as these aren't used by
|
||||
// register allocators which add partial nunbox entries.
|
||||
for (size_t i = 0; i < nunboxParts_.length(); i++) {
|
||||
if (nunboxParts_[i].typeVreg == typeVreg && !nunboxParts_[i].type.isUse())
|
||||
return nunboxParts_[i].type;
|
||||
}
|
||||
return LUse(typeVreg, LUse::ANY);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool hasNunboxPayload(LAllocation payload) const {
|
||||
if (payload.isArgument())
|
||||
return true;
|
||||
@ -1511,15 +1508,12 @@ class LSafepoint : public TempObject
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NunboxList &nunboxParts() {
|
||||
return nunboxParts_;
|
||||
}
|
||||
|
||||
uint32_t partialNunboxes() {
|
||||
return partialNunboxes_;
|
||||
}
|
||||
|
||||
#elif JS_PUNBOX64
|
||||
|
||||
void addValueRegister(Register reg) {
|
||||
|
@ -609,16 +609,20 @@ LinearScanAllocator::populateSafepoints()
|
||||
// in a register, or the payload is in a register. In
|
||||
// both cases, we don't have a contiguous spill so we
|
||||
// add a torn entry.
|
||||
if (!safepoint->addNunboxParts(*typeAlloc, *payloadAlloc))
|
||||
uint32_t typeVreg = type->def()->virtualRegister();
|
||||
if (!safepoint->addNunboxParts(typeVreg, *typeAlloc, *payloadAlloc))
|
||||
return false;
|
||||
|
||||
// If the nunbox is stored in multiple places, we need to
|
||||
// trace all of them to allow the GC to relocate objects.
|
||||
if (payloadAlloc->isGeneralReg() && isSpilledAt(payloadInterval, inputOf(ins))) {
|
||||
if (!safepoint->addNunboxParts(*typeAlloc, *payload->canonicalSpill()))
|
||||
if (!safepoint->addNunboxParts(typeVreg, *typeAlloc,
|
||||
*payload->canonicalSpill()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -299,18 +299,29 @@ SafepointWriter::writeNunboxParts(LSafepoint *safepoint)
|
||||
// Safepoints are permitted to have partially filled in entries for nunboxes,
|
||||
// provided that only the type is live and not the payload. Omit these from
|
||||
// the written safepoint.
|
||||
uint32_t partials = safepoint->partialNunboxes();
|
||||
|
||||
stream_.writeUnsigned(entries.length() - partials);
|
||||
size_t pos = stream_.length();
|
||||
stream_.writeUnsigned(entries.length());
|
||||
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < entries.length(); i++) {
|
||||
SafepointNunboxEntry &entry = entries[i];
|
||||
|
||||
if (entry.type.isUse() || entry.payload.isUse()) {
|
||||
partials--;
|
||||
if (entry.payload.isUse()) {
|
||||
// No allocation associated with the payload.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.type.isUse()) {
|
||||
// No allocation associated with the type. Look for another
|
||||
// safepoint entry with an allocation for the type.
|
||||
entry.type = safepoint->findTypeAllocation(entry.typeVreg);
|
||||
if (entry.type.isUse())
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
uint16_t header = 0;
|
||||
|
||||
header |= (AllocationToPartKind(entry.type) << TYPE_KIND_SHIFT);
|
||||
@ -337,7 +348,8 @@ SafepointWriter::writeNunboxParts(LSafepoint *safepoint)
|
||||
stream_.writeUnsigned(payloadVal);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(partials == 0);
|
||||
// Update the stream with the actual number of safepoint entries written.
|
||||
stream_.writeUnsignedAt(pos, count, entries.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4686,7 +4686,7 @@ GCRuntime::endMarkingZoneGroup()
|
||||
JSRuntime *runtime;\
|
||||
virtual void run() MOZ_OVERRIDE;\
|
||||
public:\
|
||||
name (JSRuntime *rt) : runtime(rt) {}\
|
||||
explicit name (JSRuntime *rt) : runtime(rt) {}\
|
||||
}
|
||||
MAKE_GC_PARALLEL_TASK(SweepAtomsTask);
|
||||
MAKE_GC_PARALLEL_TASK(SweepInnerViewsTask);
|
||||
|
@ -1106,12 +1106,12 @@ struct TypeObject : public gc::TenuredCell
|
||||
}
|
||||
|
||||
void addFlags(TypeObjectFlags flags) {
|
||||
MOZ_ASSERT(!needsSweep());
|
||||
maybeSweep(nullptr);
|
||||
flags_ |= flags;
|
||||
}
|
||||
|
||||
void clearFlags(TypeObjectFlags flags) {
|
||||
MOZ_ASSERT(!needsSweep());
|
||||
maybeSweep(nullptr);
|
||||
flags_ &= ~flags;
|
||||
}
|
||||
|
||||
|
@ -308,13 +308,18 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
||||
makeTypedInstance(JSContext *cx, uint32_t len, gc::AllocKind allocKind)
|
||||
{
|
||||
const Class *clasp = instanceClass();
|
||||
bool largeAllocation = len * sizeof(NativeType) >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH;
|
||||
if (len * sizeof(NativeType) >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH) {
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, clasp, allocKind, SingletonObject);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
return &obj->as<TypedArrayObject>();
|
||||
}
|
||||
|
||||
jsbytecode *pc;
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
NewObjectKind newKind = script
|
||||
? UseNewTypeForInitializer(script, pc, clasp)
|
||||
: (largeAllocation ? SingletonObject : GenericObject);
|
||||
: GenericObject;
|
||||
RootedObject obj(cx, NewBuiltinClassInstance(cx, clasp, allocKind, newKind));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsBidiPresUtils.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsRenderingContext.h"
|
||||
@ -2054,42 +2055,51 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor : public nsBidiPresUtils::BidiProcessor {
|
||||
class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor MOZ_FINAL
|
||||
: public nsBidiPresUtils::BidiProcessor
|
||||
{
|
||||
public:
|
||||
nsIRenderingContextBidiProcessor(nsRenderingContext* aCtx,
|
||||
nsRenderingContext* aTextRunConstructionContext,
|
||||
nsFontMetrics* aFontMetrics,
|
||||
const nsPoint& aPt)
|
||||
: mCtx(aCtx), mTextRunConstructionContext(aTextRunConstructionContext), mPt(aPt) { }
|
||||
: mCtx(aCtx)
|
||||
, mTextRunConstructionContext(aTextRunConstructionContext)
|
||||
, mFontMetrics(aFontMetrics)
|
||||
, mPt(aPt)
|
||||
{}
|
||||
|
||||
~nsIRenderingContextBidiProcessor()
|
||||
{
|
||||
mCtx->SetTextRunRTL(false);
|
||||
mFontMetrics->SetTextRunRTL(false);
|
||||
}
|
||||
|
||||
virtual void SetText(const char16_t* aText,
|
||||
int32_t aLength,
|
||||
nsBidiDirection aDirection) MOZ_OVERRIDE
|
||||
{
|
||||
mTextRunConstructionContext->SetTextRunRTL(aDirection==NSBIDI_RTL);
|
||||
mFontMetrics->SetTextRunRTL(aDirection==NSBIDI_RTL);
|
||||
mText = aText;
|
||||
mLength = aLength;
|
||||
}
|
||||
|
||||
virtual nscoord GetWidth() MOZ_OVERRIDE
|
||||
{
|
||||
return mTextRunConstructionContext->GetWidth(mText, mLength);
|
||||
return nsLayoutUtils::AppUnitWidthOfString(mText, mLength, *mFontMetrics,
|
||||
*mTextRunConstructionContext);
|
||||
}
|
||||
|
||||
virtual void DrawText(nscoord aXOffset,
|
||||
nscoord) MOZ_OVERRIDE
|
||||
{
|
||||
mCtx->FontMetrics()->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y,
|
||||
mFontMetrics->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y,
|
||||
mCtx, mTextRunConstructionContext);
|
||||
}
|
||||
|
||||
private:
|
||||
nsRenderingContext* mCtx;
|
||||
nsRenderingContext* mTextRunConstructionContext;
|
||||
nsFontMetrics* mFontMetrics;
|
||||
nsPoint mPt;
|
||||
const char16_t* mText;
|
||||
int32_t mLength;
|
||||
@ -2101,6 +2111,7 @@ nsresult nsBidiPresUtils::ProcessTextForRenderingContext(const char16_t* a
|
||||
nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsRenderingContext& aTextRunConstructionContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
Mode aMode,
|
||||
nscoord aX,
|
||||
nscoord aY,
|
||||
@ -2108,7 +2119,10 @@ nsresult nsBidiPresUtils::ProcessTextForRenderingContext(const char16_t* a
|
||||
int32_t aPosResolveCount,
|
||||
nscoord* aWidth)
|
||||
{
|
||||
nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY));
|
||||
nsIRenderingContextBidiProcessor processor(&aRenderingContext,
|
||||
&aTextRunConstructionContext,
|
||||
&aFontMetrics,
|
||||
nsPoint(aX, aY));
|
||||
nsBidi bidiEngine;
|
||||
return ProcessText(aText, aLength, aBaseLevel, aPresContext, processor,
|
||||
aMode, aPosResolve, aPosResolveCount, aWidth, &bidiEngine);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
struct BidiParagraphData;
|
||||
struct BidiLineData;
|
||||
class nsFontMetrics;
|
||||
class nsIFrame;
|
||||
class nsBlockFrame;
|
||||
class nsPresContext;
|
||||
@ -206,24 +207,29 @@ public:
|
||||
nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsRenderingContext& aTextRunConstructionContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nscoord aX,
|
||||
nscoord aY,
|
||||
nsBidiPositionResolve* aPosResolve = nullptr,
|
||||
int32_t aPosResolveCount = 0)
|
||||
{
|
||||
return ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext, aRenderingContext,
|
||||
aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
|
||||
aTextRunConstructionContext,
|
||||
aFontMetrics,
|
||||
MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
|
||||
}
|
||||
|
||||
static nscoord MeasureTextWidth(const char16_t* aText,
|
||||
int32_t aLength,
|
||||
nsBidiLevel aBaseLevel,
|
||||
nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext)
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics)
|
||||
{
|
||||
nscoord length;
|
||||
nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext,
|
||||
aRenderingContext, aRenderingContext,
|
||||
aFontMetrics,
|
||||
MODE_MEASURE, 0, 0, nullptr, 0, &length);
|
||||
return NS_SUCCEEDED(rv) ? length : 0;
|
||||
}
|
||||
@ -360,6 +366,7 @@ private:
|
||||
nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsRenderingContext& aTextRunConstructionContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
Mode aMode,
|
||||
nscoord aX, // DRAW only
|
||||
nscoord aY, // DRAW only
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "gfxUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsIFrame.h"
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "nsCharTraits.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
@ -3185,6 +3187,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
*/
|
||||
bool
|
||||
nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
const char16_t* aText,
|
||||
int32_t aBaseWidth,
|
||||
int32_t aBaseInx,
|
||||
@ -3197,7 +3200,9 @@ nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
|
||||
int32_t range = aEndInx - aStartInx;
|
||||
if ((range == 1) || (range == 2 && NS_IS_HIGH_SURROGATE(aText[aStartInx]))) {
|
||||
aIndex = aStartInx + aBaseInx;
|
||||
aTextWidth = aRendContext->GetWidth(aText, aIndex);
|
||||
aTextWidth = nsLayoutUtils::AppUnitWidthOfString(aText, aIndex,
|
||||
aFontMetrics,
|
||||
*aRendContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3207,7 +3212,9 @@ nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
|
||||
if (NS_IS_HIGH_SURROGATE(aText[inx-1]))
|
||||
inx++;
|
||||
|
||||
int32_t textWidth = aRendContext->GetWidth(aText, inx);
|
||||
int32_t textWidth = nsLayoutUtils::AppUnitWidthOfString(aText, inx,
|
||||
aFontMetrics,
|
||||
*aRendContext);
|
||||
|
||||
int32_t fullWidth = aBaseWidth + textWidth;
|
||||
if (fullWidth == aCursorPos) {
|
||||
@ -3216,12 +3223,16 @@ nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
|
||||
return true;
|
||||
} else if (aCursorPos < fullWidth) {
|
||||
aTextWidth = aBaseWidth;
|
||||
if (BinarySearchForPosition(aRendContext, aText, aBaseWidth, aBaseInx, aStartInx, inx, aCursorPos, aIndex, aTextWidth)) {
|
||||
if (BinarySearchForPosition(aRendContext, aFontMetrics, aText, aBaseWidth,
|
||||
aBaseInx, aStartInx, inx, aCursorPos, aIndex,
|
||||
aTextWidth)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
aTextWidth = fullWidth;
|
||||
if (BinarySearchForPosition(aRendContext, aText, aBaseWidth, aBaseInx, inx, aEndInx, aCursorPos, aIndex, aTextWidth)) {
|
||||
if (BinarySearchForPosition(aRendContext, aFontMetrics, aText, aBaseWidth,
|
||||
aBaseInx, inx, aEndInx, aCursorPos, aIndex,
|
||||
aTextWidth)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -4628,8 +4639,94 @@ nsLayoutUtils::GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
|
||||
return aContext->DeviceToUser(putativeRect.TopLeft()).y * appUnitsPerDevUnit;
|
||||
}
|
||||
|
||||
// Hard limit substring lengths to 8000 characters ... this lets us statically
|
||||
// size the cluster buffer array in FindSafeLength
|
||||
#define MAX_GFX_TEXT_BUF_SIZE 8000
|
||||
|
||||
static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
|
||||
uint32_t aMaxChunkLength)
|
||||
{
|
||||
if (aLength <= aMaxChunkLength)
|
||||
return aLength;
|
||||
|
||||
int32_t len = aMaxChunkLength;
|
||||
|
||||
// Ensure that we don't break inside a surrogate pair
|
||||
while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
|
||||
len--;
|
||||
}
|
||||
if (len == 0) {
|
||||
// We don't want our caller to go into an infinite loop, so don't
|
||||
// return zero. It's hard to imagine how we could actually get here
|
||||
// unless there are languages that allow clusters of arbitrary size.
|
||||
// If there are and someone feeds us a 500+ character cluster, too
|
||||
// bad.
|
||||
return aMaxChunkLength;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int32_t GetMaxChunkLength(nsFontMetrics& aFontMetrics)
|
||||
{
|
||||
return std::min(aFontMetrics.GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsLayoutUtils::AppUnitWidthOfString(const nsString& aString,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext)
|
||||
{
|
||||
return AppUnitWidthOfString(aString.get(), aString.Length(),
|
||||
aFontMetrics, aContext);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsLayoutUtils::AppUnitWidthOfString(const char16_t *aString,
|
||||
uint32_t aLength,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext)
|
||||
{
|
||||
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
|
||||
nscoord width = 0;
|
||||
while (aLength > 0) {
|
||||
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
width += aFontMetrics.GetWidth(aString, len, &aContext);
|
||||
aLength -= len;
|
||||
aString += len;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
nsBoundingMetrics
|
||||
nsLayoutUtils::AppUnitBoundsOfString(const char16_t* aString,
|
||||
uint32_t aLength,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext)
|
||||
{
|
||||
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
|
||||
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
// Assign directly in the first iteration. This ensures that
|
||||
// negative ascent/descent can be returned and the left bearing
|
||||
// is properly initialized.
|
||||
nsBoundingMetrics totalMetrics =
|
||||
aFontMetrics.GetBoundingMetrics(aString, len, &aContext);
|
||||
aLength -= len;
|
||||
aString += len;
|
||||
|
||||
while (aLength > 0) {
|
||||
len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
nsBoundingMetrics metrics =
|
||||
aFontMetrics.GetBoundingMetrics(aString, len, &aContext);
|
||||
totalMetrics += metrics;
|
||||
aLength -= len;
|
||||
aString += len;
|
||||
}
|
||||
return totalMetrics;
|
||||
}
|
||||
|
||||
void
|
||||
nsLayoutUtils::DrawString(const nsIFrame* aFrame,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext* aContext,
|
||||
const char16_t* aString,
|
||||
int32_t aLength,
|
||||
@ -4644,12 +4741,13 @@ nsLayoutUtils::DrawString(const nsIFrame* aFrame,
|
||||
aStyleContext : aFrame->StyleContext());
|
||||
rv = nsBidiPresUtils::RenderText(aString, aLength, level,
|
||||
presContext, *aContext, *aContext,
|
||||
aFontMetrics,
|
||||
aPoint.x, aPoint.y);
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
aContext->SetTextRunRTL(false);
|
||||
DrawUniDirString(aString, aLength, aPoint, *aContext);
|
||||
aFontMetrics.SetTextRunRTL(false);
|
||||
DrawUniDirString(aString, aLength, aPoint, aFontMetrics, *aContext);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4657,33 +4755,33 @@ void
|
||||
nsLayoutUtils::DrawUniDirString(const char16_t* aString,
|
||||
uint32_t aLength,
|
||||
nsPoint aPoint,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext)
|
||||
{
|
||||
nscoord x = aPoint.x;
|
||||
nscoord y = aPoint.y;
|
||||
|
||||
nsFontMetrics* fm = aContext.FontMetrics();
|
||||
|
||||
uint32_t maxChunkLength = aContext.GetMaxChunkLength();
|
||||
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
|
||||
if (aLength <= maxChunkLength) {
|
||||
fm->DrawString(aString, aLength, x, y, &aContext, &aContext);
|
||||
aFontMetrics.DrawString(aString, aLength, x, y, &aContext, &aContext);
|
||||
return;
|
||||
}
|
||||
|
||||
bool isRTL = fm->GetTextRunRTL();
|
||||
bool isRTL = aFontMetrics.GetTextRunRTL();
|
||||
|
||||
// If we're drawing right to left, we must start at the end.
|
||||
if (isRTL) {
|
||||
x += aContext.GetWidth(aString, aLength);
|
||||
x += nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
|
||||
aContext);
|
||||
}
|
||||
|
||||
while (aLength > 0) {
|
||||
int32_t len = nsRenderingContext::FindSafeLength(aString, aLength, maxChunkLength);
|
||||
nscoord width = fm->GetWidth(aString, len, &aContext);
|
||||
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
|
||||
nscoord width = aFontMetrics.GetWidth(aString, len, &aContext);
|
||||
if (isRTL) {
|
||||
x -= width;
|
||||
}
|
||||
fm->DrawString(aString, len, x, y, &aContext, &aContext);
|
||||
aFontMetrics.DrawString(aString, len, x, y, &aContext, &aContext);
|
||||
if (!isRTL) {
|
||||
x += width;
|
||||
}
|
||||
@ -4695,6 +4793,7 @@ nsLayoutUtils::DrawUniDirString(const char16_t* aString,
|
||||
nscoord
|
||||
nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
|
||||
nsRenderingContext* aContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
const char16_t* aString,
|
||||
int32_t aLength)
|
||||
{
|
||||
@ -4703,10 +4802,12 @@ nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
|
||||
nsBidiLevel level =
|
||||
nsBidiPresUtils::BidiLevelFromStyle(aFrame->StyleContext());
|
||||
return nsBidiPresUtils::MeasureTextWidth(aString, aLength,
|
||||
level, presContext, *aContext);
|
||||
level, presContext, *aContext,
|
||||
aFontMetrics);
|
||||
}
|
||||
aContext->SetTextRunRTL(false);
|
||||
return aContext->GetWidth(aString, aLength);
|
||||
aFontMetrics.SetTextRunRTL(false);
|
||||
return nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
|
||||
*aContext);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@ -7175,7 +7276,6 @@ nsLayoutUtils::SetBSizeFromFontMetrics(const nsIFrame* aFrame,
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
float inflation = nsLayoutUtils::FontSizeInflationFor(aFrame);
|
||||
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm), inflation);
|
||||
aReflowState.rendContext->SetFont(fm);
|
||||
|
||||
if (fm) {
|
||||
// Compute final height of the frame.
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "nsBoundingMetrics.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsFrameList.h"
|
||||
@ -958,6 +959,7 @@ public:
|
||||
*/
|
||||
static bool
|
||||
BinarySearchForPosition(nsRenderingContext* acx,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
const char16_t* aText,
|
||||
int32_t aBaseWidth,
|
||||
int32_t aBaseInx,
|
||||
@ -1317,7 +1319,25 @@ public:
|
||||
static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
|
||||
nscoord aY, nscoord aAscent);
|
||||
|
||||
static nscoord AppUnitWidthOfString(char16_t aC,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext) {
|
||||
return AppUnitWidthOfString(&aC, 1, aFontMetrics, aContext);
|
||||
}
|
||||
static nscoord AppUnitWidthOfString(const nsString& aString,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext);
|
||||
static nscoord AppUnitWidthOfString(const char16_t *aString,
|
||||
uint32_t aLength,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext);
|
||||
static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
|
||||
uint32_t aLength,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext);
|
||||
|
||||
static void DrawString(const nsIFrame* aFrame,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext* aContext,
|
||||
const char16_t* aString,
|
||||
int32_t aLength,
|
||||
@ -1330,10 +1350,12 @@ public:
|
||||
static void DrawUniDirString(const char16_t* aString,
|
||||
uint32_t aLength,
|
||||
nsPoint aPoint,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRenderingContext& aContext);
|
||||
|
||||
static nscoord GetStringWidth(const nsIFrame* aFrame,
|
||||
nsRenderingContext* aContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
const char16_t* aString,
|
||||
int32_t aLength);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsTextControlFrame.h"
|
||||
#include "nsIPlaintextEditor.h"
|
||||
#include "nsCaret.h"
|
||||
@ -155,7 +156,6 @@ nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext,
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet),
|
||||
aFontSizeInflation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRenderingContext->SetFont(fontMet);
|
||||
|
||||
lineHeight =
|
||||
nsHTMLReflowState::CalcLineHeight(GetContent(), StyleContext(),
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsCaret.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsGfxScrollFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
@ -238,8 +239,7 @@ nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm),
|
||||
nsLayoutUtils::FontSizeInflationFor(mFrame));
|
||||
aCtx->SetFont(fm);
|
||||
nsLayoutUtils::DrawString(mFrame, aCtx, mStyle->mString.get(),
|
||||
nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(),
|
||||
mStyle->mString.Length(), pt);
|
||||
}
|
||||
}
|
||||
@ -763,8 +763,8 @@ TextOverflow::Marker::SetupString(nsIFrame* aFrame)
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm),
|
||||
nsLayoutUtils::FontSizeInflationFor(aFrame));
|
||||
rc->SetFont(fm);
|
||||
mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, mStyle->mString.get(),
|
||||
mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, *fm,
|
||||
mStyle->mString.get(),
|
||||
mStyle->mString.Length());
|
||||
}
|
||||
mIntrinsicISize = mWidth;
|
||||
|
@ -6,6 +6,7 @@
|
||||
/* rendering object for HTML <br> elements */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsLineLayout.h"
|
||||
@ -118,7 +119,6 @@ BRFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
|
||||
nsLayoutUtils::FontSizeInflationFor(this));
|
||||
aReflowState.rendContext->SetFont(fm); // FIXME: maybe not needed?
|
||||
if (fm) {
|
||||
nscoord logicalHeight = aReflowState.CalcLineHeight();
|
||||
finalSize.BSize(wm) = logicalHeight;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsBlockReflowContext.h"
|
||||
#include "nsBlockReflowState.h"
|
||||
#include "nsBulletFrame.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsLineBox.h"
|
||||
#include "nsLineLayout.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
@ -2513,7 +2514,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
|
||||
nsLayoutUtils::FontSizeInflationFor(this));
|
||||
aState.mReflowState.rendContext->SetFont(fm); // FIXME: needed?
|
||||
|
||||
nscoord minAscent =
|
||||
nsLayoutUtils::GetCenteredFontBaseline(fm, aState.mMinLineHeight);
|
||||
@ -3065,7 +3065,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||
// Now compute the collapsed margin-block-start value into
|
||||
// aState.mPrevBEndMargin, assuming that all child margins
|
||||
// collapse down to clearanceFrame.
|
||||
nsBlockReflowContext::ComputeCollapsedBStartMargin(reflowState,
|
||||
brc.ComputeCollapsedBStartMargin(reflowState,
|
||||
&aState.mPrevBEndMargin,
|
||||
clearanceFrame,
|
||||
&mayNeedRetry);
|
||||
@ -3101,7 +3101,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||
|
||||
// Compute the collapsed margin again, ignoring the incoming margin this time
|
||||
mayNeedRetry = false;
|
||||
nsBlockReflowContext::ComputeCollapsedBStartMargin(reflowState,
|
||||
brc.ComputeCollapsedBStartMargin(reflowState,
|
||||
&aState.mPrevBEndMargin,
|
||||
clearanceFrame,
|
||||
&mayNeedRetry);
|
||||
@ -5855,7 +5855,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||
floatRS.mDiscoveredClearance = nullptr;
|
||||
// Only first in flow gets a top margin.
|
||||
if (!aFloat->GetPrevInFlow()) {
|
||||
nsBlockReflowContext::ComputeCollapsedBStartMargin(floatRS, &margin,
|
||||
brc.ComputeCollapsedBStartMargin(floatRS, &margin,
|
||||
clearanceFrame,
|
||||
&mayNeedRetry);
|
||||
|
||||
|
@ -57,8 +57,10 @@ nsBlockReflowContext::ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
|
||||
bool* aBlockIsEmpty)
|
||||
{
|
||||
WritingMode wm = aRS.GetWritingMode();
|
||||
// Include frame's block-start margin
|
||||
aMargin->Include(aRS.ComputedLogicalMargin().BStart(wm));
|
||||
WritingMode parentWM = mMetrics.GetWritingMode();
|
||||
|
||||
// Include block-start element of frame's margin
|
||||
aMargin->Include(aRS.ComputedLogicalMargin().ConvertTo(parentWM, wm).BStart(parentWM));
|
||||
|
||||
// The inclusion of the block-end margin when empty is done by the caller
|
||||
// since it doesn't need to be done by the top-level (non-recursive)
|
||||
@ -174,8 +176,8 @@ nsBlockReflowContext::ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
|
||||
if (isEmpty) {
|
||||
WritingMode innerWM = innerReflowState.GetWritingMode();
|
||||
LogicalMargin innerMargin =
|
||||
innerReflowState.ComputedLogicalMargin().ConvertTo(wm, innerWM);
|
||||
aMargin->Include(innerMargin.BEnd(wm));
|
||||
innerReflowState.ComputedLogicalMargin().ConvertTo(parentWM, innerWM);
|
||||
aMargin->Include(innerMargin.BEnd(parentWM));
|
||||
}
|
||||
}
|
||||
if (outerReflowState != &aRS) {
|
||||
|
@ -54,9 +54,11 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the collapsed block-start margin for a block whose reflow state
|
||||
* is in aRS.
|
||||
* The computed margin is added into aMargin.
|
||||
* Computes the collapsed block-start margin (in the context's parent's
|
||||
* writing mode) for a block whose reflow state is in aRS.
|
||||
* The computed margin is added into aMargin, whose writing mode is the
|
||||
* parent's mode as found in mMetrics.GetWritingMode(); note this may not be
|
||||
* the block's own writing mode as found in aRS.
|
||||
* If aClearanceFrame is null then this is the first optimistic pass which
|
||||
* shall assume that no frames have clearance, and we clear the HasClearance
|
||||
* on all frames encountered.
|
||||
@ -70,7 +72,7 @@ public:
|
||||
* We return true if we changed the clearance state of any line and marked it
|
||||
* dirty.
|
||||
*/
|
||||
static bool ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
|
||||
bool ComputeCollapsedBStartMargin(const nsHTMLReflowState& aRS,
|
||||
nsCollapsingMargin* aMargin,
|
||||
nsIFrame* aClearanceFrame,
|
||||
bool* aMayNeedRetry,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
@ -428,7 +429,6 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
|
||||
GetFontSizeInflation());
|
||||
GetListItemText(text);
|
||||
aRenderingContext.SetFont(fm);
|
||||
nscoord ascent = fm->MaxAscent();
|
||||
aPt.MoveBy(padding.left, padding.top);
|
||||
aPt.y = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineY(
|
||||
@ -437,7 +437,7 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
|
||||
if (!presContext->BidiEnabled() && HasRTLChars(text)) {
|
||||
presContext->SetBidiEnabled();
|
||||
}
|
||||
nsLayoutUtils::DrawString(this, &aRenderingContext,
|
||||
nsLayoutUtils::DrawString(this, *fm, &aRenderingContext,
|
||||
text.get(), text.Length(), aPt);
|
||||
break;
|
||||
}
|
||||
@ -601,9 +601,8 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
|
||||
default:
|
||||
GetListItemText(text);
|
||||
finalSize.BSize(wm) = fm->MaxHeight();
|
||||
aRenderingContext->SetFont(fm);
|
||||
finalSize.ISize(wm) =
|
||||
nsLayoutUtils::GetStringWidth(this, aRenderingContext,
|
||||
nsLayoutUtils::GetStringWidth(this, aRenderingContext, *fm,
|
||||
text.get(), text.Length());
|
||||
aMetrics.SetBlockStartAscent(fm->MaxAscent());
|
||||
break;
|
||||
@ -862,7 +861,9 @@ nsBulletFrame::GetSpokenText(nsAString& aText)
|
||||
bool isBullet;
|
||||
style->GetSpokenCounterText(mOrdinal, GetWritingMode(), aText, isBullet);
|
||||
if (isBullet) {
|
||||
if (!style->IsNone()) {
|
||||
aText.Append(' ');
|
||||
}
|
||||
} else {
|
||||
nsAutoString prefix, suffix;
|
||||
style->GetPrefix(prefix);
|
||||
|
@ -2167,7 +2167,7 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
|
||||
!IsSideCaption(frame, mStyleDisplay) &&
|
||||
mStyleDisplay->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE &&
|
||||
!flexContainerFrame) {
|
||||
CalculateBlockSideMargins(AvailableWidth(), ComputedWidth(), aFrameType);
|
||||
CalculateBlockSideMargins(AvailableISize(), ComputedISize(), aFrameType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2313,47 +2313,67 @@ nsCSSOffsetState::InitOffsets(nscoord aHorizontalPercentBasis,
|
||||
//
|
||||
// Note: the width unit is not auto when this is called
|
||||
void
|
||||
nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
|
||||
nscoord aComputedWidth,
|
||||
nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailISize,
|
||||
nscoord aComputedISize,
|
||||
nsIAtom* aFrameType)
|
||||
{
|
||||
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aComputedWidth &&
|
||||
NS_UNCONSTRAINEDSIZE != aAvailWidth,
|
||||
"have unconstrained width; this should only result from "
|
||||
"very large sizes, not attempts at intrinsic width "
|
||||
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aComputedISize &&
|
||||
NS_UNCONSTRAINEDSIZE != aAvailISize,
|
||||
"have unconstrained inline-size; this should only result from "
|
||||
"very large sizes, not attempts at intrinsic inline-size "
|
||||
"calculation");
|
||||
|
||||
nscoord sum = ComputedPhysicalMargin().left + ComputedPhysicalBorderPadding().left +
|
||||
aComputedWidth + ComputedPhysicalBorderPadding().right + ComputedPhysicalMargin().right;
|
||||
if (sum == aAvailWidth)
|
||||
nscoord sum = ComputedLogicalMargin().IStartEnd(mWritingMode) +
|
||||
ComputedLogicalBorderPadding().IStartEnd(mWritingMode) + aComputedISize;
|
||||
if (sum == aAvailISize) {
|
||||
// The sum is already correct
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the left and right margin values. The width value
|
||||
// Determine the start and end margin values. The isize value
|
||||
// remains constant while we do this.
|
||||
|
||||
// Calculate how much space is available for margins
|
||||
nscoord availMarginSpace = aAvailWidth - sum;
|
||||
nscoord availMarginSpace = aAvailISize - sum;
|
||||
|
||||
LogicalMargin margin = ComputedLogicalMargin();
|
||||
|
||||
// If the available margin space is negative, then don't follow the
|
||||
// usual overconstraint rules.
|
||||
if (availMarginSpace < 0) {
|
||||
if (mCBReflowState &&
|
||||
mCBReflowState->mStyleVisibility->mDirection == NS_STYLE_DIRECTION_RTL) {
|
||||
ComputedPhysicalMargin().left += availMarginSpace;
|
||||
mCBReflowState->GetWritingMode().IsBidiLTR() !=
|
||||
mWritingMode.IsBidiLTR()) {
|
||||
margin.IStart(mWritingMode) += availMarginSpace;
|
||||
} else {
|
||||
ComputedPhysicalMargin().right += availMarginSpace;
|
||||
margin.IEnd(mWritingMode) += availMarginSpace;
|
||||
}
|
||||
SetComputedLogicalMargin(margin);
|
||||
return;
|
||||
}
|
||||
|
||||
// The css2 spec clearly defines how block elements should behave
|
||||
// in section 10.3.3.
|
||||
bool isAutoLeftMargin =
|
||||
eStyleUnit_Auto == mStyleMargin->mMargin.GetLeftUnit();
|
||||
bool isAutoRightMargin =
|
||||
eStyleUnit_Auto == mStyleMargin->mMargin.GetRightUnit();
|
||||
if (!isAutoLeftMargin && !isAutoRightMargin) {
|
||||
bool isAutoStartMargin, isAutoEndMargin;
|
||||
const nsStyleSides& styleSides = mStyleMargin->mMargin;
|
||||
if (mWritingMode.IsVertical()) {
|
||||
if (mWritingMode.IsBidiLTR()) {
|
||||
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetTopUnit();
|
||||
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetBottomUnit();
|
||||
} else {
|
||||
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetBottomUnit();
|
||||
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetTopUnit();
|
||||
}
|
||||
} else {
|
||||
if (mWritingMode.IsBidiLTR()) {
|
||||
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetLeftUnit();
|
||||
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetRightUnit();
|
||||
} else {
|
||||
isAutoStartMargin = eStyleUnit_Auto == styleSides.GetRightUnit();
|
||||
isAutoEndMargin = eStyleUnit_Auto == styleSides.GetLeftUnit();
|
||||
}
|
||||
}
|
||||
if (!isAutoStartMargin && !isAutoEndMargin) {
|
||||
// Neither margin is 'auto' so we're over constrained. Use the
|
||||
// 'direction' property of the parent to tell which margin to
|
||||
// ignore
|
||||
@ -2370,19 +2390,27 @@ nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
|
||||
(prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
|
||||
prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
|
||||
prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)) {
|
||||
isAutoLeftMargin =
|
||||
if (prs->mWritingMode.IsBidiLTR()) {
|
||||
isAutoStartMargin =
|
||||
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
|
||||
isAutoRightMargin =
|
||||
isAutoEndMargin =
|
||||
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
|
||||
} else {
|
||||
isAutoStartMargin =
|
||||
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
|
||||
isAutoEndMargin =
|
||||
prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
|
||||
}
|
||||
}
|
||||
// Otherwise apply the CSS rules, and ignore one margin by forcing
|
||||
// it to 'auto', depending on 'direction'.
|
||||
else if (mCBReflowState &&
|
||||
NS_STYLE_DIRECTION_RTL == mCBReflowState->mStyleVisibility->mDirection) {
|
||||
isAutoLeftMargin = true;
|
||||
mCBReflowState->GetWritingMode().IsBidiLTR() !=
|
||||
mWritingMode.IsBidiLTR()) {
|
||||
isAutoStartMargin = true;
|
||||
}
|
||||
else {
|
||||
isAutoRightMargin = true;
|
||||
isAutoEndMargin = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2390,18 +2418,19 @@ nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
|
||||
// The computed margins need not be zero because the 'auto' could come from
|
||||
// overconstraint or from HTML alignment so values need to be accumulated
|
||||
|
||||
if (isAutoLeftMargin) {
|
||||
if (isAutoRightMargin) {
|
||||
if (isAutoStartMargin) {
|
||||
if (isAutoEndMargin) {
|
||||
// Both margins are 'auto' so the computed addition should be equal
|
||||
nscoord forLeft = availMarginSpace / 2;
|
||||
ComputedPhysicalMargin().left += forLeft;
|
||||
ComputedPhysicalMargin().right += availMarginSpace - forLeft;
|
||||
nscoord forStart = availMarginSpace / 2;
|
||||
margin.IStart(mWritingMode) += forStart;
|
||||
margin.IEnd(mWritingMode) += availMarginSpace - forStart;
|
||||
} else {
|
||||
ComputedPhysicalMargin().left += availMarginSpace;
|
||||
margin.IStart(mWritingMode) += availMarginSpace;
|
||||
}
|
||||
} else if (isAutoRightMargin) {
|
||||
ComputedPhysicalMargin().right += availMarginSpace;
|
||||
} else if (isAutoEndMargin) {
|
||||
margin.IEnd(mWritingMode) += availMarginSpace;
|
||||
}
|
||||
SetComputedLogicalMargin(margin);
|
||||
}
|
||||
|
||||
#define NORMAL_LINE_HEIGHT_FACTOR 1.2f // in term of emHeight
|
||||
|
@ -117,13 +117,20 @@ public:
|
||||
nsMargin& ComputedPhysicalBorderPadding() { return mComputedBorderPadding; }
|
||||
nsMargin& ComputedPhysicalPadding() { return mComputedPadding; }
|
||||
|
||||
LogicalMargin ComputedLogicalMargin() const
|
||||
const LogicalMargin ComputedLogicalMargin() const
|
||||
{ return LogicalMargin(mWritingMode, mComputedMargin); }
|
||||
LogicalMargin ComputedLogicalBorderPadding() const
|
||||
const LogicalMargin ComputedLogicalBorderPadding() const
|
||||
{ return LogicalMargin(mWritingMode, mComputedBorderPadding); }
|
||||
LogicalMargin ComputedLogicalPadding() const
|
||||
const LogicalMargin ComputedLogicalPadding() const
|
||||
{ return LogicalMargin(mWritingMode, mComputedPadding); }
|
||||
|
||||
void SetComputedLogicalMargin(const LogicalMargin& aMargin)
|
||||
{ mComputedMargin = aMargin.GetPhysicalMargin(mWritingMode); }
|
||||
void SetComputedLogicalBorderPadding(const LogicalMargin& aMargin)
|
||||
{ mComputedBorderPadding = aMargin.GetPhysicalMargin(mWritingMode); }
|
||||
void SetComputedLogicalPadding(const LogicalMargin& aMargin)
|
||||
{ mComputedPadding = aMargin.GetPhysicalMargin(mWritingMode); }
|
||||
|
||||
WritingMode GetWritingMode() const { return mWritingMode; }
|
||||
|
||||
protected:
|
||||
@ -803,8 +810,8 @@ protected:
|
||||
nscoord* aInsideBoxSizing,
|
||||
nscoord* aOutsideBoxSizing);
|
||||
|
||||
void CalculateBlockSideMargins(nscoord aAvailWidth,
|
||||
nscoord aComputedWidth,
|
||||
void CalculateBlockSideMargins(nscoord aAvailISize,
|
||||
nscoord aComputedISize,
|
||||
nsIAtom* aFrameType);
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "mozilla/MouseEvents.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
@ -1012,11 +1013,12 @@ nsImageFrame::MeasureString(const char16_t* aString,
|
||||
int32_t aLength,
|
||||
nscoord aMaxWidth,
|
||||
uint32_t& aMaxFit,
|
||||
nsRenderingContext& aContext)
|
||||
nsRenderingContext& aContext,
|
||||
nsFontMetrics& aFontMetrics)
|
||||
{
|
||||
nscoord totalWidth = 0;
|
||||
aContext.FontMetrics()->SetTextRunRTL(false);
|
||||
nscoord spaceWidth = aContext.FontMetrics()->SpaceWidth();
|
||||
aFontMetrics.SetTextRunRTL(false);
|
||||
nscoord spaceWidth = aFontMetrics.SpaceWidth();
|
||||
|
||||
aMaxFit = 0;
|
||||
while (aLength > 0) {
|
||||
@ -1033,7 +1035,7 @@ nsImageFrame::MeasureString(const char16_t* aString,
|
||||
|
||||
// Measure this chunk of text, and see if it fits
|
||||
nscoord width =
|
||||
nsLayoutUtils::GetStringWidth(this, &aContext, aString, len);
|
||||
nsLayoutUtils::GetStringWidth(this, &aContext, aFontMetrics, aString, len);
|
||||
bool fits = (totalWidth + width) <= aMaxWidth;
|
||||
|
||||
// If it fits on the line, or it's the first word we've processed then
|
||||
@ -1080,7 +1082,6 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
|
||||
nsLayoutUtils::FontSizeInflationFor(this));
|
||||
aRenderingContext.SetFont(fm);
|
||||
|
||||
// Format the text to display within the formatting rect
|
||||
|
||||
@ -1105,7 +1106,7 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
||||
// Determine how much of the text to display on this line
|
||||
uint32_t maxFit; // number of characters that fit
|
||||
nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
|
||||
aRenderingContext);
|
||||
aRenderingContext, *fm);
|
||||
|
||||
// Display the text
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
@ -1115,17 +1116,17 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
||||
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
|
||||
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
|
||||
aPresContext, aRenderingContext,
|
||||
aRenderingContext,
|
||||
aRenderingContext, *fm,
|
||||
aRect.XMost() - strWidth, y + maxAscent);
|
||||
else
|
||||
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
|
||||
aPresContext, aRenderingContext,
|
||||
aRenderingContext,
|
||||
aRenderingContext, *fm,
|
||||
aRect.x, y + maxAscent);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
nsLayoutUtils::DrawUniDirString(str, maxFit,
|
||||
nsPoint(aRect.x, y + maxAscent),
|
||||
nsPoint(aRect.x, y + maxAscent), *fm,
|
||||
aRenderingContext);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "nsIReflowCallback.h"
|
||||
#include "nsTObserverArray.h"
|
||||
|
||||
class nsFontMetrics;
|
||||
class nsImageMap;
|
||||
class nsIURI;
|
||||
class nsILoadGroup;
|
||||
@ -205,7 +206,8 @@ protected:
|
||||
int32_t aLength,
|
||||
nscoord aMaxWidth,
|
||||
uint32_t& aMaxFit,
|
||||
nsRenderingContext& aContext);
|
||||
nsRenderingContext& aContext,
|
||||
nsFontMetrics& aFontMetrics);
|
||||
|
||||
void DisplayAltText(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "SVGTextFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsFloatManager.h"
|
||||
@ -1101,16 +1102,16 @@ nsLineLayout::AllowForStartMargin(PerFrameData* pfd,
|
||||
// the frame we will properly avoid adding in the starting margin.
|
||||
pfd->mMargin.IStart(frameWM) = 0;
|
||||
} else {
|
||||
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.AvailableWidth(),
|
||||
"have unconstrained width; this should only result from "
|
||||
"very large sizes, not attempts at intrinsic width "
|
||||
"calculation");
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth()) {
|
||||
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.AvailableISize(),
|
||||
"have unconstrained inline-size; this should only result "
|
||||
"from very large sizes, not attempts at intrinsic "
|
||||
"inline-size calculation");
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedISize()) {
|
||||
// For inline-ish and text-ish things (which don't compute widths
|
||||
// in the reflow state), adjust available width to account for the
|
||||
// in the reflow state), adjust available inline-size to account for the
|
||||
// start margin. The end margin will be accounted for when we
|
||||
// finish flowing the frame.
|
||||
aReflowState.AvailableWidth() -= pfd->mMargin.IStart(frameWM);
|
||||
aReflowState.AvailableISize() -= pfd->mMargin.IStart(frameWM);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1589,7 +1590,6 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||
GetInflationForBlockDirAlignment(spanFrame, mInflationMinFontSize);
|
||||
nsLayoutUtils::GetFontMetricsForFrame(spanFrame, getter_AddRefs(fm),
|
||||
inflation);
|
||||
mBlockReflowState->rendContext->SetFont(fm);
|
||||
|
||||
bool preMode = mStyleText->WhiteSpaceIsSignificant();
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsRenderingContext.h"
|
||||
@ -237,11 +238,13 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
const nsRect& aRect,
|
||||
int32_t aJust,
|
||||
const nsString& aStr)
|
||||
{
|
||||
nscoord width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
|
||||
aFontMetrics,
|
||||
aStr.get(), aStr.Length());
|
||||
|
||||
nscoord x = aRect.x;
|
||||
@ -273,6 +276,7 @@ nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
|
||||
// @param aHeight - the height of the font
|
||||
void
|
||||
nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsHeaderFooterEnum aHeaderFooter,
|
||||
const nsString& aStrLeft,
|
||||
const nsString& aStrCenter,
|
||||
@ -290,17 +294,17 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
nscoord strSpace = aRect.width / numStrs;
|
||||
|
||||
if (!aStrLeft.IsEmpty()) {
|
||||
DrawHeaderFooter(aRenderingContext, aHeaderFooter,
|
||||
DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
|
||||
nsIPrintSettings::kJustLeft, aStrLeft, aRect, aAscent,
|
||||
aHeight, strSpace);
|
||||
}
|
||||
if (!aStrCenter.IsEmpty()) {
|
||||
DrawHeaderFooter(aRenderingContext, aHeaderFooter,
|
||||
DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
|
||||
nsIPrintSettings::kJustCenter, aStrCenter, aRect, aAscent,
|
||||
aHeight, strSpace);
|
||||
}
|
||||
if (!aStrRight.IsEmpty()) {
|
||||
DrawHeaderFooter(aRenderingContext, aHeaderFooter,
|
||||
DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
|
||||
nsIPrintSettings::kJustRight, aStrRight, aRect, aAscent,
|
||||
aHeight, strSpace);
|
||||
}
|
||||
@ -317,6 +321,7 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
// @param aWidth - available width for the string
|
||||
void
|
||||
nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsHeaderFooterEnum aHeaderFooter,
|
||||
int32_t aJust,
|
||||
const nsString& aStr,
|
||||
@ -342,7 +347,8 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
return; // bail is empty string
|
||||
}
|
||||
// find how much text fits, the "position" is the size of the available area
|
||||
if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, text, 0, 0, 0, len,
|
||||
if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, aFontMetrics,
|
||||
text, 0, 0, 0, len,
|
||||
int32_t(contentWidth), indx, textWidth)) {
|
||||
if (indx < len-1 ) {
|
||||
// we can't fit in all the text
|
||||
@ -369,7 +375,7 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
}
|
||||
|
||||
// cacl the x and y positions of the text
|
||||
nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
|
||||
nscoord x = GetXPosition(aRenderingContext, aFontMetrics, aRect, aJust, str);
|
||||
nscoord y;
|
||||
if (aHeaderFooter == eHeader) {
|
||||
y = aRect.y + mPD->mEdgePaperMargin.top;
|
||||
@ -385,7 +391,9 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
gfx->Clip(NSRectToSnappedRect(aRect, PresContext()->AppUnitsPerDevPixel(),
|
||||
*drawTarget));
|
||||
aRenderingContext.ThebesContext()->SetColor(NS_RGB(0,0,0));
|
||||
nsLayoutUtils::DrawString(this, &aRenderingContext, str.get(), str.Length(), nsPoint(x, y + aAscent));
|
||||
nsLayoutUtils::DrawString(this, aFontMetrics, &aRenderingContext,
|
||||
str.get(), str.Length(),
|
||||
nsPoint(x, y + aAscent));
|
||||
gfx->Restore();
|
||||
}
|
||||
}
|
||||
@ -597,8 +605,6 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
pc->GetTextPerfMetrics(),
|
||||
*getter_AddRefs(fontMet));
|
||||
|
||||
aRenderingContext.SetFont(fontMet);
|
||||
|
||||
nscoord ascent = 0;
|
||||
nscoord visibleHeight = 0;
|
||||
if (fontMet) {
|
||||
@ -611,7 +617,7 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
mPD->mPrintSettings->GetHeaderStrLeft(getter_Copies(headerLeft));
|
||||
mPD->mPrintSettings->GetHeaderStrCenter(getter_Copies(headerCenter));
|
||||
mPD->mPrintSettings->GetHeaderStrRight(getter_Copies(headerRight));
|
||||
DrawHeaderFooter(aRenderingContext, eHeader,
|
||||
DrawHeaderFooter(aRenderingContext, *fontMet, eHeader,
|
||||
headerLeft, headerCenter, headerRight,
|
||||
rect, ascent, visibleHeight);
|
||||
|
||||
@ -619,7 +625,7 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
mPD->mPrintSettings->GetFooterStrLeft(getter_Copies(footerLeft));
|
||||
mPD->mPrintSettings->GetFooterStrCenter(getter_Copies(footerCenter));
|
||||
mPD->mPrintSettings->GetFooterStrRight(getter_Copies(footerRight));
|
||||
DrawHeaderFooter(aRenderingContext, eFooter,
|
||||
DrawHeaderFooter(aRenderingContext, *fontMet, eFooter,
|
||||
footerLeft, footerCenter, footerRight,
|
||||
rect, ascent, visibleHeight);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsLeafFrame.h"
|
||||
|
||||
class nsFontMetrics;
|
||||
class nsSharedPageData;
|
||||
|
||||
// Page frame class used by the simple page sequence frame
|
||||
@ -66,11 +67,13 @@ protected:
|
||||
} nsHeaderFooterEnum;
|
||||
|
||||
nscoord GetXPosition(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
const nsRect& aRect,
|
||||
int32_t aJust,
|
||||
const nsString& aStr);
|
||||
|
||||
void DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsHeaderFooterEnum aHeaderFooter,
|
||||
int32_t aJust,
|
||||
const nsString& sStr,
|
||||
@ -80,6 +83,7 @@ protected:
|
||||
nscoord aWidth);
|
||||
|
||||
void DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsHeaderFooterEnum aHeaderFooter,
|
||||
const nsString& aStrLeft,
|
||||
const nsString& aStrRight,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsSplittableFrame.h"
|
||||
#include "nsLineLayout.h"
|
||||
#include "nsString.h"
|
||||
|
@ -5,12 +5,14 @@
|
||||
|
||||
#include "nsMathMLChar.h"
|
||||
|
||||
#include "gfxTextRun.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
|
@ -53,12 +53,12 @@ nsMathMLContainerFrame::ReflowError(nsRenderingContext& aRenderingContext,
|
||||
// Set font
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
|
||||
// bounding metrics
|
||||
nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
|
||||
mBoundingMetrics =
|
||||
aRenderingContext.GetBoundingMetrics(errorMsg.get(), errorMsg.Length());
|
||||
nsLayoutUtils::AppUnitBoundsOfString(errorMsg.get(), errorMsg.Length(),
|
||||
*fm, aRenderingContext);
|
||||
|
||||
// reflow metrics
|
||||
WritingMode wm = aDesiredSize.GetWritingMode();
|
||||
@ -96,7 +96,6 @@ void nsDisplayMathMLError::Paint(nsDisplayListBuilder* aBuilder,
|
||||
// Set color and font ...
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm));
|
||||
aCtx->SetFont(fm);
|
||||
|
||||
nsPoint pt = ToReferenceFrame();
|
||||
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
@ -108,12 +107,10 @@ void nsDisplayMathMLError::Paint(nsDisplayListBuilder* aBuilder,
|
||||
drawTarget->FillRect(rect, red);
|
||||
|
||||
aCtx->ThebesContext()->SetColor(NS_RGB(255,255,255));
|
||||
nscoord ascent = aCtx->FontMetrics()->MaxAscent();
|
||||
nscoord ascent = fm->MaxAscent();
|
||||
NS_NAMED_LITERAL_STRING(errorMsg, "invalid-markup");
|
||||
nsLayoutUtils::DrawUniDirString(errorMsg.get(),
|
||||
uint32_t(errorMsg.Length()),
|
||||
nsPoint(pt.x, pt.y + ascent),
|
||||
*aCtx);
|
||||
nsLayoutUtils::DrawUniDirString(errorMsg.get(), uint32_t(errorMsg.Length()),
|
||||
nsPoint(pt.x, pt.y + ascent), *fm, *aCtx);
|
||||
}
|
||||
|
||||
/* /////////////
|
||||
|
@ -172,15 +172,11 @@ nsMathMLFrame::GetRuleThickness(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics* aFontMetrics,
|
||||
nscoord& aRuleThickness)
|
||||
{
|
||||
// get the bounding metrics of the overbar char, the rendering context
|
||||
// is assumed to have been set with the font of the current style context
|
||||
NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
|
||||
Equals(aFontMetrics->Font()),
|
||||
"unexpected state");
|
||||
|
||||
nscoord xHeight = aFontMetrics->XHeight();
|
||||
char16_t overBar = 0x00AF;
|
||||
nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&overBar, 1);
|
||||
nsBoundingMetrics bm =
|
||||
nsLayoutUtils::AppUnitBoundsOfString(&overBar, 1, *aFontMetrics,
|
||||
aRenderingContext);
|
||||
aRuleThickness = bm.ascent + bm.descent;
|
||||
if (aRuleThickness <= 0 || aRuleThickness >= xHeight) {
|
||||
// fall-back to the other version
|
||||
@ -201,15 +197,11 @@ nsMathMLFrame::GetAxisHeight(nsRenderingContext& aRenderingContext,
|
||||
return;
|
||||
}
|
||||
|
||||
// get the bounding metrics of the minus sign, the rendering context
|
||||
// is assumed to have been set with the font of the current style context
|
||||
NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
|
||||
Equals(aFontMetrics->Font()),
|
||||
"unexpected state");
|
||||
|
||||
nscoord xHeight = aFontMetrics->XHeight();
|
||||
char16_t minus = 0x2212; // not '-', but official Unicode minus sign
|
||||
nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&minus, 1);
|
||||
nsBoundingMetrics bm =
|
||||
nsLayoutUtils::AppUnitBoundsOfString(&minus, 1, *aFontMetrics,
|
||||
aRenderingContext);
|
||||
aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
|
||||
if (aAxisHeight <= 0 || aAxisHeight >= xHeight) {
|
||||
// fall-back to the other version
|
||||
|
@ -345,14 +345,14 @@ nsMathMLmencloseFrame::PlaceInternal(nsRenderingContext& aRenderingContext,
|
||||
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
GetRuleThickness(aRenderingContext, fm, mRuleThickness);
|
||||
if (mRuleThickness < onePixel) {
|
||||
mRuleThickness = onePixel;
|
||||
}
|
||||
|
||||
char16_t one = '1';
|
||||
nsBoundingMetrics bmOne = aRenderingContext.GetBoundingMetrics(&one, 1);
|
||||
nsBoundingMetrics bmOne =
|
||||
nsLayoutUtils::AppUnitBoundsOfString(&one, 1, *fm, aRenderingContext);
|
||||
|
||||
///////////////
|
||||
// General rules: the menclose element takes the size of the enclosed content.
|
||||
|
@ -221,7 +221,6 @@ nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsStyleFont* font = StyleFont();
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aReflowState.rendContext->SetFont(fm);
|
||||
nscoord axisHeight, em;
|
||||
GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
|
||||
GetEmHeight(fm, em);
|
||||
@ -340,19 +339,19 @@ nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
/////////////////
|
||||
// opening fence ...
|
||||
ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar,
|
||||
ReflowChar(aPresContext, *aReflowState.rendContext, *fm, mOpenChar,
|
||||
NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel,
|
||||
axisHeight, leading, em, containerSize, ascent, descent, isRTL);
|
||||
/////////////////
|
||||
// separators ...
|
||||
for (i = 0; i < mSeparatorsCount; i++) {
|
||||
ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i],
|
||||
ReflowChar(aPresContext, *aReflowState.rendContext, *fm, &mSeparatorsChar[i],
|
||||
NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
|
||||
axisHeight, leading, em, containerSize, ascent, descent, isRTL);
|
||||
}
|
||||
/////////////////
|
||||
// closing fence ...
|
||||
ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar,
|
||||
ReflowChar(aPresContext, *aReflowState.rendContext, *fm, mCloseChar,
|
||||
NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
|
||||
axisHeight, leading, em, containerSize, ascent, descent, isRTL);
|
||||
|
||||
@ -470,6 +469,7 @@ GetCharSpacing(nsMathMLChar* aMathMLChar,
|
||||
/*static*/ nsresult
|
||||
nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsMathMLChar* aMathMLChar,
|
||||
nsOperatorFlags aForm,
|
||||
int32_t aScriptLevel,
|
||||
@ -501,13 +501,14 @@ nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
|
||||
}
|
||||
else {
|
||||
// either it hasn't changed or stretching the char failed (i.e.,
|
||||
// GetBoundingMetrics failed)
|
||||
// nsLayoutUtils::AppUnitBoundsOfString failed)
|
||||
leading = 0;
|
||||
if (NS_FAILED(res)) {
|
||||
nsAutoString data;
|
||||
aMathMLChar->GetData(data);
|
||||
nsBoundingMetrics metrics =
|
||||
aRenderingContext.GetBoundingMetrics(data.get(), data.Length());
|
||||
nsLayoutUtils::AppUnitBoundsOfString(data.get(), data.Length(),
|
||||
aFontMetrics, aRenderingContext);
|
||||
charSize.ascent = metrics.ascent;
|
||||
charSize.descent = metrics.descent;
|
||||
charSize.width = metrics.width;
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsMathMLContainerFrame.h"
|
||||
|
||||
class nsFontMetrics;
|
||||
|
||||
//
|
||||
// <mfenced> -- surround content with a pair of fences
|
||||
//
|
||||
@ -63,6 +65,7 @@ public:
|
||||
static nsresult
|
||||
ReflowChar(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsMathMLChar* aMathMLChar,
|
||||
nsOperatorFlags aForm,
|
||||
int32_t aScriptLevel,
|
||||
|
@ -216,7 +216,6 @@ nsMathMLmfracFrame::PlaceInternal(nsRenderingContext& aRenderingContext,
|
||||
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
|
||||
nscoord defaultRuleThickness, axisHeight;
|
||||
nscoord oneDevPixel = fm->AppUnitsPerDevPixel();
|
||||
|
@ -185,7 +185,6 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
|
||||
const nsStyleFont* font = aFrame->StyleFont();
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(baseFrame, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
|
||||
nscoord xHeight = fm->XHeight();
|
||||
|
||||
|
@ -611,7 +611,6 @@ nsMathMLmoFrame::Stretch(nsRenderingContext& aRenderingContext,
|
||||
// get the axis height;
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
nscoord axisHeight, height;
|
||||
GetAxisHeight(aRenderingContext, fm, axisHeight);
|
||||
|
||||
|
@ -225,7 +225,6 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
renderingContext.SetFont(fm);
|
||||
|
||||
nscoord ruleThickness, leading, psi;
|
||||
GetRadicalParameters(fm, StyleFont()->mMathDisplay ==
|
||||
@ -234,7 +233,8 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
// built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131)
|
||||
char16_t one = '1';
|
||||
nsBoundingMetrics bmOne = renderingContext.GetBoundingMetrics(&one, 1);
|
||||
nsBoundingMetrics bmOne =
|
||||
nsLayoutUtils::AppUnitBoundsOfString(&one, 1, *fm, renderingContext);
|
||||
if (bmOne.ascent > bmBase.ascent)
|
||||
psi += bmOne.ascent - bmBase.ascent;
|
||||
|
||||
|
@ -857,11 +857,8 @@ nsMathMLmtableOuterFrame::Reflow(nsPresContext* aPresContext,
|
||||
// XXX should instead use style data from the row of reference here ?
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aReflowState.rendContext->SetFont(fm);
|
||||
nscoord axisHeight;
|
||||
GetAxisHeight(*aReflowState.rendContext,
|
||||
aReflowState.rendContext->FontMetrics(),
|
||||
axisHeight);
|
||||
GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
|
||||
if (rowFrame) {
|
||||
// anchor the table on the axis of the row of reference
|
||||
// XXX fallback to baseline because it is a hard problem
|
||||
|
@ -396,7 +396,6 @@ nsMathMLmunderoverFrame::Place(nsRenderingContext& aRenderingContext,
|
||||
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
|
||||
nscoord xHeight = fm->XHeight();
|
||||
nscoord oneDevPixel = fm->AppUnitsPerDevPixel();
|
||||
|
27
layout/reftests/writing-mode/1083892-1-ref.html
Normal file
27
layout/reftests/writing-mode/1083892-1-ref.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1083892</title>
|
||||
<style>
|
||||
div {
|
||||
width:400px;
|
||||
height:400px;
|
||||
padding:10px;
|
||||
border:1px solid black;
|
||||
writing-mode:vertical-lr;
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
This is the first line.<br>
|
||||
Line two.<br>
|
||||
Third and final line.
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
27
layout/reftests/writing-mode/1083892-1.html
Normal file
27
layout/reftests/writing-mode/1083892-1.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1083892</title>
|
||||
<style>
|
||||
div {
|
||||
width:400px;
|
||||
height:400px;
|
||||
padding:10px;
|
||||
border:1px solid black;
|
||||
writing-mode:vertical-lr;
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<p>This is the first line.
|
||||
<p>Line two.
|
||||
<p>Third and final line.
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
28
layout/reftests/writing-mode/1086883-1-ref.html
Normal file
28
layout/reftests/writing-mode/1086883-1-ref.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1086883</title>
|
||||
<!-- writing mode of #inner div should not affect its position within #outer -->
|
||||
<style>
|
||||
#outer {
|
||||
width:400px;
|
||||
height:300px;
|
||||
padding:50px;
|
||||
border:1px solid black;
|
||||
}
|
||||
#inner {
|
||||
width:200px;
|
||||
height:100px;
|
||||
background:red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="outer">
|
||||
<div id="inner">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
29
layout/reftests/writing-mode/1086883-1a.html
Normal file
29
layout/reftests/writing-mode/1086883-1a.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1086883</title>
|
||||
<!-- writing mode of #inner div should not affect its position within #outer -->
|
||||
<style>
|
||||
#outer {
|
||||
width:400px;
|
||||
height:300px;
|
||||
padding:50px;
|
||||
border:1px solid black;
|
||||
}
|
||||
#inner {
|
||||
width:200px;
|
||||
height:100px;
|
||||
background:red;
|
||||
writing-mode:vertical-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="outer">
|
||||
<div id="inner">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
29
layout/reftests/writing-mode/1086883-1b.html
Normal file
29
layout/reftests/writing-mode/1086883-1b.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1086883</title>
|
||||
<!-- writing mode of #inner div should not affect its position within #outer -->
|
||||
<style>
|
||||
#outer {
|
||||
width:400px;
|
||||
height:300px;
|
||||
padding:50px;
|
||||
border:1px solid black;
|
||||
}
|
||||
#inner {
|
||||
width:200px;
|
||||
height:100px;
|
||||
background:red;
|
||||
writing-mode:vertical-rl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="outer">
|
||||
<div id="inner">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -3,3 +3,6 @@
|
||||
# is turned on
|
||||
== 1082844.html 1082844-ref.html
|
||||
== 1083748.html 1083748-ref.html
|
||||
== 1083892-1.html 1083892-1-ref.html
|
||||
== 1086883-1a.html 1086883-1-ref.html
|
||||
== 1086883-1b.html 1086883-1-ref.html
|
||||
|
@ -725,10 +725,10 @@ nsListBoxBodyFrame::ComputeIntrinsicISize(nsBoxLayoutState& aBoxLayoutState)
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForStyleContext(styleContext,
|
||||
getter_AddRefs(fm));
|
||||
rendContext->SetFont(fm);
|
||||
|
||||
nscoord textWidth =
|
||||
nsLayoutUtils::GetStringWidth(this, rendContext, value.get(), value.Length());
|
||||
nsLayoutUtils::GetStringWidth(this, rendContext, *fm,
|
||||
value.get(), value.Length());
|
||||
textWidth += width;
|
||||
|
||||
if (textWidth > largestWidth)
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "gfxUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGkAtoms.h"
|
||||
@ -500,10 +501,7 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
||||
nsRefPtr<nsRenderingContext> refContext =
|
||||
PresContext()->PresShell()->CreateReferenceRenderingContext();
|
||||
|
||||
aRenderingContext.SetFont(fontMet);
|
||||
refContext->SetFont(fontMet);
|
||||
|
||||
CalculateUnderline(*refContext);
|
||||
CalculateUnderline(*refContext, *fontMet);
|
||||
|
||||
nscolor c = aOverrideColor ? *aOverrideColor : StyleColor()->mColor;
|
||||
ColorPattern color(ToDeviceColor(c));
|
||||
@ -521,7 +519,7 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
||||
posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
|
||||
rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level,
|
||||
presContext, aRenderingContext,
|
||||
*refContext,
|
||||
*refContext, *fontMet,
|
||||
aTextRect.x, baseline,
|
||||
&posResolve,
|
||||
1);
|
||||
@ -532,21 +530,22 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
||||
{
|
||||
rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level,
|
||||
presContext, aRenderingContext,
|
||||
*refContext,
|
||||
*refContext, *fontMet,
|
||||
aTextRect.x, baseline);
|
||||
}
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
aRenderingContext.SetTextRunRTL(false);
|
||||
fontMet->SetTextRunRTL(false);
|
||||
|
||||
if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
|
||||
// In the simple (non-BiDi) case, we calculate the mnemonic's
|
||||
// underline position by getting the text metric.
|
||||
// XXX are attribute values always two byte?
|
||||
if (mAccessKeyInfo->mAccesskeyIndex > 0)
|
||||
mAccessKeyInfo->mBeforeWidth =
|
||||
refContext->GetWidth(mCroppedTitle.get(),
|
||||
mAccessKeyInfo->mAccesskeyIndex);
|
||||
mAccessKeyInfo->mBeforeWidth = nsLayoutUtils::
|
||||
AppUnitWidthOfString(mCroppedTitle.get(),
|
||||
mAccessKeyInfo->mAccesskeyIndex,
|
||||
*fontMet, *refContext);
|
||||
else
|
||||
mAccessKeyInfo->mBeforeWidth = 0;
|
||||
}
|
||||
@ -581,21 +580,21 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
||||
}
|
||||
|
||||
void
|
||||
nsTextBoxFrame::CalculateUnderline(nsRenderingContext& aRenderingContext)
|
||||
nsTextBoxFrame::CalculateUnderline(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics)
|
||||
{
|
||||
if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
|
||||
// Calculate all fields of mAccessKeyInfo which
|
||||
// are the same for both BiDi and non-BiDi frames.
|
||||
const char16_t *titleString = mCroppedTitle.get();
|
||||
aRenderingContext.SetTextRunRTL(false);
|
||||
mAccessKeyInfo->mAccessWidth =
|
||||
aRenderingContext.GetWidth(titleString[mAccessKeyInfo->
|
||||
mAccesskeyIndex]);
|
||||
aFontMetrics.SetTextRunRTL(false);
|
||||
mAccessKeyInfo->mAccessWidth = nsLayoutUtils::
|
||||
AppUnitWidthOfString(titleString[mAccessKeyInfo->mAccesskeyIndex],
|
||||
aFontMetrics, aRenderingContext);
|
||||
|
||||
nscoord offset, baseline;
|
||||
nsFontMetrics* metrics = aRenderingContext.FontMetrics();
|
||||
metrics->GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize);
|
||||
baseline = metrics->MaxAscent();
|
||||
aFontMetrics.GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize);
|
||||
baseline = aFontMetrics.MaxAscent();
|
||||
mAccessKeyInfo->mAccessOffset = baseline - offset;
|
||||
}
|
||||
}
|
||||
@ -612,10 +611,10 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
aRenderingContext.SetFont(fm);
|
||||
|
||||
// see if the text will completely fit in the width given
|
||||
nscoord titleWidth = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
|
||||
*fm,
|
||||
mTitle.get(), mTitle.Length());
|
||||
|
||||
if (titleWidth <= aWidth) {
|
||||
@ -632,8 +631,9 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
|
||||
// see if the width is even smaller than the ellipsis
|
||||
// if so, clear the text (XXX set as many '.' as we can?).
|
||||
aRenderingContext.SetTextRunRTL(false);
|
||||
titleWidth = aRenderingContext.GetWidth(kEllipsis);
|
||||
fm->SetTextRunRTL(false);
|
||||
titleWidth = nsLayoutUtils::AppUnitWidthOfString(kEllipsis, *fm,
|
||||
aRenderingContext);
|
||||
|
||||
if (titleWidth > aWidth) {
|
||||
mCroppedTitle.SetLength(0);
|
||||
@ -661,7 +661,8 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
for (i = 0; i < length; ++i) {
|
||||
char16_t ch = mTitle.CharAt(i);
|
||||
// still in LTR mode
|
||||
cwidth = aRenderingContext.GetWidth(ch);
|
||||
cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
|
||||
aRenderingContext);
|
||||
if (twidth + cwidth > aWidth)
|
||||
break;
|
||||
|
||||
@ -689,7 +690,8 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
int i;
|
||||
for (i=length-1; i >= 0; --i) {
|
||||
char16_t ch = mTitle.CharAt(i);
|
||||
cwidth = aRenderingContext.GetWidth(ch);
|
||||
cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
|
||||
aRenderingContext);
|
||||
if (twidth + cwidth > aWidth)
|
||||
break;
|
||||
|
||||
@ -711,7 +713,7 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
case CropCenter:
|
||||
{
|
||||
nscoord stringWidth =
|
||||
nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
|
||||
nsLayoutUtils::GetStringWidth(this, &aRenderingContext, *fm,
|
||||
mTitle.get(), mTitle.Length());
|
||||
if (stringWidth <= aWidth) {
|
||||
// the entire string will fit in the maximum width
|
||||
@ -727,11 +729,12 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
nsAutoString leftString, rightString;
|
||||
|
||||
rightPos = mTitle.Length() - 1;
|
||||
aRenderingContext.SetTextRunRTL(false);
|
||||
fm->SetTextRunRTL(false);
|
||||
for (leftPos = 0; leftPos <= rightPos;) {
|
||||
// look at the next character on the left end
|
||||
ch = mTitle.CharAt(leftPos);
|
||||
charWidth = aRenderingContext.GetWidth(ch);
|
||||
charWidth = nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
|
||||
aRenderingContext);
|
||||
totalWidth += charWidth;
|
||||
if (totalWidth > aWidth)
|
||||
// greater than the allowable width
|
||||
@ -745,7 +748,9 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
if (rightPos > leftPos) {
|
||||
// haven't looked at this character yet
|
||||
ch = mTitle.CharAt(rightPos);
|
||||
charWidth = aRenderingContext.GetWidth(ch);
|
||||
charWidth =
|
||||
nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
|
||||
aRenderingContext);
|
||||
totalWidth += charWidth;
|
||||
if (totalWidth > aWidth)
|
||||
// greater than the allowable width
|
||||
@ -766,7 +771,7 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext,
|
||||
break;
|
||||
}
|
||||
|
||||
return nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
|
||||
return nsLayoutUtils::GetStringWidth(this, &aRenderingContext, *fm,
|
||||
mCroppedTitle.get(), mCroppedTitle.Length());
|
||||
}
|
||||
|
||||
@ -994,9 +999,8 @@ nsTextBoxFrame::GetTextSize(nsPresContext* aPresContext,
|
||||
nsRefPtr<nsFontMetrics> fontMet;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
|
||||
aSize.height = fontMet->MaxHeight();
|
||||
aRenderingContext.SetFont(fontMet);
|
||||
aSize.width =
|
||||
nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
|
||||
nsLayoutUtils::GetStringWidth(this, &aRenderingContext, *fontMet,
|
||||
aString.get(), aString.Length());
|
||||
aAscent = fontMet->MaxAscent();
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
class nsAccessKeyInfo;
|
||||
class nsAsyncAccesskeyUpdate;
|
||||
class nsFontMetrics;
|
||||
|
||||
typedef nsLeafBoxFrame nsTextBoxFrameSuper;
|
||||
class nsTextBoxFrame : public nsTextBoxFrameSuper
|
||||
@ -84,7 +85,8 @@ protected:
|
||||
nsRenderingContext& aRenderingContext,
|
||||
const nsRect& aRect);
|
||||
|
||||
void CalculateUnderline(nsRenderingContext& aRenderingContext);
|
||||
void CalculateUnderline(nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics);
|
||||
|
||||
void CalcTextSize(nsBoxLayoutState& aBoxLayoutState);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "gfxUtils.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
@ -1268,8 +1269,7 @@ nsTreeBodyFrame::GetCoordsForCellItem(int32_t aRow, nsITreeColumn* aCol, const n
|
||||
GetBorderPadding(textContext, bp);
|
||||
textRect.height += bp.top + bp.bottom;
|
||||
|
||||
rc->SetFont(fm);
|
||||
AdjustForCellText(cellText, aRow, currCol, *rc, textRect);
|
||||
AdjustForCellText(cellText, aRow, currCol, *rc, *fm, textRect);
|
||||
|
||||
theRect = textRect;
|
||||
}
|
||||
@ -1314,12 +1314,14 @@ void
|
||||
nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
|
||||
int32_t aRowIndex, nsTreeColumn* aColumn,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
nsFontMetrics& aFontMetrics,
|
||||
nsRect& aTextRect)
|
||||
{
|
||||
NS_PRECONDITION(aColumn && aColumn->GetFrame(), "invalid column passed");
|
||||
|
||||
nscoord width =
|
||||
nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aText.get(), aText.Length());
|
||||
nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aFontMetrics,
|
||||
aText.get(), aText.Length());
|
||||
nscoord maxWidth = aTextRect.width;
|
||||
|
||||
if (aColumn->Overflow()) {
|
||||
@ -1363,8 +1365,10 @@ nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
|
||||
// See if the width is even smaller than the ellipsis
|
||||
// If so, clear the text completely.
|
||||
const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
|
||||
aRenderingContext.SetTextRunRTL(false);
|
||||
nscoord ellipsisWidth = aRenderingContext.GetWidth(kEllipsis);
|
||||
aFontMetrics.SetTextRunRTL(false);
|
||||
nscoord ellipsisWidth =
|
||||
nsLayoutUtils::AppUnitWidthOfString(kEllipsis, aFontMetrics,
|
||||
aRenderingContext);
|
||||
|
||||
width = maxWidth;
|
||||
if (ellipsisWidth > width)
|
||||
@ -1389,7 +1393,8 @@ nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
|
||||
for (i = 0; i < length; ++i) {
|
||||
char16_t ch = aText[i];
|
||||
// XXX this is horrible and doesn't handle clusters
|
||||
cwidth = aRenderingContext.GetWidth(ch);
|
||||
cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
|
||||
aRenderingContext);
|
||||
if (twidth + cwidth > width)
|
||||
break;
|
||||
twidth += cwidth;
|
||||
@ -1407,7 +1412,8 @@ nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
|
||||
int32_t i;
|
||||
for (i=length-1; i >= 0; --i) {
|
||||
char16_t ch = aText[i];
|
||||
cwidth = aRenderingContext.GetWidth(ch);
|
||||
cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
|
||||
aRenderingContext);
|
||||
if (twidth + cwidth > width)
|
||||
break;
|
||||
twidth += cwidth;
|
||||
@ -1429,14 +1435,16 @@ nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
|
||||
int32_t rightPos = length - 1;
|
||||
for (int32_t leftPos = 0; leftPos < rightPos; ++leftPos) {
|
||||
char16_t ch = aText[leftPos];
|
||||
cwidth = aRenderingContext.GetWidth(ch);
|
||||
cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
|
||||
aRenderingContext);
|
||||
twidth += cwidth;
|
||||
if (twidth > width)
|
||||
break;
|
||||
leftStr.Append(ch);
|
||||
|
||||
ch = aText[rightPos];
|
||||
cwidth = aRenderingContext.GetWidth(ch);
|
||||
cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
|
||||
aRenderingContext);
|
||||
twidth += cwidth;
|
||||
if (twidth > width)
|
||||
break;
|
||||
@ -1451,7 +1459,9 @@ nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
|
||||
}
|
||||
}
|
||||
|
||||
width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aText.get(), aText.Length());
|
||||
width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
|
||||
aFontMetrics, aText.get(),
|
||||
aText.Length());
|
||||
}
|
||||
|
||||
switch (aColumn->GetTextAlignment()) {
|
||||
@ -1609,9 +1619,7 @@ nsTreeBodyFrame::GetItemWithinCellAt(nscoord aX, const nsRect& aCellRect,
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForStyleContext(textContext,
|
||||
getter_AddRefs(fm));
|
||||
rc->SetFont(fm);
|
||||
|
||||
AdjustForCellText(cellText, aRowIndex, aColumn, *rc, textRect);
|
||||
AdjustForCellText(cellText, aRowIndex, aColumn, *rc, *fm, textRect);
|
||||
|
||||
if (aX >= textRect.x && aX < textRect.x + textRect.width)
|
||||
return nsCSSAnonBoxes::moztreecelltext;
|
||||
@ -1739,11 +1747,10 @@ nsTreeBodyFrame::GetCellWidth(int32_t aRow, nsTreeColumn* aCol,
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForStyleContext(textContext,
|
||||
getter_AddRefs(fm));
|
||||
aRenderingContext->SetFont(fm);
|
||||
|
||||
// Get the width of the text itself
|
||||
nscoord width =
|
||||
nsLayoutUtils::GetStringWidth(this, aRenderingContext, cellText.get(), cellText.Length());
|
||||
nsLayoutUtils::GetStringWidth(this, aRenderingContext, *fm,
|
||||
cellText.get(), cellText.Length());
|
||||
nscoord totalTextWidth = width + bp.left + bp.right;
|
||||
aDesiredSize += totalTextWidth;
|
||||
return NS_OK;
|
||||
@ -3603,9 +3610,7 @@ nsTreeBodyFrame::PaintText(int32_t aRowIndex,
|
||||
}
|
||||
|
||||
// Set our font.
|
||||
aRenderingContext.SetFont(fontMet);
|
||||
|
||||
AdjustForCellText(text, aRowIndex, aColumn, aRenderingContext, textRect);
|
||||
AdjustForCellText(text, aRowIndex, aColumn, aRenderingContext, *fontMet, textRect);
|
||||
textRect.Inflate(bp);
|
||||
|
||||
// Subtract out the remaining width.
|
||||
@ -3656,8 +3661,10 @@ nsTreeBodyFrame::PaintText(int32_t aRowIndex,
|
||||
}
|
||||
|
||||
ctx->SetColor(textContext->StyleColor()->mColor);
|
||||
nsLayoutUtils::DrawString(this, &aRenderingContext, text.get(), text.Length(),
|
||||
textRect.TopLeft() + nsPoint(0, baseline), cellContext);
|
||||
nsLayoutUtils::DrawString(this, *fontMet, &aRenderingContext, text.get(),
|
||||
text.Length(),
|
||||
textRect.TopLeft() + nsPoint(0, baseline),
|
||||
cellContext);
|
||||
|
||||
if (opacity != 1.0f) {
|
||||
ctx->PopGroupToSource();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user