Merge inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2014-10-24 15:05:02 -07:00
commit a3f4d1e96c
123 changed files with 2245 additions and 1030 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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