Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2016-05-16 14:19:52 -07:00
commit c033991528
102 changed files with 1763 additions and 663 deletions

View File

@ -131,10 +131,12 @@ var FullScreen = {
let topWin = event.target.ownerDocument.defaultView.top;
browser = gBrowser.getBrowserForContentWindow(topWin);
}
TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
this.enterDomFullscreen(browser);
break;
}
case "MozDOMFullscreen:Exited":
TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
this.cleanupDomFullscreen();
break;
}
@ -157,6 +159,7 @@ var FullScreen = {
}
case "DOMFullscreen:Painted": {
Services.obs.notifyObservers(window, "fullscreen-painted", "");
TelemetryStopwatch.finish("FULLSCREEN_CHANGE_MS");
break;
}
}

View File

@ -268,7 +268,7 @@ tags = mcb
tags = mcb
[browser_bug906190.js]
tags = mcb
skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
skip-if = buildapp == "mulet" # Bug 1093642 - test manipulates content and relies on content focus
[browser_mixedContentFromOnunload.js]
tags = mcb
[browser_mixedContentFramesOnHttp.js]

View File

@ -192,8 +192,6 @@ add_task(function* test_same_origin_metarefresh_different_origin() {
* - Doorhanger to disable protection appears - we disable it
* - Load a new page from the same origin in a new tab simulating a click
* - Redirect to another page from the same origin using 302 redirect
* - Doorhanger >> APPEARS << , but should >> NOT << appear again!
* - FOLLOW UP BUG 914860!
*/
add_task(function* test_same_origin_302redirect_same_origin() {
// the sjs files returns a 302 redirect- note, same origins
@ -201,10 +199,10 @@ add_task(function* test_same_origin_302redirect_same_origin() {
gHttpTestRoot1 + "file_bug906190.sjs", function* () {
// The doorhanger should appear but activeBlocked should be >> NOT << true.
// Currently it is >> TRUE << - see follow up bug 914860
todo(!gIdentityHandler._identityBox.classList.contains("mixedActiveBlocked"),
ok(!gIdentityHandler._identityBox.classList.contains("mixedActiveBlocked"),
"OK: Mixed Content is NOT being blocked");
todo_is(content.document.getElementById('mctestdiv').innerHTML,
is(content.document.getElementById('mctestdiv').innerHTML,
"Mixed Content Blocker disabled", "OK: Executed mixed script");
});
});
@ -214,7 +212,6 @@ add_task(function* test_same_origin_302redirect_same_origin() {
* - Doorhanger to disable protection appears - we disable it
* - Load a new page from the same origin in a new tab simulating a click
* - Redirect to another page from a different origin using 302 redirect
* - Doorhanger >> SHOULD << appear again!
*/
add_task(function* test_same_origin_302redirect_different_origin() {
// the sjs files returns a 302 redirect - note, different origins
@ -229,3 +226,15 @@ add_task(function* test_same_origin_302redirect_different_origin() {
"Mixed Content Blocker enabled", "OK: Blocked mixed script");
});
});
/**
* 7. - Test memory leak issue on redirection error. See Bug 1269426.
*/
add_task(function* test_bad_redirection() {
// the sjs files returns a 302 redirect - note, different origins
yield doTest(gHttpTestRoot2 + "file_bug906190_1.html",
gHttpTestRoot2 + "file_bug906190.sjs?bad-redirection=1", function* () {
// Nothing to do. Just see if memory leak is reported in the end.
ok(true, "Nothing to do");
});
});

View File

@ -1,7 +1,13 @@
function handleRequest(request, response) {
var page = "<!DOCTYPE html><html><body>bug 906190</body></html>";
var path = "https://test1.example.com/browser/browser/base/content/test/general/";
var url = path + "file_bug906190_redirected.html";
var url;
if (request.queryString.includes('bad-redirection=1')) {
url = path + "this_page_does_not_exist.html";
} else {
url = path + "file_bug906190_redirected.html";
}
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);

View File

@ -7353,6 +7353,19 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
{
NS_ASSERTION(aStateFlags & STATE_REDIRECTING,
"Calling OnRedirectStateChange when there is no redirect");
// If mixed content is allowed for the old channel, we forward
// the permission to the new channel if it has the same origin
// as the old one.
if (mMixedContentChannel && mMixedContentChannel == aOldChannel) {
nsresult rv = nsContentUtils::CheckSameOrigin(mMixedContentChannel, aNewChannel);
if (NS_SUCCEEDED(rv)) {
SetMixedContentChannel(aNewChannel); // Same origin: forward permission.
} else {
SetMixedContentChannel(nullptr); // Different origin: clear mMixedContentChannel.
}
}
if (!(aStateFlags & STATE_IS_DOCUMENT)) {
return; // not a toplevel document
}

View File

@ -690,6 +690,14 @@ KeyframeEffectReadOnly::SetIsRunningOnCompositor(nsCSSProperty aProperty,
}
}
void
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
{
for (AnimationProperty& property : mProperties) {
property.mIsRunningOnCompositor = false;
}
}
KeyframeEffectReadOnly::~KeyframeEffectReadOnly()
{
}
@ -750,14 +758,6 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(
return effect.forget();
}
void
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
{
for (AnimationProperty& property : mProperties) {
property.mIsRunningOnCompositor = false;
}
}
void
KeyframeEffectReadOnly::ResetWinsInCascade()
{

View File

@ -312,6 +312,7 @@ public:
// Returns true if at least one property is being animated on compositor.
bool IsRunningOnCompositor() const;
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
void ResetIsRunningOnCompositor();
// Returns true if this effect, applied to |aFrame|, contains properties
// that mean we shouldn't run transform compositor animations on this element.
@ -352,7 +353,6 @@ protected:
const OptionsType& aOptions,
ErrorResult& aRv);
void ResetIsRunningOnCompositor();
void ResetWinsInCascade();
// This effect is registered with its target element so long as:

View File

@ -421,7 +421,7 @@ waitForAllPaints(function() {
'Opacity script animations keep running even when the target element ' +
'has "display: none" style');
todo(!animation.isRunningOnCompositor,
ok(!animation.isRunningOnCompositor,
'Opacity script animations on "display:none" element should not ' +
'run on the compositor');

View File

@ -103,6 +103,11 @@
#include "nsXULPopupManager.h"
#endif
#ifdef NS_PRINTING
#include "mozilla/embedding/printingui/PrintingParent.h"
#include "nsIWebBrowserPrint.h"
#endif
using namespace mozilla;
using namespace mozilla::hal;
using namespace mozilla::dom;
@ -3102,6 +3107,46 @@ nsFrameLoader::RequestNotifyLayerTreeCleared()
return NS_OK;
}
NS_IMETHODIMP
nsFrameLoader::Print(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aProgressListener)
{
#if defined(NS_PRINTING)
if (mRemoteBrowser) {
RefPtr<embedding::PrintingParent> printingParent =
mRemoteBrowser->Manager()->AsContentParent()->GetPrintingParent();
embedding::PrintData printData;
nsresult rv = printingParent->SerializeAndEnsureRemotePrintJob(
aPrintSettings, aProgressListener, nullptr, &printData);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool success = mRemoteBrowser->SendPrint(printData);
return success ? NS_OK : NS_ERROR_FAILURE;
}
if (mDocShell) {
nsCOMPtr<nsIContentViewer> viewer;
mDocShell->GetContentViewer(getter_AddRefs(viewer));
if (!viewer) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint = do_QueryInterface(viewer);
if (!webBrowserPrint) {
return NS_ERROR_FAILURE;
}
return webBrowserPrint->Print(aPrintSettings, aProgressListener);
}
return NS_ERROR_FAILURE;
#endif
return NS_OK;
}
/* [infallible] */ NS_IMETHODIMP
nsFrameLoader::SetVisible(bool aVisible)
{

View File

@ -6248,6 +6248,7 @@ private:
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsISupports> mTransitionData;
TimeStamp mFullscreenChangeStartTime;
FullscreenTransitionDuration mDuration;
Stage mStage;
bool mFullscreen;
@ -6274,6 +6275,7 @@ FullscreenTransitionTask::Run()
this);
} else if (stage == eToggleFullscreen) {
PROFILER_MARKER("Fullscreen toggle start");
mFullscreenChangeStartTime = TimeStamp::Now();
if (MOZ_UNLIKELY(mWindow->mFullScreen != mFullscreen)) {
// This could happen in theory if several fullscreen requests in
// different direction happen continuously in a short time. We
@ -6310,6 +6312,8 @@ FullscreenTransitionTask::Run()
Preferences::GetUint("full-screen-api.transition.timeout", 500);
mTimer->Init(observer, timeout, nsITimer::TYPE_ONE_SHOT);
} else if (stage == eAfterToggle) {
Telemetry::AccumulateTimeDelta(Telemetry::FULLSCREEN_TRANSITION_BLACK_MS,
mFullscreenChangeStartTime);
mWidget->PerformFullscreenTransition(nsIWidget::eAfterFullscreenToggle,
mDuration.mFadeOut, mTransitionData,
this);

View File

@ -16,6 +16,8 @@ interface nsIVariant;
interface nsIDOMElement;
interface nsITabParent;
interface nsILoadContext;
interface nsIPrintSettings;
interface nsIWebProgressListener;
[scriptable, builtinclass, uuid(1645af04-1bc7-4363-8f2c-eb9679220ab1)]
interface nsIFrameLoader : nsISupports
@ -139,6 +141,16 @@ interface nsIFrameLoader : nsISupports
void requestNotifyLayerTreeReady();
void requestNotifyLayerTreeCleared();
/**
* Print the current document.
*
* @param aPrintSettings optional print settings to use; printSilent can be
* set to prevent prompting.
* @param aProgressListener optional print progress listener.
*/
void print(in nsIPrintSettings aPrintSettings,
in nsIWebProgressListener aProgressListener);
/**
* The default event mode automatically forwards the events
* handled in EventStateManager::HandleCrossProcessEvent to

View File

@ -1186,9 +1186,8 @@ nsDOMCameraControl::NotifyRecordingStatusChange(const nsString& aMsg)
// Camera app will stop recording when it falls to the background, so no callback is necessary.
mAudioChannelAgent->Init(mWindow, (int32_t)AudioChannel::Content, nullptr);
// Video recording doesn't output any sound, so it's not necessary to check canPlay.
float volume = 0.0;
bool muted = true;
rv = mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
AudioPlaybackConfig config;
rv = mAudioChannelAgent->NotifyStartedPlaying(&config, AudioChannelService::AudibleState::eAudible);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

View File

@ -107,6 +107,7 @@
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsContentPermissionHelper.h"
#include "nsPrintingProxy.h"
#include "IHistory.h"
#include "nsNetUtil.h"
@ -711,6 +712,11 @@ ContentChild::Init(MessageLoop* aIOLoop,
NuwaAddConstructor(ResetTransports, nullptr);
}
#endif
#ifdef NS_PRINTING
// Force the creation of the nsPrintingProxy so that it's IPC counterpart,
// PrintingParent, is always available for printing initiated from the parent.
RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
#endif
return true;
}
@ -930,13 +936,13 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
renderFrame = nullptr;
}
ShowInfo showInfo(EmptyString(), false, false, true, 0, 0);
ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0);
auto* opener = nsPIDOMWindowOuter::From(aParent);
nsIDocShell* openerShell;
if (opener && (openerShell = opener->GetDocShell())) {
nsCOMPtr<nsILoadContext> context = do_QueryInterface(openerShell);
showInfo = ShowInfo(EmptyString(), false,
context->UsePrivateBrowsing(), true,
context->UsePrivateBrowsing(), true, false,
aTabOpener->mDPI, aTabOpener->mDefaultScale);
}

View File

@ -86,6 +86,7 @@
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/PAPZParent.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeParent.h"
#include "mozilla/layers/SharedBufferManagerParent.h"
#include "mozilla/layout/RenderFrameParent.h"
@ -2558,7 +2559,7 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
// PBrowsers are created, because they rely on the Compositor
// already being around. (Creation is async, so can't happen
// on demand.)
bool useOffMainThreadCompositing = !!CompositorBridgeParent::CompositorLoop();
bool useOffMainThreadCompositing = !!CompositorThreadHolder::Loop();
if (useOffMainThreadCompositing) {
DebugOnly<bool> opened = PCompositorBridge::Open(this);
MOZ_ASSERT(opened);
@ -3819,24 +3820,42 @@ PPrintingParent*
ContentParent::AllocPPrintingParent()
{
#ifdef NS_PRINTING
return new PrintingParent();
MOZ_ASSERT(!mPrintingParent,
"Only one PrintingParent should be created per process.");
// Create the printing singleton for this process.
mPrintingParent = new PrintingParent();
return mPrintingParent.get();
#else
MOZ_ASSERT_UNREACHABLE("Should never be created if no printing.");
return nullptr;
#endif
}
bool
ContentParent::RecvPPrintingConstructor(PPrintingParent* aActor)
ContentParent::DeallocPPrintingParent(PPrintingParent* printing)
{
#ifdef NS_PRINTING
MOZ_ASSERT(mPrintingParent == printing,
"Only one PrintingParent should have been created per process.");
mPrintingParent = nullptr;
#else
MOZ_ASSERT_UNREACHABLE("Should never have been created if no printing.");
#endif
return true;
}
bool
ContentParent::DeallocPPrintingParent(PPrintingParent* printing)
#ifdef NS_PRINTING
already_AddRefed<embedding::PrintingParent>
ContentParent::GetPrintingParent()
{
delete printing;
return true;
MOZ_ASSERT(mPrintingParent);
RefPtr<embedding::PrintingParent> printingParent = mPrintingParent;
return printingParent.forget();
}
#endif
PSendStreamParent*
ContentParent::AllocPSendStreamParent()

View File

@ -49,6 +49,10 @@ class SandboxBroker;
class SandboxBrokerPolicyFactory;
#endif
namespace embedding {
class PrintingParent;
}
namespace ipc {
class OptionalURIParams;
class PFileDescriptorSetParent;
@ -380,10 +384,15 @@ public:
virtual PPrintingParent* AllocPPrintingParent() override;
virtual bool RecvPPrintingConstructor(PPrintingParent* aActor) override;
virtual bool DeallocPPrintingParent(PPrintingParent* aActor) override;
#if defined(NS_PRINTING)
/**
* @return the PrintingParent for this ContentParent.
*/
already_AddRefed<embedding::PrintingParent> GetPrintingParent();
#endif
virtual PSendStreamParent* AllocPSendStreamParent() override;
virtual bool DeallocPSendStreamParent(PSendStreamParent* aActor) override;
@ -1200,6 +1209,10 @@ private:
static mozilla::UniquePtr<SandboxBrokerPolicyFactory>
sSandboxBrokerPolicyFactory;
#endif
#ifdef NS_PRINTING
RefPtr<embedding::PrintingParent> mPrintingParent;
#endif
};
} // namespace dom

View File

@ -15,10 +15,12 @@ include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
include protocol PPluginWidget;
include protocol PRemotePrintJob;
include DOMTypes;
include JavaScriptTypes;
include URIParams;
include BrowserConfiguration;
include PPrintingTypes;
include PTabContext;
@ -92,6 +94,7 @@ struct ShowInfo
bool fullscreenAllowed;
bool isPrivate;
bool fakeShowInfo;
bool isTransparent;
float dpi;
double defaultScale;
};
@ -781,6 +784,13 @@ child:
async HandledWindowedPluginKeyEvent(NativeEventData aKeyEventData,
bool aIsConsumed);
/**
* Tell the child to print the current page with the given settings.
*
* @param aPrintData the serialized settings to print with
*/
async Print(PrintData aPrintData);
/*
* FIXME: write protocol!

View File

@ -112,6 +112,13 @@
#include "nsDeviceContext.h"
#include "FrameLayerBuilder.h"
#ifdef NS_PRINTING
#include "nsIPrintSession.h"
#include "nsIPrintSettings.h"
#include "nsIPrintSettingsService.h"
#include "nsIWebBrowserPrint.h"
#endif
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -591,6 +598,7 @@ TabChild::TabChild(nsIContentChild* aManager,
, mUniqueId(aTabId)
, mDPI(0)
, mDefaultScale(0)
, mIsTransparent(false)
, mIPCOpen(true)
, mParentIsActive(false)
, mDidSetRealShowInfo(false)
@ -1302,30 +1310,6 @@ TabChild::SetProcessNameToAppName()
ContentChild::GetSingleton()->SetProcessName(appName, true);
}
bool
TabChild::IsRootContentDocument() const
{
// A TabChild is a "root content document" if it's
//
// - <iframe mozapp> not inside another <iframe mozapp>,
// - <iframe mozbrowser> (not mozapp), or
// - a vanilla remote frame (<html:iframe remote=true> or <xul:browser
// remote=true>).
//
// Put another way, an iframe is /not/ a "root content document" iff it's a
// mozapp inside a mozapp. (This corresponds exactly to !HasAppOwnerApp.)
//
// Note that we're lying through our teeth here (thus the scare quotes).
// <html:iframe remote=true> or <xul:browser remote=true> inside another
// content iframe is not actually a root content document, but we say it is.
//
// We do this because we make a remote frame opaque iff
// IsRootContentDocument(), and making vanilla remote frames transparent
// breaks our remote reftests.
return !HasAppOwnerApp();
}
bool
TabChild::RecvLoadURL(const nsCString& aURI,
const BrowserConfiguration& aConfiguration,
@ -1564,6 +1548,7 @@ TabChild::ApplyShowInfo(const ShowInfo& aInfo)
}
mDPI = aInfo.dpi();
mDefaultScale = aInfo.defaultScale();
mIsTransparent = aInfo.isTransparent();
}
#ifdef MOZ_WIDGET_GONK
@ -2457,6 +2442,45 @@ TabChild::RecvSetUseGlobalHistory(const bool& aUse)
return true;
}
bool
TabChild::RecvPrint(const PrintData& aPrintData)
{
#ifdef NS_PRINTING
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint = do_GetInterface(mWebNav);
if (NS_WARN_IF(!webBrowserPrint)) {
return true;
}
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1");
if (NS_WARN_IF(!printSettingsSvc)) {
return true;
}
nsCOMPtr<nsIPrintSettings> printSettings;
nsresult rv =
printSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
nsCOMPtr<nsIPrintSession> printSession =
do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
printSettings->SetPrintSession(printSession);
printSettingsSvc->DeserializeToPrintSettings(aPrintData, printSettings);
rv = webBrowserPrint->Print(printSettings, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
#endif
return true;
}
bool
TabChild::RecvDestroy()
{
@ -2994,7 +3018,7 @@ TabChild::InvalidateLayers()
void
TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier)
{
gfxPlatform::GetPlatform()->UpdateRenderModeIfDeviceReset();
gfxPlatform::GetPlatform()->CompositorUpdated();
RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
ClientLayerManager* clm = lm->AsClientLayerManager();

View File

@ -194,12 +194,12 @@ public:
// Get the Document for the top-level window in this tab.
already_AddRefed<nsIDocument> GetDocument() const;
protected:
virtual ~TabChildBase();
// Get the pres-shell of the document for the top-level window in this tab.
already_AddRefed<nsIPresShell> GetPresShell() const;
protected:
virtual ~TabChildBase();
// Wraps up a JSON object as a structured clone and sends it to the browser
// chrome script.
//
@ -265,8 +265,6 @@ public:
Create(nsIContentChild* aManager, const TabId& aTabId,
const TabContext& aContext, uint32_t aChromeFlags);
bool IsRootContentDocument() const;
// Let managees query if it is safe to send messages.
bool IsDestroyed() const{ return mDestroyed; }
@ -476,6 +474,8 @@ public:
void GetDefaultScale(double *aScale);
bool IsTransparent() const { return mIsTransparent; }
void GetMaxTouchPoints(uint32_t* aTouchPoints);
ScreenOrientationInternal GetOrientation() const { return mOrientation; }
@ -580,6 +580,8 @@ public:
const mozilla::NativeEventData& aKeyEventData,
const bool& aIsConsumed) override;
virtual bool RecvPrint(const PrintData& aPrintData) override;
/**
* Native widget remoting protocol for use with windowed plugins with e10s.
*/
@ -751,6 +753,8 @@ private:
float mDPI;
double mDefaultScale;
bool mIsTransparent;
bool mIPCOpen;
bool mParentIsActive;
bool mAsyncPanZoomEnabled;

View File

@ -3325,12 +3325,15 @@ TabParent::GetShowInfo()
mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen);
bool isPrivate = mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing);
bool isTransparent =
nsContentUtils::IsChromeDoc(mFrameElement->OwnerDoc()) &&
mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
return ShowInfo(name, allowFullscreen, isPrivate, false,
mDPI, mDefaultScale.scale);
isTransparent, mDPI, mDefaultScale.scale);
}
return ShowInfo(EmptyString(), false, false, false,
mDPI, mDefaultScale.scale);
false, mDPI, mDefaultScale.scale);
}
void

View File

@ -187,6 +187,7 @@ WidevineDecryptor::DecryptingComplete()
{
Log("WidevineDecryptor::DecryptingComplete() this=%p", this);
mCDM = nullptr;
mCallback = nullptr;
Release();
}

View File

@ -1969,6 +1969,32 @@ TrackBuffersManager::SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack,
return parsed;
}
const MediaRawData*
TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack,
size_t aIndex,
const TimeUnit& aExpectedDts,
const TimeUnit& aExpectedPts,
const TimeUnit& aFuzz)
{
const TrackBuffer& track = GetTrackBuffer(aTrack);
if (aIndex >= track.Length()) {
// reached the end.
return nullptr;
}
const RefPtr<MediaRawData>& sample = track[aIndex];
if (!aIndex || sample->mTimecode <= (aExpectedDts + aFuzz).ToMicroseconds() ||
sample->mTime <= (aExpectedPts + aFuzz).ToMicroseconds()) {
return sample;
}
// Gap is too big. End of Stream or Waiting for Data.
// TODO, check that we have continuous data based on the sanitized buffered
// range instead.
return nullptr;
}
already_AddRefed<MediaRawData>
TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack,
const TimeUnit& aFuzz,
@ -1980,9 +2006,7 @@ TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack,
aError = false;
if (!track.Length() ||
(trackData.mNextGetSampleIndex.isSome() &&
trackData.mNextGetSampleIndex.ref() >= track.Length())) {
if (!track.Length()) {
return nullptr;
}
if (trackData.mNextGetSampleIndex.isNothing() &&
@ -1992,11 +2016,13 @@ TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack,
}
if (trackData.mNextGetSampleIndex.isSome()) {
const RefPtr<MediaRawData>& sample =
track[trackData.mNextGetSampleIndex.ref()];
if (trackData.mNextGetSampleIndex.ref() &&
sample->mTimecode > (trackData.mNextSampleTimecode + aFuzz).ToMicroseconds()) {
// Gap is too big. End of Stream or Waiting for Data.
const MediaRawData* sample =
GetSample(aTrack,
trackData.mNextGetSampleIndex.ref(),
trackData.mNextSampleTimecode,
trackData.mNextSampleTime,
aFuzz);
if (!sample) {
return nullptr;
}
@ -2078,11 +2104,12 @@ TrackBuffersManager::GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
uint32_t i = trackData.mNextGetSampleIndex.ref();
TimeUnit nextSampleTimecode = trackData.mNextSampleTimecode;
TimeUnit nextSampleTime = trackData.mNextSampleTime;
for (; i < track.Length(); i++) {
const RefPtr<MediaRawData>& sample = track[i];
if (sample->mTimecode > (nextSampleTimecode + aFuzz).ToMicroseconds()) {
// Gap is too big. End of Stream or Waiting for Data.
const MediaRawData* sample =
GetSample(aTrack, i, nextSampleTimecode, nextSampleTime, aFuzz);
if (!sample) {
break;
}
if (sample->mKeyframe) {
@ -2090,6 +2117,7 @@ TrackBuffersManager::GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
}
nextSampleTimecode =
TimeUnit::FromMicroseconds(sample->mTimecode + sample->mDuration);
nextSampleTime = TimeUnit::FromMicroseconds(sample->GetEndTime());
}
return TimeUnit::FromInfinity();
}

View File

@ -340,6 +340,11 @@ private:
// Find index of sample. Return a negative value if not found.
uint32_t FindSampleIndex(const TrackBuffer& aTrackBuffer,
const media::TimeInterval& aInterval);
const MediaRawData* GetSample(TrackInfo::TrackType aTrack,
size_t aIndex,
const media::TimeUnit& aExpectedDts,
const media::TimeUnit& aExpectedPts,
const media::TimeUnit& aFuzz);
void UpdateBufferedRanges();
void RejectProcessing(nsresult aRejectValue, const char* aName);
void ResolveProcessing(bool aResolveValue, const char* aName);

View File

@ -5,7 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaSystemResourceManagerParent.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/unused.h"
#include "MediaSystemResourceService.h"
@ -46,7 +46,7 @@ MediaSystemResourceService::Shutdown()
MediaSystemResourceService::MediaSystemResourceService()
: mDestroyed(false)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
#ifdef MOZ_WIDGET_GONK
// The maximum number of hardware resoureces available.
// XXX need to hange to a dynamic way.
@ -82,7 +82,7 @@ MediaSystemResourceService::Acquire(media::MediaSystemResourceManagerParent* aPa
MediaSystemResourceType aResourceType,
bool aWillWait)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aParent);
if (mDestroyed) {
@ -123,7 +123,7 @@ MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerPar
uint32_t aId,
MediaSystemResourceType aResourceType)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aParent);
if (mDestroyed) {

View File

@ -23,6 +23,7 @@ sync protocol PPrinting
parent:
sync ShowProgress(PBrowser browser,
PPrintProgressDialog printProgressDialog,
PRemotePrintJob remotePrintJob,
bool isForPrinting)
returns(bool notifyOnOpen,
nsresult rv);

View File

@ -6,14 +6,15 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/unused.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintOptions.h"
#include "nsIPrintProgressParams.h"
#include "nsIPrintSettingsService.h"
#include "nsIServiceManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIWebProgressListener.h"
#include "PrintingParent.h"
#include "PrintDataUtils.h"
@ -30,6 +31,7 @@ namespace embedding {
bool
PrintingParent::RecvShowProgress(PBrowserParent* parent,
PPrintProgressDialogParent* printProgressDialog,
PRemotePrintJobParent* remotePrintJob,
const bool& isForPrinting,
bool* notifyOnOpen,
nsresult* result)
@ -62,7 +64,15 @@ PrintingParent::RecvShowProgress(PBrowserParent* parent,
notifyOnOpen);
NS_ENSURE_SUCCESS(*result, true);
if (remotePrintJob) {
// If we have a RemotePrintJob use that as a more general forwarder for
// print progress listeners.
static_cast<RemotePrintJobParent*>(remotePrintJob)
->RegisterListener(printProgressListener);
} else {
dialogParent->SetWebProgressListener(printProgressListener);
}
dialogParent->SetPrintProgressParams(printProgressParams);
return true;
@ -88,25 +98,22 @@ PrintingParent::ShowPrintDialog(PBrowserParent* aParent,
// nsIWebBrowserPrint to keep the dialogs happy.
nsCOMPtr<nsIWebBrowserPrint> wbp = new MockWebBrowserPrint(aData);
nsresult rv;
nsCOMPtr<nsIPrintOptions> po = do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrintSettings> settings;
rv = po->CreatePrintSettings(getter_AddRefs(settings));
nsresult rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(rv, rv);
rv = po->DeserializeToPrintSettings(aData, settings);
rv = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(rv, rv);
rv = pps->ShowPrintDialog(parentWin, wbp, settings);
NS_ENSURE_SUCCESS(rv, rv);
// And send it back.
rv = po->SerializeToPrintData(settings, nullptr, aResult);
PRemotePrintJobParent* remotePrintJob = new RemotePrintJobParent(settings);
aResult->remotePrintJobParent() = SendPRemotePrintJobConstructor(remotePrintJob);
// Serialize back to aResult. Use the existing RemotePrintJob if we have one
// otherwise SerializeAndEnsureRemotePrintJob() will create a new one.
RemotePrintJobParent* remotePrintJob =
static_cast<RemotePrintJobParent*>(aData.remotePrintJobParent());
rv = SerializeAndEnsureRemotePrintJob(settings, nullptr, remotePrintJob,
aResult);
return rv;
}
@ -137,21 +144,16 @@ PrintingParent::RecvSavePrintSettings(const PrintData& aData,
const uint32_t& aFlags,
nsresult* aResult)
{
nsCOMPtr<nsIPrintSettingsService> pss =
do_GetService("@mozilla.org/gfx/printsettings-service;1", aResult);
NS_ENSURE_SUCCESS(*aResult, true);
nsCOMPtr<nsIPrintOptions> po = do_QueryInterface(pss, aResult);
NS_ENSURE_SUCCESS(*aResult, true);
nsCOMPtr<nsIPrintSettings> settings;
*aResult = po->CreatePrintSettings(getter_AddRefs(settings));
*aResult = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(*aResult, true);
*aResult = po->DeserializeToPrintSettings(aData, settings);
*aResult = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(*aResult, true);
*aResult = pss->SavePrintSettingsToPrefs(settings, aUsePrinterNamePrefix, aFlags);
*aResult = mPrintSettingsSvc->SavePrintSettingsToPrefs(settings,
aUsePrinterNamePrefix,
aFlags);
return true;
}
@ -238,9 +240,53 @@ PrintingParent::DOMWindowFromBrowserParent(PBrowserParent* parent)
return parentWin;
}
nsresult
PrintingParent::SerializeAndEnsureRemotePrintJob(
nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
layout::RemotePrintJobParent* aRemotePrintJob, PrintData* aPrintData)
{
MOZ_ASSERT(aPrintData);
nsresult rv;
nsCOMPtr<nsIPrintSettings> printSettings;
if (aPrintSettings) {
printSettings = aPrintSettings;
} else {
rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
rv = mPrintSettingsSvc->SerializeToPrintData(aPrintSettings, nullptr,
aPrintData);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RemotePrintJobParent* remotePrintJob;
if (aRemotePrintJob) {
remotePrintJob = aRemotePrintJob;
aPrintData->remotePrintJobParent() = remotePrintJob;
} else {
remotePrintJob = new RemotePrintJobParent(aPrintSettings);
aPrintData->remotePrintJobParent() =
SendPRemotePrintJobConstructor(remotePrintJob);
}
if (aListener) {
remotePrintJob->RegisterListener(aListener);
}
return NS_OK;
}
PrintingParent::PrintingParent()
{
MOZ_COUNT_CTOR(PrintingParent);
mPrintSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1");
MOZ_ASSERT(mPrintSettingsSvc);
}
PrintingParent::~PrintingParent()

View File

@ -10,6 +10,8 @@
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/embedding/PPrintingParent.h"
class nsIPrintSettingsService;
class nsIWebProgressListener;
class nsPIDOMWindowOuter;
class PPrintProgressDialogParent;
class PPrintSettingsDialogParent;
@ -17,6 +19,7 @@ class PPrintSettingsDialogParent;
namespace mozilla {
namespace layout {
class PRemotePrintJobParent;
class RemotePrintJobParent;
}
namespace embedding {
@ -24,9 +27,12 @@ namespace embedding {
class PrintingParent final : public PPrintingParent
{
public:
NS_INLINE_DECL_REFCOUNTING(PrintingParent)
virtual bool
RecvShowProgress(PBrowserParent* parent,
PPrintProgressDialogParent* printProgressDialog,
PRemotePrintJobParent* remotePrintJob,
const bool& isForPrinting,
bool* notifyOnOpen,
nsresult* result);
@ -63,9 +69,29 @@ public:
ActorDestroy(ActorDestroyReason aWhy);
MOZ_IMPLICIT PrintingParent();
virtual ~PrintingParent();
/**
* Serialize nsIPrintSettings to PrintData ready for sending to a child
* process. A RemotePrintJob will be created and added to the PrintData.
* An optional progress listener can be given, which will be registered
* with the RemotePrintJob, so that progress can be tracked in the parent.
*
* @param aPrintSettings optional print settings to serialize, otherwise a
* default print settings will be used.
* @param aProgressListener optional print progress listener.
* @param aRemotePrintJob optional remote print job, so that an existing
* one can be used.
* @param aPrintData PrintData to populate.
*/
nsresult
SerializeAndEnsureRemotePrintJob(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aListener,
layout::RemotePrintJobParent* aRemotePrintJob,
PrintData* aPrintData);
private:
virtual ~PrintingParent();
nsPIDOMWindowOuter*
DOMWindowFromBrowserParent(PBrowserParent* parent);
@ -73,6 +99,8 @@ private:
ShowPrintDialog(PBrowserParent* parent,
const PrintData& data,
PrintData* result);
nsCOMPtr<nsIPrintSettingsService> mPrintSettingsSvc;
};
} // namespace embedding

View File

@ -14,10 +14,13 @@
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintSession.h"
#include "nsPIDOMWindow.h"
#include "nsPrintOptionsImpl.h"
#include "nsServiceManagerUtils.h"
#include "PrintDataUtils.h"
#include "PrintProgressDialogChild.h"
#include "PrintSettingsDialogChild.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -87,12 +90,13 @@ nsPrintingProxy::ShowPrintDialog(mozIDOMWindowProxy *parent,
// Next, serialize the nsIWebBrowserPrint and nsIPrintSettings we were given.
nsresult rv = NS_OK;
nsCOMPtr<nsIPrintOptions> po =
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PrintData inSettings;
rv = po->SerializeToPrintData(printSettings, webBrowserPrint, &inSettings);
rv = printSettingsSvc->SerializeToPrintData(printSettings, webBrowserPrint,
&inSettings);
NS_ENSURE_SUCCESS(rv, rv);
// Now, the waiting game. The parent process should be showing
@ -112,7 +116,8 @@ nsPrintingProxy::ShowPrintDialog(mozIDOMWindowProxy *parent,
rv = dialog->result();
NS_ENSURE_SUCCESS(rv, rv);
rv = po->DeserializeToPrintSettings(dialog->data(), printSettings);
rv = printSettingsSvc->DeserializeToPrintSettings(dialog->data(),
printSettings);
return NS_OK;
}
@ -145,14 +150,29 @@ nsPrintingProxy::ShowProgress(mozIDOMWindowProxy* parent,
SendPPrintProgressDialogConstructor(dialogChild);
// Get the RemotePrintJob if we have one available.
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
if (printSettings) {
nsCOMPtr<nsIPrintSession> printSession;
nsresult rv = printSettings->GetPrintSession(getter_AddRefs(printSession));
if (NS_SUCCEEDED(rv) && printSession) {
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
}
}
nsresult rv = NS_OK;
mozilla::Unused << SendShowProgress(pBrowser, dialogChild,
mozilla::Unused << SendShowProgress(pBrowser, dialogChild, remotePrintJob,
isForPrinting, notifyOnOpen, &rv);
if (NS_FAILED(rv)) {
return rv;
}
// If we have a RemotePrintJob that will be being used as a more general
// forwarder for print progress listeners. Once we always have one we can
// remove the interface from PrintProgressDialogChild.
if (!remotePrintJob) {
NS_ADDREF(*webProgressListener = dialogChild);
}
NS_ADDREF(*printProgressParams = dialogChild);
return NS_OK;
@ -180,12 +200,12 @@ nsPrintingProxy::SavePrintSettings(nsIPrintSettings* aPS,
uint32_t aFlags)
{
nsresult rv;
nsCOMPtr<nsIPrintOptions> po =
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PrintData settings;
rv = po->SerializeToPrintData(aPS, nullptr, &settings);
rv = printSettingsSvc->SerializeToPrintData(aPS, nullptr, &settings);
NS_ENSURE_SUCCESS(rv, rv);
Unused << SendSavePrintSettings(settings, aUsePrinterNamePrefix, aFlags,

View File

@ -7,6 +7,7 @@
#include "base/message_loop.h" // for MessageLoop
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent
#include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "gfx2DGlue.h"
#include "nsAppRunner.h"
@ -25,8 +26,8 @@ namespace layers {
/* static */ void
Compositor::AssertOnCompositorThread()
{
MOZ_ASSERT(!CompositorBridgeParent::CompositorLoop() ||
CompositorBridgeParent::CompositorLoop() == MessageLoop::current(),
MOZ_ASSERT(!CompositorThreadHolder::Loop() ||
CompositorThreadHolder::Loop() == MessageLoop::current(),
"Can only call this from the compositor thread!");
}

View File

@ -195,6 +195,8 @@ public:
: mCompositorID(0)
, mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
, mParent(aParent)
, mPixelsPerFrame(0)
, mPixelsFilled(0)
, mScreenRotation(ROTATION_0)
, mWidget(aWidget)
{

View File

@ -17,7 +17,7 @@
#include "TexturePoolOGL.h"
#include "mozilla/layers/CompositorOGL.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/TextureHostOGL.h"
@ -1899,7 +1899,7 @@ bool
LayerScope::CheckSendable()
{
// Only compositor threads check LayerScope status
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread() || gIsGtest);
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || gIsGtest);
if (!gfxPrefs::LayerScopeEnabled()) {
return false;

View File

@ -503,6 +503,14 @@ CanvasClientSharedSurface::Updated()
forwarder->UseTextures(this, textures);
}
void
CanvasClientSharedSurface::OnDetach() {
if (mShSurfClient) {
mShSurfClient->CancelWaitForCompositorRecycle();
}
ClearSurfaces();
}
void
CanvasClientSharedSurface::ClearSurfaces()
{

View File

@ -160,9 +160,7 @@ public:
virtual void Updated() override;
virtual void OnDetach() override {
ClearSurfaces();
}
virtual void OnDetach() override;
};
/**

View File

@ -205,6 +205,7 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
if (DependsOnStaleDevice()) {
FrameLayerBuilder::InvalidateAllLayers(this);
mDeviceCounter = gfxPlatform::GetPlatform()->GetDeviceCounter();
}
MOZ_ASSERT(mKeepAlive.IsEmpty(), "uncommitted txn?");

View File

@ -23,6 +23,7 @@
#include "mozilla/layers/APZUtils.h" // for CompleteAsyncTransform
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent, etc
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayerAnimationUtils.h" // for TimingFunctionToComputedTimingFunction
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
#include "nsCoord.h" // for NSAppUnitsToFloatPixels, etc
@ -706,7 +707,7 @@ void
AsyncCompositionManager::RecordShadowTransforms(Layer* aLayer)
{
MOZ_ASSERT(gfxPrefs::CollectScrollTransforms());
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
ForEachNodePostOrder<ForwardIterator>(
aLayer,
@ -1439,7 +1440,7 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
void
AsyncCompositionManager::GetFrameUniformity(FrameUniformityData* aOutData)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mLayerTransformRecorder.EndTest(aOutData);
}

View File

@ -6,6 +6,7 @@
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include <stddef.h> // for size_t
#include "ClientLayerManager.h" // for ClientLayerManager
#include "base/message_loop.h" // for MessageLoop
@ -180,7 +181,7 @@ CompositorBridgeChild::OpenSameProcess(CompositorBridgeParent* aParent)
mCompositorBridgeParent = aParent;
mCanSend = Open(mCompositorBridgeParent->GetIPCChannel(),
CompositorBridgeParent::CompositorLoop(),
CompositorThreadHolder::Loop(),
ipc::ChildSide);
return mCanSend;
}

View File

@ -38,6 +38,7 @@
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/CompositorLRU.h" // for CompositorLRU
#include "mozilla/layers/CompositorOGL.h" // for CompositorOGL
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/FrameUniformityData.h"
#include "mozilla/layers/ImageBridgeParent.h"
@ -90,11 +91,6 @@
namespace mozilla {
namespace gfx {
// See VRManagerChild.cpp
void ReleaseVRManagerParentSingleton();
} // namespace gfx
namespace layers {
using namespace mozilla::ipc;
@ -155,99 +151,30 @@ CompositorBridgeParent::ForEachIndirectLayerTree(const Lambda& aCallback)
* compositor
*/
typedef map<uint64_t,CompositorBridgeParent*> CompositorMap;
static CompositorMap* sCompositorMap;
static StaticAutoPtr<CompositorMap> sCompositorMap;
static void CreateCompositorMap()
void
CompositorBridgeParent::Initialize()
{
EnsureLayerTreeMapReady();
MOZ_ASSERT(!sCompositorMap);
sCompositorMap = new CompositorMap;
}
static void DestroyCompositorMap()
void
CompositorBridgeParent::Shutdown()
{
MOZ_ASSERT(sCompositorMap);
MOZ_ASSERT(sCompositorMap->empty());
delete sCompositorMap;
sCompositorMap = nullptr;
}
// See ImageBridgeChild.cpp
void ReleaseImageBridgeParentSingleton();
CompositorThreadHolder::CompositorThreadHolder()
: mCompositorThread(CreateCompositorThread())
void
CompositorBridgeParent::FinishShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CompositorThreadHolder);
}
CompositorThreadHolder::~CompositorThreadHolder()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(CompositorThreadHolder);
DestroyCompositorThread(mCompositorThread);
}
static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder;
static bool sFinishedCompositorShutDown = false;
CompositorThreadHolder* GetCompositorThreadHolder()
{
return sCompositorThreadHolder;
}
/* static */ Thread*
CompositorThreadHolder::CreateCompositorThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
Thread* compositorThread = new Thread("Compositor");
Thread::Options options;
/* Timeout values are powers-of-two to enable us get better data.
128ms is chosen for transient hangs because 8Hz should be the minimally
acceptable goal for Compositor responsiveness (normal goal is 60Hz). */
options.transient_hang_timeout = 128; // milliseconds
/* 2048ms is chosen for permanent hangs because it's longer than most
* Compositor hangs seen in the wild, but is short enough to not miss getting
* native hang stacks. */
options.permanent_hang_timeout = 2048; // milliseconds
#if defined(_WIN32)
/* With d3d9 the compositor thread creates native ui, see DeviceManagerD3D9. As
* such the thread is a gui thread, and must process a windows message queue or
* risk deadlocks. Chromium message loop TYPE_UI does exactly what we need. */
options.message_loop_type = MessageLoop::TYPE_UI;
#endif
if (!compositorThread->StartWithOptions(options)) {
delete compositorThread;
return nullptr;
}
EnsureLayerTreeMapReady();
CreateCompositorMap();
return compositorThread;
}
/* static */ void
CompositorThreadHolder::DestroyCompositorThread(Thread* aCompositorThread)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sCompositorThreadHolder, "We shouldn't be destroying the compositor thread yet.");
DestroyCompositorMap();
delete aCompositorThread;
sFinishedCompositorShutDown = true;
}
static Thread* CompositorThread() {
return sCompositorThreadHolder ? sCompositorThreadHolder->GetCompositorThread() : nullptr;
// TODO: this should be empty by now...
sIndirectLayerTrees.clear();
}
static void SetThreadPriority()
@ -358,7 +285,7 @@ CompositorVsyncScheduler::SetDisplay(bool aDisplayEnable)
{
// SetDisplay() is usually called from nsScreenManager at main thread. Post
// to compositor thread if needs.
if (!CompositorBridgeParent::IsInCompositorThread()) {
if (!CompositorThreadHolder::IsInCompositorThread()) {
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mSetDisplayMonitor);
RefPtr<CancelableRunnable> task =
@ -385,7 +312,7 @@ CompositorVsyncScheduler::SetDisplay(bool aDisplayEnable)
void
CompositorVsyncScheduler::CancelSetDisplayTask()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MonitorAutoLock lock(mSetDisplayMonitor);
if (mSetDisplayTask) {
mSetDisplayTask->Cancel();
@ -406,7 +333,7 @@ CompositorVsyncScheduler::Destroy()
// Destroy was already called on this object.
return;
}
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
UnobserveVsync();
mVsyncObserver->Destroy();
mVsyncObserver = nullptr;
@ -437,7 +364,7 @@ CompositorVsyncScheduler::PostCompositeTask(TimeStamp aCompositeTimestamp)
void
CompositorVsyncScheduler::ScheduleComposition()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mAsapScheduling) {
// Used only for performance testing purposes
PostCompositeTask(TimeStamp::Now());
@ -459,7 +386,7 @@ CompositorVsyncScheduler::ScheduleComposition()
void
CompositorVsyncScheduler::CancelCurrentSetNeedsCompositeTask()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MonitorAutoLock lock(mSetNeedsCompositeMonitor);
if (mSetNeedsCompositeTask) {
mSetNeedsCompositeTask->Cancel();
@ -478,7 +405,7 @@ CompositorVsyncScheduler::CancelCurrentSetNeedsCompositeTask()
void
CompositorVsyncScheduler::SetNeedsComposite()
{
if (!CompositorBridgeParent::IsInCompositorThread()) {
if (!CompositorThreadHolder::IsInCompositorThread()) {
MonitorAutoLock lock(mSetNeedsCompositeMonitor);
RefPtr<CancelableRunnable> task =
NewCancelableRunnableMethod(this, &CompositorVsyncScheduler::SetNeedsComposite);
@ -509,7 +436,7 @@ bool
CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp)
{
// Called from the vsync dispatch thread
MOZ_ASSERT(!CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(!CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(!NS_IsMainThread());
PostCompositeTask(aVsyncTimestamp);
return true;
@ -518,7 +445,7 @@ CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp)
void
CompositorVsyncScheduler::CancelCurrentCompositeTask()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread() || NS_IsMainThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || NS_IsMainThread());
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
if (mCurrentCompositeTask) {
mCurrentCompositeTask->Cancel();
@ -529,7 +456,7 @@ CompositorVsyncScheduler::CancelCurrentCompositeTask()
void
CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
{
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
mCurrentCompositeTask = nullptr;
@ -572,14 +499,14 @@ CompositorVsyncScheduler::OnForceComposeToTarget()
* free and this oscillating behavior causes a performance hit. In order to avoid this problem,
* we reset the mVsyncNotificationsSkipped counter to keep vsync enabled.
*/
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mVsyncNotificationsSkipped = 0;
}
void
CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
OnForceComposeToTarget();
mLastCompose = TimeStamp::Now();
ComposeToTarget(aTarget, aRect);
@ -588,14 +515,14 @@ CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const I
bool
CompositorVsyncScheduler::NeedsComposite()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
return mNeedsComposite;
}
void
CompositorVsyncScheduler::ObserveVsync()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mCompositorVsyncDispatcher->SetCompositorVsyncObserver(mVsyncObserver);
mIsObservingVsync = true;
}
@ -603,7 +530,7 @@ CompositorVsyncScheduler::ObserveVsync()
void
CompositorVsyncScheduler::UnobserveVsync()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mCompositorVsyncDispatcher->SetCompositorVsyncObserver(nullptr);
mIsObservingVsync = false;
}
@ -619,59 +546,25 @@ CompositorVsyncScheduler::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
void
CompositorVsyncScheduler::DispatchVREvents(TimeStamp aVsyncTimestamp)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
VRManager* vm = VRManager::Get();
vm->NotifyVsync(aVsyncTimestamp);
}
void CompositorBridgeParent::StartUp()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
sCompositorThreadHolder = new CompositorThreadHolder();
}
void CompositorBridgeParent::ShutDown()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(sCompositorThreadHolder, "The compositor thread has already been shut down!");
ReleaseImageBridgeParentSingleton();
ReleaseVRManagerParentSingleton();
MediaSystemResourceService::Shutdown();
sCompositorThreadHolder = nullptr;
// No locking is needed around sFinishedCompositorShutDown because it is only
// ever accessed on the main thread.
while (!sFinishedCompositorShutDown) {
NS_ProcessNextEvent(nullptr, true);
}
// TODO: this should be empty by now...
sIndirectLayerTrees.clear();
}
MessageLoop* CompositorBridgeParent::CompositorLoop()
{
return CompositorThread() ? CompositorThread()->message_loop() : nullptr;
}
void
CompositorVsyncScheduler::ScheduleTask(already_AddRefed<CancelableRunnable> aTask,
int aTime)
{
MOZ_ASSERT(CompositorBridgeParent::CompositorLoop());
MOZ_ASSERT(CompositorThreadHolder::Loop());
MOZ_ASSERT(aTime >= 0);
CompositorBridgeParent::CompositorLoop()->PostDelayedTask(Move(aTask), aTime);
CompositorThreadHolder::Loop()->PostDelayedTask(Move(aTask), aTime);
}
void
CompositorVsyncScheduler::ResumeComposition()
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mLastCompose = TimeStamp::Now();
ComposeToTarget(nullptr);
}
@ -679,11 +572,17 @@ CompositorVsyncScheduler::ResumeComposition()
void
CompositorVsyncScheduler::ComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
{
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(mCompositorBridgeParent);
mCompositorBridgeParent->CompositeToTarget(aTarget, aRect);
}
static inline MessageLoop*
CompositorLoop()
{
return CompositorThreadHolder::Loop();
}
CompositorBridgeParent::CompositorBridgeParent(widget::CompositorWidgetProxy* aWidget,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
@ -701,7 +600,7 @@ CompositorBridgeParent::CompositorBridgeParent(widget::CompositorWidgetProxy* aW
, mRootLayerTreeID(AllocateLayerTreeId())
, mOverrideComposeReadiness(false)
, mForceCompositionTask(nullptr)
, mCompositorThreadHolder(sCompositorThreadHolder)
, mCompositorThreadHolder(CompositorThreadHolder::GetSingleton())
, mCompositorScheduler(nullptr)
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
, mLastPluginUpdateLayerTreeId(0)
@ -744,12 +643,6 @@ CompositorBridgeParent::CompositorBridgeParent(widget::CompositorWidgetProxy* aW
mSelfRef = this;
}
bool
CompositorBridgeParent::IsInCompositorThread()
{
return CompositorThread() && CompositorThread()->thread_id() == PlatformThread::CurrentId();
}
uint64_t
CompositorBridgeParent::RootLayerTreeId()
{
@ -1015,7 +908,7 @@ CompositorBridgeParent::InvalidateOnCompositorThread()
void
CompositorBridgeParent::PauseComposition()
{
MOZ_ASSERT(IsInCompositorThread(),
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
"PauseComposition() can only be called on the compositor thread");
MonitorAutoLock lock(mPauseCompositionMonitor);
@ -1036,7 +929,7 @@ CompositorBridgeParent::PauseComposition()
void
CompositorBridgeParent::ResumeComposition()
{
MOZ_ASSERT(IsInCompositorThread(),
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
"ResumeComposition() can only be called on the compositor thread");
MonitorAutoLock lock(mResumeCompositionMonitor);
@ -1170,7 +1063,7 @@ CompositorBridgeParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstP
void
CompositorBridgeParent::ScheduleComposition()
{
MOZ_ASSERT(IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mPaused) {
return;
}
@ -1213,7 +1106,7 @@ CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRec
PROFILER_LABEL("CompositorBridgeParent", "Composite",
js::ProfileEntry::Category::GRAPHICS);
MOZ_ASSERT(IsInCompositorThread(),
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
"Composite can only be called on the compositor thread");
TimeStamp start = TimeStamp::Now();
@ -1373,7 +1266,7 @@ void
CompositorBridgeParent::ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
bool aIsFirstPaint)
{
MOZ_ASSERT(IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (!aIsFirstPaint &&
!mCompositionManager->IsFirstPaint() &&
@ -1872,7 +1765,7 @@ static void
InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
VsyncPayload* payload = new VsyncPayload(aVsyncTimestamp);
PROFILER_MARKER_PAYLOAD("VsyncTimestamp", payload);
#endif
@ -1882,7 +1775,7 @@ InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
CompositorBridgeParent::PostInsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
{
// Called in the vsync thread
if (profiler_is_active() && sCompositorThreadHolder) {
if (profiler_is_active() && CompositorThreadHolder::IsActive()) {
CompositorLoop()->PostTask(
NewRunnableFunction(InsertVsyncProfilerMarker, aVsyncTimestamp));
}
@ -2072,7 +1965,9 @@ public:
virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
protected:
void OnChannelConnected(int32_t pid) override { mCompositorThreadHolder = sCompositorThreadHolder; }
void OnChannelConnected(int32_t pid) override {
mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();
}
private:
// Private destructor, to discourage deletion outside of Release():
virtual ~CrossProcessCompositorBridgeParent();

View File

@ -17,9 +17,6 @@
#include <stdint.h> // for uint64_t
#include "Layers.h" // for Layer
#include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS
#include "base/platform_thread.h" // for PlatformThreadId
#include "base/thread.h" // for Thread
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/Attributes.h" // for override
#include "mozilla/Maybe.h"
@ -68,6 +65,7 @@ class LayerManagerComposite;
class LayerTransactionParent;
class PAPZParent;
class CrossProcessCompositorBridgeParent;
class CompositorThreadHolder;
struct ScopedLayerTreeRegistration
{
@ -81,28 +79,6 @@ private:
uint64_t mLayersId;
};
class CompositorThreadHolder final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder)
public:
CompositorThreadHolder();
base::Thread* GetCompositorThread() const {
return mCompositorThread;
}
private:
~CompositorThreadHolder();
base::Thread* const mCompositorThread;
static base::Thread* CreateCompositorThread();
static void DestroyCompositorThread(base::Thread* aCompositorThread);
friend class CompositorBridgeParent;
};
/**
* Manages the vsync (de)registration and tracking on behalf of the
* compositor when it need to paint.
@ -231,6 +207,7 @@ class CompositorBridgeParent final : public PCompositorBridgeParent,
public ShmemAllocator
{
friend class CompositorVsyncScheduler;
friend class CompositorThreadHolder;
public:
explicit CompositorBridgeParent(widget::CompositorWidgetProxy* aWidget,
@ -395,27 +372,6 @@ public:
*/
static CompositorBridgeParent* GetCompositor(uint64_t id);
/**
* Returns the compositor thread's message loop.
*
* This message loop is used by CompositorBridgeParent, ImageBridgeParent,
* and VRManagerParent
*/
static MessageLoop* CompositorLoop();
/**
* Creates the compositor thread and the global compositor map.
*/
static void StartUp();
/**
* Waits for all [CrossProcess]CompositorBridgeParent's to be gone,
* and destroys the compositor thread and global compositor map.
*
* Does not return until all of that has completed.
*/
static void ShutDown();
/**
* Allocate an ID that can be used to refer to a layer tree and
* associated resources that live only on the compositor thread.
@ -519,11 +475,6 @@ public:
float ComputeRenderIntegrity();
/**
* Returns true if the calling thread is the compositor thread.
*/
static bool IsInCompositorThread();
widget::CompositorWidgetProxy* GetWidgetProxy() { return mWidgetProxy; }
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
@ -584,6 +535,21 @@ protected:
*/
static CompositorBridgeParent* RemoveCompositor(uint64_t id);
/**
* Creates the global compositor map.
*/
static void Initialize();
/**
* Destroys the compositor thread and global compositor map.
*/
static void Shutdown();
/**
* Finish the shutdown operation on the compositor thread.
*/
static void FinishShutdown();
/**
* Return true if current state allows compositing, that is
* finishing a layers transaction.

View File

@ -0,0 +1,153 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 sts=2 ts=8 et tw=99 : */
/* 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 "CompositorThread.h"
#include "MainThreadUtils.h"
#include "nsThreadUtils.h"
#include "CompositorBridgeParent.h"
#include "mozilla/media/MediaSystemResourceService.h"
namespace mozilla {
namespace gfx {
// See VRManagerChild.cpp
void ReleaseVRManagerParentSingleton();
} // namespace gfx
namespace layers {
static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder;
static bool sFinishedCompositorShutDown = false;
// See ImageBridgeChild.cpp
void ReleaseImageBridgeParentSingleton();
CompositorThreadHolder* GetCompositorThreadHolder()
{
return sCompositorThreadHolder;
}
base::Thread*
CompositorThread()
{
return sCompositorThreadHolder
? sCompositorThreadHolder->GetCompositorThread()
: nullptr;
}
/* static */ MessageLoop*
CompositorThreadHolder::Loop()
{
return CompositorThread() ? CompositorThread()->message_loop() : nullptr;
}
CompositorThreadHolder*
CompositorThreadHolder::GetSingleton()
{
return sCompositorThreadHolder;
}
CompositorThreadHolder::CompositorThreadHolder()
: mCompositorThread(CreateCompositorThread())
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CompositorThreadHolder);
}
CompositorThreadHolder::~CompositorThreadHolder()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(CompositorThreadHolder);
DestroyCompositorThread(mCompositorThread);
}
/* static */ void
CompositorThreadHolder::DestroyCompositorThread(base::Thread* aCompositorThread)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sCompositorThreadHolder, "We shouldn't be destroying the compositor thread yet.");
CompositorBridgeParent::Shutdown();
delete aCompositorThread;
sFinishedCompositorShutDown = true;
}
/* static */ base::Thread*
CompositorThreadHolder::CreateCompositorThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
base::Thread* compositorThread = new base::Thread("Compositor");
base::Thread::Options options;
/* Timeout values are powers-of-two to enable us get better data.
128ms is chosen for transient hangs because 8Hz should be the minimally
acceptable goal for Compositor responsiveness (normal goal is 60Hz). */
options.transient_hang_timeout = 128; // milliseconds
/* 2048ms is chosen for permanent hangs because it's longer than most
* Compositor hangs seen in the wild, but is short enough to not miss getting
* native hang stacks. */
options.permanent_hang_timeout = 2048; // milliseconds
#if defined(_WIN32)
/* With d3d9 the compositor thread creates native ui, see DeviceManagerD3D9. As
* such the thread is a gui thread, and must process a windows message queue or
* risk deadlocks. Chromium message loop TYPE_UI does exactly what we need. */
options.message_loop_type = MessageLoop::TYPE_UI;
#endif
if (!compositorThread->StartWithOptions(options)) {
delete compositorThread;
return nullptr;
}
CompositorBridgeParent::Initialize();
return compositorThread;
}
void
CompositorThreadHolder::Start()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
sCompositorThreadHolder = new CompositorThreadHolder();
}
void
CompositorThreadHolder::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(sCompositorThreadHolder, "The compositor thread has already been shut down!");
ReleaseImageBridgeParentSingleton();
gfx::ReleaseVRManagerParentSingleton();
MediaSystemResourceService::Shutdown();
sCompositorThreadHolder = nullptr;
// No locking is needed around sFinishedCompositorShutDown because it is only
// ever accessed on the main thread.
while (!sFinishedCompositorShutDown) {
NS_ProcessNextEvent(nullptr, true);
}
CompositorBridgeParent::FinishShutdown();
}
/* static */ bool
CompositorThreadHolder::IsInCompositorThread()
{
return CompositorThread() &&
CompositorThread()->thread_id() == PlatformThread::CurrentId();
}
} // namespace mozilla
} // namespace layers

View File

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 sts=2 ts=8 et tw=99 : */
/* 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_layers_CompositorThread_h
#define mozilla_layers_CompositorThread_h
#include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS
#include "base/platform_thread.h" // for PlatformThreadId
#include "base/thread.h" // for Thread
#include "base/message_loop.h"
#include "nsISupportsImpl.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
namespace mozilla {
namespace layers {
class CompositorThreadHolder final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder)
public:
CompositorThreadHolder();
base::Thread* GetCompositorThread() const {
return mCompositorThread;
}
static CompositorThreadHolder* GetSingleton();
static bool IsActive() {
return !!GetSingleton();
}
/**
* Creates the compositor thread and the global compositor map.
*/
static void Start();
/*
* Waits for all [CrossProcess]CompositorBridgeParents to shutdown and
* releases compositor-thread owned resources.
*/
static void Shutdown();
static MessageLoop* Loop();
// Returns true if the calling thread is the compositor thread.
static bool IsInCompositorThread();
private:
~CompositorThreadHolder();
base::Thread* const mCompositorThread;
static base::Thread* CreateCompositorThread();
static void DestroyCompositorThread(base::Thread* aCompositorThread);
friend class CompositorBridgeParent;
};
base::Thread* CompositorThread();
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_CompositorThread_h

View File

@ -24,7 +24,7 @@
#include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
#include "mozilla/media/MediaSystemResourceManagerChild.h" // for MediaSystemResourceManagerChild
#include "mozilla/layers/CompositableClient.h" // for CompositableChild, etc
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
#include "mozilla/layers/ImageClient.h" // for ImageClient
#include "mozilla/layers/LayersMessages.h" // for CompositableOperation
@ -844,7 +844,7 @@ bool ImageBridgeChild::StartUpOnThread(Thread* aThread)
}
sImageBridgeChildSingleton = new ImageBridgeChild();
sImageBridgeParentSingleton = new ImageBridgeParent(
CompositorBridgeParent::CompositorLoop(), nullptr, base::GetCurrentProcId());
CompositorThreadHolder::Loop(), nullptr, base::GetCurrentProcId());
sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
NewRunnableFunction(CallSendImageBridgeThreadId,

View File

@ -20,6 +20,7 @@
#include "mozilla/media/MediaSystemResourceManagerParent.h" // for MediaSystemResourceManagerParent
#include "mozilla/layers/CompositableTransactionParent.h"
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/LayersMessages.h" // for EditReply
#include "mozilla/layers/LayersSurfaces.h" // for PGrallocBufferParent
@ -200,7 +201,7 @@ ConnectImageBridgeInParentProcess(ImageBridgeParent* aBridge,
/*static*/ PImageBridgeParent*
ImageBridgeParent::Create(Transport* aTransport, ProcessId aChildProcessId, GeckoChildProcessHost* aProcessHost)
{
MessageLoop* loop = CompositorBridgeParent::CompositorLoop();
MessageLoop* loop = CompositorThreadHolder::Loop();
RefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport, aChildProcessId);
if (aProcessHost) {

View File

@ -158,6 +158,7 @@ EXPORTS.mozilla.layers += [
'ipc/CompositorBridgeChild.h',
'ipc/CompositorBridgeParent.h',
'ipc/CompositorLRU.h',
'ipc/CompositorThread.h',
'ipc/FenceUtils.h',
'ipc/GonkNativeHandle.h',
'ipc/GonkNativeHandleUtils.h',
@ -343,6 +344,7 @@ UNIFIED_SOURCES += [
'ipc/CompositorBridgeChild.cpp',
'ipc/CompositorBridgeParent.cpp',
'ipc/CompositorLRU.cpp',
'ipc/CompositorThread.cpp',
'ipc/FenceUtils.cpp',
'ipc/ImageBridgeChild.cpp',
'ipc/ImageBridgeParent.cpp',

View File

@ -1247,23 +1247,12 @@ CompositorOGL::DrawQuad(const Rect& aRect,
didSetBlendMode = SetBlendMode(gl(), blendMode, texturedEffect->mPremultiplied);
gfx::Filter filter = texturedEffect->mFilter;
Matrix4x4 textureTransform = source->AsSourceOGL()->GetTextureTransform();
#ifdef MOZ_WIDGET_ANDROID
gfx::Matrix textureTransform2D;
if (filter != gfx::Filter::POINT &&
aTransform.Is2DIntegerTranslation() &&
textureTransform.Is2D(&textureTransform2D) &&
textureTransform2D.HasOnlyIntegerTranslation()) {
// On Android we encounter small resampling errors in what should be
// pixel-aligned compositing operations. This works around them. This
// code should not be needed!
filter = gfx::Filter::POINT;
}
#endif
source->AsSourceOGL()->BindTexture(LOCAL_GL_TEXTURE0, filter);
program->SetTextureUnit(0);
Matrix4x4 textureTransform = source->AsSourceOGL()->GetTextureTransform();
program->SetTextureTransform(textureTransform);
if (maskType != MaskType::MaskNone) {

View File

@ -5,7 +5,7 @@
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/SharedBufferManagerChild.h"
#include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
@ -868,7 +868,7 @@ gfxPlatform::InitLayersIPC()
if (XRE_IsParentProcess())
{
mozilla::layers::CompositorBridgeParent::StartUp();
layers::CompositorThreadHolder::Start();
#ifdef MOZ_WIDGET_GONK
SharedBufferManagerChild::StartUp();
#endif
@ -905,7 +905,7 @@ gfxPlatform::ShutdownLayersIPC()
#endif
// This has to happen after shutting down the child protocols.
layers::CompositorBridgeParent::ShutDown();
layers::CompositorThreadHolder::Shutdown();
} else {
// TODO: There are other kind of processes and we should make sure gfx
// stuff is either not created there or shut down properly.

View File

@ -136,7 +136,8 @@ enum class DeviceResetReason
enum class ForcedDeviceResetReason
{
OPENSHAREDHANDLE = 0
OPENSHAREDHANDLE = 0,
COMPOSITOR_UPDATED,
};
class gfxPlatform {
@ -633,6 +634,8 @@ public:
return mCompositorBackend;
}
virtual void CompositorUpdated() {}
// Return information on how child processes should initialize graphics
// devices. Currently this is only used on Windows.
virtual void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut);

View File

@ -1331,18 +1331,20 @@ gfxUserFontSet::UserFontCache::Entry::ReportMemory(nsIMemoryReporterCallback* aC
if (mPrincipal) {
nsCOMPtr<nsIURI> uri;
mPrincipal->GetURI(getter_AddRefs(uri));
if (uri) {
nsCString spec;
uri->GetSpec(spec);
if (!spec.IsEmpty()) {
// Include a clue as to who loaded this resource. (Note that
// because of font entry sharing, other pages may now be using
// this resource, and the original page may not even be loaded
// any longer.)
// Include a clue as to who loaded this resource. (Note
// that because of font entry sharing, other pages may now
// be using this resource, and the original page may not
// even be loaded any longer.)
spec.ReplaceChar('/', '\\');
path.AppendPrintf(", principal=%s", spec.get());
}
}
}
}
path.Append(')');
return aCb->

View File

@ -37,7 +37,7 @@
#include "gfxGDIFontList.h"
#include "gfxGDIFont.h"
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent::IsInCompositorThread
#include "mozilla/layers/CompositorThread.h"
#include "DeviceManagerD3D9.h"
#include "mozilla/layers/ReadbackManagerD3D11.h"
@ -67,10 +67,10 @@
#include <winternl.h>
#include "d3dkmtQueryStatistics.h"
#include "base/thread.h"
#include "SurfaceCache.h"
#include "gfxPrefs.h"
#include "gfxConfig.h"
#include "VsyncSource.h"
#include "DriverCrashGuard.h"
#include "mozilla/dom/ContentParent.h"
@ -947,6 +947,13 @@ static DeviceResetReason HResultToResetReason(HRESULT hr)
return DeviceResetReason::UNKNOWN;
}
void
gfxWindowsPlatform::CompositorUpdated()
{
ForceDeviceReset(ForcedDeviceResetReason::COMPOSITOR_UPDATED);
UpdateRenderMode();
}
bool
gfxWindowsPlatform::IsDeviceReset(HRESULT hr, DeviceResetReason* aResetReason)
{
@ -1410,7 +1417,7 @@ gfxWindowsPlatform::GetD3D9DeviceManager()
RefPtr<DeviceManagerD3D9> result;
if (!mDeviceManager &&
(!gfxPlatform::UsesOffMainThreadCompositing() ||
CompositorBridgeParent::IsInCompositorThread())) {
CompositorThreadHolder::IsInCompositorThread())) {
mDeviceManager = new DeviceManagerD3D9();
if (!mDeviceManager->Init()) {
gfxCriticalError() << "[D3D9] Could not Initialize the DeviceManagerD3D9";

View File

@ -178,6 +178,8 @@ public:
*/
virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) override;
virtual void CompositorUpdated() override;
bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;
void SchedulePaintIfDeviceReset() override;
void UpdateRenderModeIfDeviceReset() override;

View File

@ -10,7 +10,7 @@
#include "VRDeviceProxy.h"
#include "VRDeviceProxyOrientationFallBack.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent
#include "mozilla/layers/CompositorThread.h" // for CompositorThread
#include "mozilla/dom/Navigator.h"
namespace mozilla {
@ -77,7 +77,7 @@ VRManagerChild::StartUpSameProcess()
sVRManagerChildSingleton = new VRManagerChild();
sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
mozilla::layers::CompositorBridgeParent::CompositorLoop(),
mozilla::layers::CompositorThreadHolder::Loop(),
mozilla::ipc::ChildSide);
}
}

View File

@ -10,18 +10,11 @@
#include "mozilla/ipc/ProtocolTypes.h"
#include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/unused.h"
#include "VRManager.h"
namespace mozilla {
namespace layers {
// defined in CompositorBridgeParent.cpp
CompositorThreadHolder* GetCompositorThreadHolder();
} // namespace layers
namespace gfx {
VRManagerParent::VRManagerParent(MessageLoop* aLoop,
@ -76,7 +69,7 @@ VRManagerParent::ConnectVRManagerInParentProcess(VRManagerParent* aVRManager,
/*static*/ VRManagerParent*
VRManagerParent::CreateCrossProcess(Transport* aTransport, ProcessId aChildProcessId)
{
MessageLoop* loop = mozilla::layers::CompositorBridgeParent::CompositorLoop();
MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop();
RefPtr<VRManagerParent> vmp = new VRManagerParent(loop, aTransport, aChildProcessId);
vmp->mSelfRef = vmp;
loop->PostTask(NewRunnableFunction(ConnectVRManagerInParentProcess,
@ -93,9 +86,9 @@ VRManagerParent::RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager
/*static*/ VRManagerParent*
VRManagerParent::CreateSameProcess()
{
MessageLoop* loop = mozilla::layers::CompositorBridgeParent::CompositorLoop();
MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop();
RefPtr<VRManagerParent> vmp = new VRManagerParent(loop, nullptr, base::GetCurrentProcId());
vmp->mCompositorThreadHolder = layers::GetCompositorThreadHolder();
vmp->mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton();
vmp->mSelfRef = vmp;
loop->PostTask(NewRunnableFunction(RegisterVRManagerInCompositorThread, vmp.get()));
return vmp.get();
@ -139,7 +132,7 @@ VRManagerParent::CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMa
void
VRManagerParent::OnChannelConnected(int32_t aPid)
{
mCompositorThreadHolder = layers::GetCompositorThreadHolder();
mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton();
}
bool

View File

@ -8,7 +8,7 @@
#ifndef MOZILLA_GFX_VR_VRMANAGERPARENT_H
#define MOZILLA_GFX_VR_VRMANAGERPARENT_H
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorThreadHolder
#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder
#include "mozilla/gfx/PVRManagerParent.h" // for PVRManagerParent
#include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol
#include "mozilla/TimeStamp.h" // for TimeStamp

View File

@ -586,7 +586,8 @@ class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
/**
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
* JS::TraceKind::Shape. |thing| should be non-null.
* JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
* if anything was unmarked.
*/
extern JS_FRIEND_API(bool)
UnmarkGrayGCThingRecursively(GCCellPtr thing);

View File

@ -71,16 +71,34 @@ class JS_PUBLIC_API(JSTracer)
bool isTenuringTracer() const { return tag_ == TracerKindTag::Tenuring; }
bool isCallbackTracer() const { return tag_ == TracerKindTag::Callback; }
inline JS::CallbackTracer* asCallbackTracer();
#ifdef DEBUG
bool checkEdges() { return checkEdges_; }
#endif
protected:
JSTracer(JSRuntime* rt, TracerKindTag tag,
WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
: runtime_(rt), weakMapAction_(weakTraceKind), tag_(tag)
: runtime_(rt)
, weakMapAction_(weakTraceKind)
#ifdef DEBUG
, checkEdges_(true)
#endif
, tag_(tag)
{}
#ifdef DEBUG
// Set whether to check edges are valid in debug builds.
void setCheckEdges(bool check) {
checkEdges_ = check;
}
#endif
private:
JSRuntime* runtime_;
WeakMapTraceKind weakMapAction_;
#ifdef DEBUG
bool checkEdges_;
#endif
protected:
TracerKindTag tag_;

View File

@ -85,7 +85,12 @@ class MOZ_RAII AutoStopVerifyingBarriers
AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown)
: gc(&rt->gc)
{
restartPreVerifier = gc->endVerifyPreBarriers() && !isShutdown;
if (gc->isVerifyPreBarriersEnabled()) {
gc->endVerifyPreBarriers();
restartPreVerifier = !isShutdown;
} else {
restartPreVerifier = false;
}
}
~AutoStopVerifyingBarriers() {
@ -115,8 +120,8 @@ struct MOZ_RAII AutoStopVerifyingBarriers
#endif /* JS_GC_ZEAL */
#ifdef JSGC_HASH_TABLE_CHECKS
void
CheckHashTablesAfterMovingGC(JSRuntime* rt);
void CheckHashTablesAfterMovingGC(JSRuntime* rt);
void CheckHeapAfterMovingGC(JSRuntime* rt);
#endif
struct MovingTracer : JS::CallbackTracer

View File

@ -194,7 +194,7 @@ class GCSchedulingTunables
unsigned minEmptyChunkCount(const AutoLockGC&) const { return minEmptyChunkCount_; }
unsigned maxEmptyChunkCount() const { return maxEmptyChunkCount_; }
bool setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
};
/*
@ -584,7 +584,7 @@ class GCRuntime
{
public:
explicit GCRuntime(JSRuntime* rt);
bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
MOZ_MUST_USE bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
void finishRoots();
void finish();
@ -593,17 +593,18 @@ class GCRuntime
inline bool upcomingZealousGC();
inline bool needZealousGC();
bool addRoot(Value* vp, const char* name);
MOZ_MUST_USE bool addRoot(Value* vp, const char* name);
void removeRoot(Value* vp);
void setMarkStackLimit(size_t limit, AutoLockGC& lock);
bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock);
bool triggerGC(JS::gcreason::Reason reason);
MOZ_MUST_USE bool triggerGC(JS::gcreason::Reason reason);
void maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock);
// The return value indicates if we were able to do the GC.
bool triggerZoneGC(Zone* zone, JS::gcreason::Reason reason);
bool maybeGC(Zone* zone);
MOZ_MUST_USE bool maybeGC(Zone* zone);
void maybePeriodicFullGC();
void minorGC(JS::gcreason::Reason reason) {
gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
@ -614,6 +615,7 @@ class GCRuntime
gcstats::AutoPhase ap(stats, gcstats::PHASE_EVICT_NURSERY);
minorGCImpl(reason, nullptr);
}
// The return value indicates whether a major GC was performed.
bool gcIfRequested(JSContext* cx = nullptr);
void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
void startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0);
@ -626,7 +628,7 @@ class GCRuntime
void triggerFullGCForAtoms() {
MOZ_ASSERT(fullGCForAtomsRequested_);
fullGCForAtomsRequested_ = false;
triggerGC(JS::gcreason::ALLOC_TRIGGER);
MOZ_RELEASE_ASSERT(triggerGC(JS::gcreason::ALLOC_TRIGGER));
}
void runDebugGC();
@ -755,7 +757,7 @@ class GCRuntime
bool isCompactingGCEnabled() const;
void setGrayRootsTracer(JSTraceDataOp traceOp, void* data);
bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
MOZ_MUST_USE bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
void removeBlackRootsTracer(JSTraceDataOp traceOp, void* data);
void setMaxMallocBytes(size_t value);
@ -770,11 +772,13 @@ class GCRuntime
void setObjectsTenuredCallback(JSObjectsTenuredCallback callback,
void* data);
void callObjectsTenuredCallback();
bool addFinalizeCallback(JSFinalizeCallback callback, void* data);
MOZ_MUST_USE bool addFinalizeCallback(JSFinalizeCallback callback, void* data);
void removeFinalizeCallback(JSFinalizeCallback func);
bool addWeakPointerZoneGroupCallback(JSWeakPointerZoneGroupCallback callback, void* data);
MOZ_MUST_USE bool addWeakPointerZoneGroupCallback(JSWeakPointerZoneGroupCallback callback,
void* data);
void removeWeakPointerZoneGroupCallback(JSWeakPointerZoneGroupCallback callback);
bool addWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback callback, void* data);
MOZ_MUST_USE bool addWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback callback,
void* data);
void removeWeakPointerCompartmentCallback(JSWeakPointerCompartmentCallback callback);
JS::GCSliceCallback setSliceCallback(JS::GCSliceCallback callback);
JS::GCNurseryCollectionCallback setNurseryCollectionCallback(
@ -841,7 +845,7 @@ class GCRuntime
#ifdef JS_GC_ZEAL
void startVerifyPreBarriers();
bool endVerifyPreBarriers();
void endVerifyPreBarriers();
void finishVerifier();
bool isVerifyPreBarriersEnabled() const { return !!verifyPreData; }
#else
@ -860,7 +864,7 @@ class GCRuntime
// Allocator
template <AllowGC allowGC>
bool checkAllocatorState(JSContext* cx, AllocKind kind);
MOZ_MUST_USE bool checkAllocatorState(JSContext* cx, AllocKind kind);
template <AllowGC allowGC>
JSObject* tryNewNurseryObject(JSContext* cx, size_t thingSize, size_t nDynamicSlots,
const Class* clasp);
@ -888,7 +892,7 @@ class GCRuntime
void arenaAllocatedDuringGC(JS::Zone* zone, Arena* arena);
// Allocator internals
bool gcIfNeededPerAllocation(JSContext* cx);
MOZ_MUST_USE bool gcIfNeededPerAllocation(JSContext* cx);
template <typename T>
static void checkIncrementalZoneState(ExclusiveContext* cx, T* t);
static void* refillFreeListFromAnyThread(ExclusiveContext* cx, AllocKind thingKind,
@ -921,16 +925,17 @@ class GCRuntime
// Check if the system state is such that GC has been supressed
// or otherwise delayed.
bool checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason);
MOZ_MUST_USE bool checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason);
gcstats::ZoneGCStats scanZonesBeforeGC();
void collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::Reason reason) JS_HAZ_GC_CALL;
bool gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::Reason reason);
MOZ_MUST_USE bool gcCycle(bool nonincrementalByAPI, SliceBudget& budget,
JS::gcreason::Reason reason);
void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason);
void pushZealSelectedObjects();
void purgeRuntime();
bool beginMarkPhase(JS::gcreason::Reason reason);
MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason);
bool shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime,
JS::gcreason::Reason reason);
void bufferGrayRoots();
@ -946,7 +951,7 @@ class GCRuntime
void beginSweepPhase(bool lastGC);
void findZoneGroups();
bool findZoneEdgesForWeakMaps();
MOZ_MUST_USE bool findZoneEdgesForWeakMaps();
void getNextZoneGroup();
void endMarkingZoneGroup();
void beginSweepingZoneGroup();
@ -967,8 +972,8 @@ class GCRuntime
void endCompactPhase(JS::gcreason::Reason reason);
void sweepTypesAfterCompacting(Zone* zone);
void sweepZoneAfterCompacting(Zone* zone);
bool relocateArenas(Zone* zone, JS::gcreason::Reason reason, Arena*& relocatedListOut,
SliceBudget& sliceBudget);
MOZ_MUST_USE bool relocateArenas(Zone* zone, JS::gcreason::Reason reason,
Arena*& relocatedListOut, SliceBudget& sliceBudget);
void updateTypeDescrObjects(MovingTracer* trc, Zone* zone);
void updateCellPointers(MovingTracer* trc, Zone* zone, AllocKinds kinds, size_t bgTaskCount);
void updateAllCellPointers(MovingTracer* trc, Zone* zone);
@ -1047,6 +1052,8 @@ class GCRuntime
*/
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> numArenasFreeCommitted;
VerifyPreTracer* verifyPreData;
private:
bool chunkAllocationSinceLastGC;
int64_t nextFullGCTime;
int64_t lastGCTime;

View File

@ -17,7 +17,7 @@ namespace gc {
#ifdef JS_GC_TRACE
extern bool InitTrace(GCRuntime& gc);
extern MOZ_MUST_USE bool InitTrace(GCRuntime& gc);
extern void FinishTrace();
extern bool TraceEnabled();
extern void TraceNurseryAlloc(Cell* thing, size_t size);
@ -33,7 +33,7 @@ extern void TraceTypeNewScript(js::ObjectGroup* group);
#else
inline bool InitTrace(GCRuntime& gc) { return true; }
inline MOZ_MUST_USE bool InitTrace(GCRuntime& gc) { return true; }
inline void FinishTrace() {}
inline bool TraceEnabled() { return false; }
inline void TraceNurseryAlloc(Cell* thing, size_t size) {}

View File

@ -53,6 +53,7 @@ extern bool
CurrentThreadIsIonCompiling();
#endif
// The return value indicates if anything was unmarked.
extern bool
UnmarkGrayCellRecursively(gc::Cell* cell, JS::TraceKind kind);
@ -295,6 +296,7 @@ class TenuredCell : public Cell
// Mark bit management.
MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const;
// The return value indicates if the cell went from unmarked to marked.
MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const;
MOZ_ALWAYS_INLINE void unmark(uint32_t color) const;
MOZ_ALWAYS_INLINE void copyMarkBitsFrom(const TenuredCell* src);
@ -877,6 +879,7 @@ struct ChunkBitmap
return *word & mask;
}
// The return value indicates if the cell went from unmarked to marked.
MOZ_ALWAYS_INLINE bool markIfUnmarked(const Cell* cell, uint32_t color) {
uintptr_t* word, mask;
getMarkWordAndMask(cell, BLACK, &word, &mask);
@ -995,7 +998,7 @@ struct Chunk
void releaseArena(JSRuntime* rt, Arena* arena, const AutoLockGC& lock);
void recycleArena(Arena* arena, SortedArenaList& dest, size_t thingsPerArena);
bool decommitOneFreeArena(JSRuntime* rt, AutoLockGC& lock);
MOZ_MUST_USE bool decommitOneFreeArena(JSRuntime* rt, AutoLockGC& lock);
void decommitAllArenasWithoutUnlocking(const AutoLockGC& lock);
static Chunk* allocate(JSRuntime* rt);

View File

@ -181,6 +181,9 @@ js::CheckTracedThing(JSTracer* trc, T* thing)
MOZ_ASSERT(trc);
MOZ_ASSERT(thing);
if (!trc->checkEdges())
return;
thing = MaybeForwarded(thing);
/* This function uses data that's not available in the nursery. */

View File

@ -87,13 +87,13 @@ class MarkStack
end_ = stack + capacity;
}
bool init(JSGCMode gcMode);
MOZ_MUST_USE bool init(JSGCMode gcMode);
void setBaseCapacity(JSGCMode mode);
size_t maxCapacity() const { return maxCapacity_; }
void setMaxCapacity(size_t maxCapacity);
bool push(uintptr_t item) {
MOZ_MUST_USE bool push(uintptr_t item) {
if (tos_ == end_) {
if (!enlarge(1))
return false;
@ -103,7 +103,7 @@ class MarkStack
return true;
}
bool push(uintptr_t item1, uintptr_t item2, uintptr_t item3) {
MOZ_MUST_USE bool push(uintptr_t item1, uintptr_t item2, uintptr_t item3) {
uintptr_t* nextTos = tos_ + 3;
if (nextTos > end_) {
if (!enlarge(3))
@ -130,7 +130,7 @@ class MarkStack
void reset();
/* Grow the stack, ensuring there is space for at least count elements. */
bool enlarge(unsigned count);
MOZ_MUST_USE bool enlarge(unsigned count);
void setGCMode(JSGCMode gcMode);
@ -168,7 +168,7 @@ class GCMarker : public JSTracer
{
public:
explicit GCMarker(JSRuntime* rt);
bool init(JSGCMode gcMode);
MOZ_MUST_USE bool init(JSGCMode gcMode);
void setMaxCapacity(size_t maxCap) { stack.setMaxCapacity(maxCap); }
size_t maxCapacity() const { return stack.maxCapacity(); }
@ -216,7 +216,7 @@ class GCMarker : public JSTracer
void delayMarkingArena(gc::Arena* arena);
void delayMarkingChildren(const void* thing);
void markDelayedChildren(gc::Arena* arena);
bool markDelayedChildren(SliceBudget& budget);
MOZ_MUST_USE bool markDelayedChildren(SliceBudget& budget);
bool hasDelayedChildren() const {
return !!unmarkedArenaStackTop;
}
@ -225,7 +225,7 @@ class GCMarker : public JSTracer
return isMarkStackEmpty() && !unmarkedArenaStackTop;
}
bool drainMarkStack(SliceBudget& budget);
MOZ_MUST_USE bool drainMarkStack(SliceBudget& budget);
void setGCMode(JSGCMode mode) { stack.setGCMode(mode); }
@ -289,7 +289,7 @@ class GCMarker : public JSTracer
// Mark the given GC thing, but do not trace its children. Return true
// if the thing became marked.
template <typename T>
bool mark(T* thing);
MOZ_MUST_USE bool mark(T* thing);
void pushTaggedPtr(StackTag tag, void* ptr) {
checkZone(ptr);
@ -319,7 +319,7 @@ class GCMarker : public JSTracer
return stack.isEmpty();
}
bool restoreValueArray(JSObject* obj, void** vpp, void** endp);
MOZ_MUST_USE bool restoreValueArray(JSObject* obj, void** vpp, void** endp);
void saveValueRanges();
inline void processMarkStackTop(SliceBudget& budget);
@ -451,6 +451,7 @@ struct RewrapTaggedPointer<Value, T>
} /* namespace gc */
// The return value indicates if anything was unmarked.
bool
UnmarkGrayShapeRecursively(Shape* shape);

View File

@ -262,14 +262,13 @@ MarkPagesUnused(void* p, size_t size)
return p2 == p;
}
bool
void
MarkPagesInUse(void* p, size_t size)
{
if (!DecommitEnabled())
return true;
return;
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
return true;
}
size_t
@ -320,7 +319,6 @@ bool
MarkPagesInUse(void* p, size_t size)
{
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
return true;
}
size_t
@ -399,10 +397,9 @@ bool
MarkPagesInUse(void* p, size_t size)
{
if (!DecommitEnabled())
return true;
return;
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
return true;
}
size_t
@ -667,14 +664,13 @@ MarkPagesUnused(void* p, size_t size)
return result != -1;
}
bool
void
MarkPagesInUse(void* p, size_t size)
{
if (!DecommitEnabled())
return true;
return;
MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0);
return true;
}
size_t

View File

@ -29,7 +29,7 @@ bool MarkPagesUnused(void* p, size_t size);
// Undo |MarkPagesUnused|: tell the OS that the given pages are of interest
// and should be paged in and out normally. This may be a no-op on some
// platforms.
bool MarkPagesInUse(void* p, size_t size);
void MarkPagesInUse(void* p, size_t size);
// Returns #(hard faults) + #(soft faults)
size_t GetPageFaultCount();

View File

@ -502,6 +502,13 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
#endif
TIME_END(checkHashTables);
TIME_START(checkHeap);
#ifdef JS_GC_ZEAL
if (rt->hasZealMode(ZealMode::CheckHeapOnMovingGC))
CheckHeapAfterMovingGC(rt);
#endif
TIME_END(checkHeap);
// Resize the nursery.
TIME_START(resize);
double promotionRate = mover.tenuredSize / double(allocationEnd() - start());
@ -552,6 +559,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
{"mcWCll", TIME_TOTAL(traceWholeCells)},
{"mkGnrc", TIME_TOTAL(traceGenericEntries)},
{"ckTbls", TIME_TOTAL(checkHashTables)},
{"ckHeap", TIME_TOTAL(checkHeap)},
{"mkRntm", TIME_TOTAL(markRuntime)},
{"mkDbgr", TIME_TOTAL(markDebugger)},
{"clrNOC", TIME_TOTAL(clearNewObjectCache)},

View File

@ -110,7 +110,7 @@ class Nursery
{}
~Nursery();
bool init(uint32_t maxNurseryBytes);
MOZ_MUST_USE bool init(uint32_t maxNurseryBytes);
bool exists() const { return numNurseryChunks_ != 0; }
size_t numChunks() const { return numNurseryChunks_; }
@ -171,7 +171,7 @@ class Nursery
* sets |*ref| to the new location of the object and returns true. Otherwise
* returns false and leaves |*ref| unset.
*/
MOZ_ALWAYS_INLINE bool getForwardedPointer(JSObject** ref) const;
MOZ_ALWAYS_INLINE MOZ_MUST_USE bool getForwardedPointer(JSObject** ref) const;
/* Forward a slots/elements pointer stored in an Ion frame. */
void forwardBufferPointer(HeapSlot** pSlotsElems);
@ -188,7 +188,7 @@ class Nursery
void waitBackgroundFreeEnd();
bool addedUniqueIdToCell(gc::Cell* cell) {
MOZ_MUST_USE bool addedUniqueIdToCell(gc::Cell* cell) {
if (!IsInsideNursery(cell) || !isEnabled())
return true;
MOZ_ASSERT(cellsWithUid_.initialized());

View File

@ -160,7 +160,7 @@ struct Statistics
/* Create a convenient type for referring to tables of phase times. */
using PhaseTimeTable = int64_t[NumTimingArrays][PHASE_LIMIT];
static bool initialize();
static MOZ_MUST_USE bool initialize();
explicit Statistics(JSRuntime* rt);
~Statistics();
@ -174,8 +174,8 @@ struct Statistics
void endSlice();
void setSliceCycleCount(unsigned cycleCount);
bool startTimingMutator();
bool stopTimingMutator(double& mutator_ms, double& gc_ms);
MOZ_MUST_USE bool startTimingMutator();
MOZ_MUST_USE bool stopTimingMutator(double& mutator_ms, double& gc_ms);
void reset(const char* reason) {
if (!aborted)

View File

@ -66,11 +66,11 @@ StoreBuffer::disable()
enabled_ = false;
}
bool
void
StoreBuffer::clear()
{
if (!enabled_)
return true;
return;
aboutToOverflow_ = false;
cancelIonCompilations_ = false;
@ -80,8 +80,6 @@ StoreBuffer::clear()
bufferSlot.clear();
bufferWholeCell.clear();
bufferGeneric.clear();
return true;
}
void

View File

@ -74,7 +74,7 @@ class StoreBuffer
explicit MonoTypeBuffer() : last_(T()) {}
~MonoTypeBuffer() { stores_.finish(); }
bool init() {
MOZ_MUST_USE bool init() {
if (!stores_.initialized() && !stores_.init())
return false;
clear();
@ -141,7 +141,7 @@ class StoreBuffer
explicit GenericBuffer() : storage_(nullptr) {}
~GenericBuffer() { js_delete(storage_); }
bool init() {
MOZ_MUST_USE bool init() {
if (!storage_)
storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
clear();
@ -410,7 +410,7 @@ class StoreBuffer
void disable();
bool isEnabled() const { return enabled_; }
bool clear();
void clear();
/* Get the overflowed status. */
bool isAboutToOverflow() const { return aboutToOverflow_; }

View File

@ -8,6 +8,8 @@
# include <valgrind/memcheck.h>
#endif
#include "mozilla/IntegerPrintfMacros.h"
#include "jscntxt.h"
#include "jsgc.h"
#include "jsprf.h"
@ -302,13 +304,13 @@ AssertMarkedOrAllocated(const EdgeValue& edge)
MOZ_CRASH();
}
bool
void
gc::GCRuntime::endVerifyPreBarriers()
{
VerifyPreTracer* trc = verifyPreData;
if (!trc)
return false;
return;
MOZ_ASSERT(!JS::IsGenerationalGCEnabled(rt));
@ -357,7 +359,6 @@ gc::GCRuntime::endVerifyPreBarriers()
marker.stop();
js_delete(trc);
return true;
}
/*** Barrier Verifier Scheduling ***/
@ -414,3 +415,123 @@ js::gc::GCRuntime::finishVerifier()
}
#endif /* JS_GC_ZEAL */
#ifdef JSGC_HASH_TABLE_CHECKS
class CheckHeapTracer : public JS::CallbackTracer
{
public:
explicit CheckHeapTracer(JSRuntime* rt);
bool init();
bool check();
private:
void onChild(const JS::GCCellPtr& thing) override;
struct WorkItem {
WorkItem(JS::GCCellPtr thing, const char* name, int parentIndex)
: thing(thing), name(name), parentIndex(parentIndex), processed(false)
{}
JS::GCCellPtr thing;
const char* name;
int parentIndex;
bool processed;
};
JSRuntime* rt;
bool oom;
size_t failures;
HashSet<Cell*, DefaultHasher<Cell*>, SystemAllocPolicy> visited;
Vector<WorkItem, 0, SystemAllocPolicy> stack;
int parentIndex;
};
CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
: CallbackTracer(rt, TraceWeakMapKeysValues),
rt(rt),
oom(false),
failures(0),
parentIndex(-1)
{
setCheckEdges(false);
}
bool
CheckHeapTracer::init()
{
return visited.init();
}
void
CheckHeapTracer::onChild(const JS::GCCellPtr& thing)
{
Cell* cell = thing.asCell();
if (visited.lookup(cell))
return;
if (!visited.put(cell)) {
oom = true;
return;
}
if (!IsGCThingValidAfterMovingGC(cell)) {
failures++;
fprintf(stderr, "Stale pointer %p\n", cell);
const char* name = contextName();
for (int index = parentIndex; index != -1; index = stack[index].parentIndex) {
const WorkItem& parent = stack[index];
cell = parent.thing.asCell();
fprintf(stderr, " from %s %p %s edge\n",
GCTraceKindToAscii(cell->getTraceKind()), cell, name);
name = parent.name;
}
fprintf(stderr, " from root %s\n", name);
return;
}
WorkItem item(thing, contextName(), parentIndex);
if (!stack.append(item))
oom = true;
}
bool
CheckHeapTracer::check()
{
// The analysis thinks that markRuntime might GC by calling a GC callback.
JS::AutoSuppressGCAnalysis nogc(rt);
rt->gc.markRuntime(this, GCRuntime::TraceRuntime);
while (!stack.empty()) {
WorkItem item = stack.back();
if (item.processed) {
stack.popBack();
} else {
parentIndex = stack.length() - 1;
TraceChildren(this, item.thing);
stack.back().processed = true;
}
}
if (oom)
return false;
if (failures) {
fprintf(stderr, "Heap check: %zu failure(s) out of %" PRIu32 " pointers checked\n",
failures, visited.count());
}
MOZ_RELEASE_ASSERT(failures == 0);
return true;
}
void
js::gc::CheckHeapAfterMovingGC(JSRuntime* rt)
{
MOZ_ASSERT(rt->isHeapCollecting());
CheckHeapTracer tracer(rt);
if (!tracer.init() || !tracer.check())
fprintf(stderr, "OOM checking heap\n");
}
#endif /* JSGC_HASH_TABLE_CHECKS */

View File

@ -672,7 +672,7 @@ class ZoneAllocPolicy
void free_(void* p) { js_free(p); }
void reportAllocOverflow() const {}
bool checkSimulatedOOM() const {
MOZ_MUST_USE bool checkSimulatedOOM() const {
return !js::oom::ShouldFailWithOOM();
}
};

View File

@ -1214,7 +1214,8 @@ const char* gc::ZealModeHelpText =
" 11: (IncrementalMarkingValidator) Verify incremental marking\n"
" 12: (ElementsBarrier) Always use the individual element post-write barrier, regardless of elements size\n"
" 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n"
" 14: (Compact) Perform a shrinking collection every N allocations\n";
" 14: (Compact) Perform a shrinking collection every N allocations\n"
" 15: (CheckHeapOnMovingGC) Walk the heap to check all pointers have been updated\n";
void
GCRuntime::setZeal(uint8_t zeal, uint32_t frequency)
@ -3382,7 +3383,7 @@ GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason)
#ifdef JS_GC_ZEAL
if (hasZealMode(ZealMode::Alloc)) {
triggerGC(reason);
MOZ_RELEASE_ASSERT(triggerGC(reason));
return true;
}
#endif
@ -3395,7 +3396,7 @@ GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason)
fullGCForAtomsRequested_ = true;
return false;
}
triggerGC(reason);
MOZ_RELEASE_ASSERT(triggerGC(reason));
return true;
}
@ -4360,8 +4361,8 @@ GCRuntime::markWeakReferences(gcstats::Phase phase)
marker.enterWeakMarkingMode();
// TODO bug 1167452: Make weak marking incremental
SliceBudget budget = SliceBudget::unlimited();
marker.drainMarkStack(budget);
auto unlimited = SliceBudget::unlimited();
MOZ_RELEASE_ASSERT(marker.drainMarkStack(unlimited));
for (;;) {
bool markedAny = false;
@ -4380,7 +4381,7 @@ GCRuntime::markWeakReferences(gcstats::Phase phase)
break;
auto unlimited = SliceBudget::unlimited();
marker.drainMarkStack(unlimited);
MOZ_RELEASE_ASSERT(marker.drainMarkStack(unlimited));
}
MOZ_ASSERT(marker.isDrained());
@ -4407,7 +4408,7 @@ GCRuntime::markGrayReferences(gcstats::Phase phase)
(*op)(&marker, grayRootTracer.data);
}
auto unlimited = SliceBudget::unlimited();
marker.drainMarkStack(unlimited);
MOZ_RELEASE_ASSERT(marker.drainMarkStack(unlimited));
}
void
@ -4568,9 +4569,9 @@ js::gc::MarkingValidator::nonIncrementalMark()
gc->markRuntime(gcmarker, GCRuntime::MarkRuntime);
auto unlimited = SliceBudget::unlimited();
gc->incrementalState = MARK;
gc->marker.drainMarkStack(unlimited);
auto unlimited = SliceBudget::unlimited();
MOZ_RELEASE_ASSERT(gc->marker.drainMarkStack(unlimited));
}
gc->incrementalState = SWEEP;
@ -5031,7 +5032,7 @@ MarkIncomingCrossCompartmentPointers(JSRuntime* rt, const uint32_t color)
}
auto unlimited = SliceBudget::unlimited();
rt->gc.marker.drainMarkStack(unlimited);
MOZ_RELEASE_ASSERT(rt->gc.marker.drainMarkStack(unlimited));
}
static bool
@ -5893,6 +5894,10 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget)
#ifdef DEBUG
CheckHashTablesAfterMovingGC(rt);
#endif
#ifdef JS_GC_ZEAL
if (rt->hasZealMode(ZealMode::CheckHeapOnMovingGC))
CheckHeapAfterMovingGC(rt);
#endif
return zonesToMaybeCompact.isEmpty() ? Finished : NotFinished;
}

View File

@ -1185,14 +1185,19 @@ MaybeForwarded(T t)
#ifdef JSGC_HASH_TABLE_CHECKS
template <typename T>
inline bool
IsGCThingValidAfterMovingGC(T* t)
{
return !IsInsideNursery(t) && !RelocationOverlay::isCellForwarded(t);
}
template <typename T>
inline void
CheckGCThingAfterMovingGC(T* t)
{
if (t) {
MOZ_RELEASE_ASSERT(!IsInsideNursery(t));
MOZ_RELEASE_ASSERT(!RelocationOverlay::isCellForwarded(t));
}
if (t)
MOZ_RELEASE_ASSERT(IsGCThingValidAfterMovingGC(t));
}
template <typename T>
@ -1228,13 +1233,14 @@ CheckValueAfterMovingGC(const JS::Value& value)
D(IncrementalMarkingValidator, 11) \
D(ElementsBarrier, 12) \
D(CheckHashTablesOnMinorGC, 13) \
D(Compact, 14)
D(Compact, 14) \
D(CheckHeapOnMovingGC, 15)
enum class ZealMode {
#define ZEAL_MODE(name, value) name = value,
JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
#undef ZEAL_MODE
Limit = 14
Limit = 15
};
enum VerifierType {

View File

@ -1155,6 +1155,15 @@ RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame(
animationManager->StopAnimationsForElement(element, aPseudoType);
transitionManager->StopTransitionsForElement(element, aPseudoType);
// All other animations should keep running but not running on the
// *compositor* at this point.
EffectSet* effectSet = EffectSet::GetEffectSet(element, aPseudoType);
if (effectSet) {
for (KeyframeEffectReadOnly* effect : *effectSet) {
effect->ResetIsRunningOnCompositor();
}
}
}
}

View File

@ -101,15 +101,9 @@
// Print Options
#include "nsIPrintSettings.h"
#include "nsIPrintOptions.h"
#include "nsIPrintSettingsService.h"
#include "nsISimpleEnumerator.h"
#ifdef DEBUG
// PrintOptions is now implemented by PrintSettingsService
static const char sPrintOptionsContractID[] =
"@mozilla.org/gfx/printsettings-service;1";
#endif // DEBUG
#include "nsIPluginDocument.h"
#endif // NS_PRINTING
@ -2725,11 +2719,12 @@ nsDocumentViewer::Print(bool aSilent,
// if they don't pass in a PrintSettings, then make one
// it will have all the default values
printSettings = aPrintSettings;
nsCOMPtr<nsIPrintOptions> printOptions = do_GetService(sPrintOptionsContractID, &rv);
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc
= do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
if (NS_SUCCEEDED(rv)) {
// if they don't pass in a PrintSettings, then make one
if (printSettings == nullptr) {
printOptions->CreatePrintSettings(getter_AddRefs(printSettings));
printSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
}
NS_ASSERTION(printSettings, "You can't PrintPreview without a PrintSettings!");
}

View File

@ -2734,21 +2734,6 @@ nsPresContext::IsRootContentDocument() const
return (f && f->PresContext()->IsChrome());
}
bool
nsPresContext::IsCrossProcessRootContentDocument()
{
if (!IsRootContentDocument()) {
return false;
}
if (XRE_IsParentProcess()) {
return true;
}
TabChild* tabChild = TabChild::GetFrom(mShell);
return (tabChild && tabChild->IsRootContentDocument());
}
bool nsPresContext::GetPaintFlashing() const
{
if (!mPaintFlashingInitialized) {

View File

@ -1039,7 +1039,6 @@ public:
}
bool IsRootContentDocument() const;
bool IsCrossProcessRootContentDocument();
bool IsGlyph() const {
return mIsGlyph;

View File

@ -5373,8 +5373,21 @@ static bool IsTransparentContainerElement(nsPresContext* aPresContext)
if (!pwin)
return false;
nsCOMPtr<Element> containerElement = pwin->GetFrameElementInternal();
return containerElement &&
containerElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
TabChild* tab = TabChild::GetFrom(docShell);
if (tab) {
// Check if presShell is the top PresShell. Only the top can
// influence the canvas background color.
nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
nsCOMPtr<nsIPresShell> topPresShell = tab->GetPresShell();
if (presShell != topPresShell) {
tab = nullptr;
}
}
return (containerElement &&
containerElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent))
|| (tab && tab->IsTransparent());
}
nscolor PresShell::GetDefaultBackgroundColorToDraw()
@ -5406,7 +5419,7 @@ void PresShell::UpdateCanvasBackground()
drawBackgroundImage,
drawBackgroundColor);
mHasCSSBackgroundColor = drawBackgroundColor;
if (GetPresContext()->IsCrossProcessRootContentDocument() &&
if (mPresContext->IsRootContentDocument() &&
!IsTransparentContainerElement(mPresContext)) {
mCanvasBackgroundColor =
NS_ComposeColors(GetDefaultBackgroundColorToDraw(), mCanvasBackgroundColor);

View File

@ -92,6 +92,7 @@
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/EffectSet.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/EventStates.h"
@ -700,7 +701,7 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
}
}
if (HasCSSAnimations() || HasCSSTransitions()) {
if (EffectSet::GetEffectSet(this)) {
// If no new frame for this element is created by the end of the
// restyling process, stop animations and transitions for this frame
if (presContext->RestyleManager()->IsGecko()) {

View File

@ -31,6 +31,18 @@ parent:
// the actual print.
async FinalizePrint();
// Report a state change to listeners in the parent process.
async StateChange(long aStateFlags,
nsresult aStatus);
// Report a progress change to listeners in the parent process.
async ProgressChange(long aCurSelfProgress,
long aMaxSelfProgress,
long aCurTotalProgress,
long aMaxTotalProgress);
// Report a status change to listeners in the parent process.
async StatusChange(nsresult aStatus);
child:
// Inform the child that the print has been initialized in the parent or has

View File

@ -13,6 +13,9 @@
namespace mozilla {
namespace layout {
NS_IMPL_ISUPPORTS(RemotePrintJobChild,
nsIWebProgressListener)
RemotePrintJobChild::RemotePrintJobChild()
{
MOZ_COUNT_CTOR(RemotePrintJobChild);
@ -86,6 +89,56 @@ RemotePrintJobChild::SetPrintEngine(nsPrintEngine* aPrintEngine)
mPrintEngine = aPrintEngine;
}
// nsIWebProgressListener
NS_IMETHODIMP
RemotePrintJobChild::OnStateChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, uint32_t aStateFlags,
nsresult aStatus)
{
Unused << SendStateChange(aStateFlags, aStatus);
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnProgressChange(nsIWebProgress * aProgress,
nsIRequest * aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
Unused << SendProgressChange(aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnLocationChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, nsIURI* aURI,
uint32_t aFlags)
{
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnStatusChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, nsresult aStatus,
const char16_t* aMessage)
{
Unused << SendStatusChange(aStatus);
return NS_OK;
}
NS_IMETHODIMP
RemotePrintJobChild::OnSecurityChange(nsIWebProgress* aProgress,
nsIRequest* aRequest, uint32_t aState)
{
return NS_OK;
}
// End of nsIWebProgressListener
RemotePrintJobChild::~RemotePrintJobChild()
{
MOZ_COUNT_DTOR(RemotePrintJobChild);

View File

@ -10,6 +10,7 @@
#include "mozilla/layout/PRemotePrintJobChild.h"
#include "mozilla/RefPtr.h"
#include "nsIWebProgressListener.h"
class nsPagePrintTimer;
class nsPrintEngine;
@ -18,9 +19,11 @@ namespace mozilla {
namespace layout {
class RemotePrintJobChild final : public PRemotePrintJobChild
, public nsIWebProgressListener
{
public:
NS_INLINE_DECL_REFCOUNTING(RemotePrintJobChild)
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
RemotePrintJobChild();

View File

@ -15,6 +15,7 @@
#include "nsDeviceContext.h"
#include "nsIDeviceContextSpec.h"
#include "nsIPrintSettings.h"
#include "nsIWebProgressListener.h"
#include "PrintTranslator.h"
namespace mozilla {
@ -149,6 +150,56 @@ RemotePrintJobParent::RecvAbortPrint(const nsresult& aRv)
return true;
}
bool
RemotePrintJobParent::RecvStateChange(const long& aStateFlags,
const nsresult& aStatus)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
listener->OnStateChange(nullptr, nullptr, aStateFlags, aStatus);
}
return true;
}
bool
RemotePrintJobParent::RecvProgressChange(const long& aCurSelfProgress,
const long& aMaxSelfProgress,
const long& aCurTotalProgress,
const long& aMaxTotalProgress)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
listener->OnProgressChange(nullptr, nullptr,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
}
return true;
}
bool
RemotePrintJobParent::RecvStatusChange(const nsresult& aStatus)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
listener->OnStatusChange(nullptr, nullptr, aStatus, nullptr);
}
return true;
}
void
RemotePrintJobParent::RegisterListener(nsIWebProgressListener* aListener)
{
MOZ_ASSERT(aListener);
mPrintProgressListeners.AppendElement(aListener);
}
RemotePrintJobParent::~RemotePrintJobParent()
{
MOZ_COUNT_DTOR(RemotePrintJobParent);

View File

@ -9,12 +9,14 @@
#include "mozilla/layout/PRemotePrintJobParent.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
class nsDeviceContext;
class nsIPrintSettings;
class nsIWebProgressListener;
class PrintTranslator;
namespace mozilla {
@ -38,6 +40,23 @@ public:
bool RecvAbortPrint(const nsresult& aRv) final;
bool RecvStateChange(const long& aStateFlags,
const nsresult& aStatus) final;
bool RecvProgressChange(const long& aCurSelfProgress,
const long& aMaxSelfProgress,
const long& aCurTotalProgress,
const long& aMaxTotalProgress) final;
bool RecvStatusChange(const nsresult& aStatus) final;
/**
* Register a progress listener to receive print progress updates.
*
* @param aListener the progress listener to register. Must not be null.
*/
void RegisterListener(nsIWebProgressListener* aListener);
private:
~RemotePrintJobParent() final;
@ -51,6 +70,7 @@ private:
nsCOMPtr<nsIPrintSettings> mPrintSettings;
RefPtr<nsDeviceContext> mPrintDeviceContext;
UniquePtr<PrintTranslator> mPrintTranslator;
nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
};
} // namespace layout

View File

@ -120,3 +120,15 @@ nsPrintData::DoOnProgressChange(int32_t aProgress,
}
}
void
nsPrintData::DoOnStatusChange(nsresult aStatus)
{
uint32_t numberOfListeners = mPrintProgressListeners.Length();
for (uint32_t i = 0; i < numberOfListeners; ++i) {
nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i);
if (listener) {
listener->OnStatusChange(nullptr, nullptr, aStatus, nullptr);
}
}
}

View File

@ -51,6 +51,8 @@ public:
bool aDoStartStop,
int32_t aFlag);
void DoOnStatusChange(nsresult aStatus);
ePrintDataType mType; // the type of data this is (Printing or Print Preview)
RefPtr<nsDeviceContext> mPrintDC;

View File

@ -475,14 +475,29 @@ nsPrintEngine::DoCommonPrint(bool aIsPrintPreview,
}
// Create a print session and let the print settings know about it.
// Don't overwrite an existing print session.
// The print settings hold an nsWeakPtr to the session so it does not
// need to be cleared from the settings at the end of the job.
// XXX What lifetime does the printSession need to have?
nsCOMPtr<nsIPrintSession> printSession;
bool remotePrintJobListening = false;
if (!aIsPrintPreview) {
rv = mPrt->mPrintSettings->GetPrintSession(getter_AddRefs(printSession));
if (NS_FAILED(rv) || !printSession) {
printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
mPrt->mPrintSettings->SetPrintSession(printSession);
} else {
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv) && remotePrintJob) {
// If we have a RemotePrintJob add it to the print progress listeners,
// so it can forward to the parent.
mPrt->mPrintProgressListeners.AppendElement(remotePrintJob);
remotePrintJobListening = true;
}
}
}
if (aWebProgressListener != nullptr) {
@ -612,6 +627,17 @@ nsPrintEngine::DoCommonPrint(bool aIsPrintPreview,
if (mPrt->mPrintSettings) {
// The user might have changed shrink-to-fit in the print dialog, so update our copy of its state
mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit);
// If we haven't already added the RemotePrintJob as a listener,
// add it now if there is one.
if (!remotePrintJobListening) {
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv) && remotePrintJob) {
mPrt->mPrintProgressListeners.AppendElement(remotePrintJob);
remotePrintJobListening = true;
}
}
}
} else if (rv == NS_ERROR_NOT_IMPLEMENTED) {
// This means the Dialog service was there,
@ -1531,6 +1557,9 @@ nsPrintEngine::FirePrintingErrorEvent(nsresult aPrintError)
new AsyncEventDispatcher(doc, event);
asyncDispatcher->mOnlyChromeDispatch = true;
asyncDispatcher->RunDOMEventWhenSafe();
// Inform any progress listeners of the Error.
mPrt->DoOnStatusChange(aPrintError);
}
//-----------------------------------------------------------------

View File

@ -361,7 +361,7 @@ pref("media.gmp.storage.version.expected", 1);
// Filter what triggers user notifications.
// See DecoderDoctorDocumentWatcher::ReportAnalysis for details.
pref("media.decoder-doctor.notifications-allowed", "MediaWidevineNoWMFNoSilverlight");
pref("media.decoder-doctor.notifications-allowed", "MediaWMFNeeded,MediaWidevineNoWMFNoSilverlight");
// Whether we report partial failures.
pref("media.decoder-doctor.verbose", false);

View File

@ -824,11 +824,10 @@ class Artifacts(object):
return candidate_pushheads
def _get_hg_revisions_from_git(self):
# First commit is HEAD, next is HEAD~1, etc.
rev_list = subprocess.check_output([
self._git, 'rev-list', '--topo-order',
'HEAD~{num}..HEAD'.format(num=NUM_REVISIONS_TO_QUERY),
'--max-count={num}'.format(num=NUM_REVISIONS_TO_QUERY),
'HEAD',
])
hg_hash_list = subprocess.check_output([

View File

@ -184,6 +184,81 @@ config = {
},
},
},
'mozilla-esr45': {
'enable_release_promotion': True,
'repo_path': 'releases/mozilla-esr45',
'update_channel': 'esr',
'branch_uses_per_checkin_strategy': True,
'use_branch_in_symbols_extra_buildid': False,
'stage_server': 'upload.ffxbld.productdelivery.prod.mozaws.net',
'platform_overrides': {
'linux': {
'src_mozconfig': 'browser/config/mozconfigs/linux32/release',
'force_clobber': True,
},
'linux64': {
'src_mozconfig': 'browser/config/mozconfigs/linux64/release',
'force_clobber': True,
},
'macosx64': {
'src_mozconfig': 'browser/config/mozconfigs/macosx-universal/release',
'force_clobber': True,
},
'win32': {
'src_mozconfig': 'browser/config/mozconfigs/win32/release',
'force_clobber': True,
},
'win64': {
'src_mozconfig': 'browser/config/mozconfigs/win64/release',
'force_clobber': True,
},
'linux-debug': {
'update_channel': 'default',
},
'linux64-debug': {
'update_channel': 'default',
},
'linux64-asan-debug': {
'update_channel': 'default',
},
'linux64-asan': {
'update_channel': 'default',
},
'linux64-cc': {
'update_channel': 'default',
},
'linux64-st-an-debug': {
'update_channel': 'default',
},
'linux64-st-an': {
'update_channel': 'default',
},
'linux64-tsan': {
'update_channel': 'default',
},
'macosx64-debug': {
'update_channel': 'default',
},
'macosx64-st-an': {
'update_channel': 'default',
},
'macosx64-mulet': {
'update_channel': 'default',
},
'macosx64-st-an-debug': {
'update_channel': 'default',
},
'win32-debug': {
'update_channel': 'default',
},
'win32-mulet': {
'update_channel': 'default',
},
'win64-debug': {
'update_channel': 'default',
},
},
},
'mozilla-aurora': {
'repo_path': 'releases/mozilla-aurora',
'update_channel': 'aurora',

View File

@ -0,0 +1,18 @@
config = {
"log_name": "bump_esr45",
"version_files": [
{"file": "browser/config/version.txt"},
{"file": "browser/config/version_display.txt"},
{"file": "config/milestone.txt"},
],
"repo": {
"repo": "https://hg.mozilla.org/releases/mozilla-esr45",
"revision": "default",
"dest": "mozilla-esr45",
"vcs": "hg",
},
"push_dest": "ssh://hg.mozilla.org/releases/mozilla-esr45",
"ignore_no_changes": True,
"ssh_user": "ffxbld",
"ssh_key": "~/.ssh/ffxbld_rsa",
}

View File

@ -0,0 +1,34 @@
config = {
"log_name": "updates_esr45",
"repo": {
"repo": "https://hg.mozilla.org/build/tools",
"revision": "default",
"dest": "tools",
"vcs": "hg",
},
"push_dest": "ssh://hg.mozilla.org/build/tools",
"shipped-locales-url": "https://hg.mozilla.org/releases/mozilla-esr45/raw-file/{revision}/browser/locales/shipped-locales",
"ignore_no_changes": True,
"ssh_user": "ffxbld",
"ssh_key": "~/.ssh/ffxbld_rsa",
"archive_domain": "archive.mozilla.org",
"archive_prefix": "https://archive.mozilla.org/pub",
"previous_archive_prefix": "https://archive.mozilla.org/pub",
"download_domain": "download.mozilla.org",
"balrog_url": "https://aus5.mozilla.org",
"balrog_username": "ffxbld",
"update_channels": {
"esr": {
"version_regex": r".*",
"requires_mirrors": True,
"patcher_config": "mozEsr45-branch-patcher2.cfg",
"update_verify_channel": "esr-localtest",
"mar_channel_ids": [],
"channel_names": ["esr", "esr-localtest", "esr-cdntest"],
"rules_to_update": ["esr45-cdntest", "esr45-localtest"],
"publish_rules": ["esr"],
},
},
"balrog_use_dummy_suffix": False,
}

View File

@ -0,0 +1,40 @@
config = {
"nightly_build": True,
"branch": "mozilla-esr45",
"en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-esr45/",
"update_channel": "esr",
"latest_mar_dir": '/pub/mozilla.org/firefox/nightly/latest-mozilla-esr45-l10n',
# l10n
"hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-release",
# repositories
"mozilla_dir": "mozilla-esr45",
"repos": [{
"vcs": "hg",
"repo": "https://hg.mozilla.org/build/tools",
"revision": "default",
"dest": "tools",
}, {
"vcs": "hgtool",
"repo": "https://hg.mozilla.org/releases/mozilla-esr45",
"revision": "default",
"dest": "mozilla-esr45",
}, {
"vcs": "hgtool",
"repo": "https://hg.mozilla.org/build/compare-locales",
"revision": "RELEASE_AUTOMATION"
}],
# purge options
'purge_minsize': 12,
'is_automation': True,
'default_actions': [
"clobber",
"pull",
"list-locales",
"setup",
"repack",
"taskcluster-upload",
"summary",
],
}

View File

@ -336,6 +336,26 @@
"n_buckets": 50,
"description": "Max time spent on one forget skippable (ms)"
},
"FULLSCREEN_TRANSITION_BLACK_MS": {
"alert_emails": ["xquan@mozilla.com"],
"expires_in_version": "never",
"kind": "exponential",
"low": 100,
"high": 5000,
"n_buckets": 50,
"bug_numbers": [1271160],
"description": "The time spent in the fully-black screen in fullscreen transition"
},
"FULLSCREEN_CHANGE_MS": {
"alert_emails": ["xquan@mozilla.com"],
"expires_in_version": "never",
"kind": "exponential",
"low": 100,
"high": 5000,
"n_buckets": 50,
"bug_numbers": [1271160],
"description": "The time content uses to enter/exit fullscreen regardless of fullscreen transition timeout"
},
"GC_REASON_2": {
"alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
"expires_in_version": "never",

View File

@ -0,0 +1,245 @@
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
// These tables share the same updateURL.
const TEST_TABLE_DATA_LIST = [
// 0:
{
tableName: "test-listmanager0-digest256",
providerName: "google",
updateUrl: "http://localhost:4444/safebrowsing/update",
gethashUrl: "http://localhost:4444/safebrowsing/gethash0",
},
// 1:
{
tableName: "test-listmanager1-digest256",
providerName: "google",
updateUrl: "http://localhost:4444/safebrowsing/update",
gethashUrl: "http://localhost:4444/safebrowsing/gethash1",
},
// 2.
{
tableName: "test-listmanager2-digest256",
providerName: "google",
updateUrl: "http://localhost:4444/safebrowsing/update",
gethashUrl: "http://localhost:4444/safebrowsing/gethash2",
}
];
// This table has a different update URL.
const TEST_TABLE_DATA_ANOTHER = {
tableName: "test-listmanageranother-digest256",
providerName: "google",
updateUrl: "http://localhost:5555/safebrowsing/update",
gethashUrl: "http://localhost:5555/safebrowsing/gethash-another",
};
const PREF_NEXTUPDATETIME = "browser.safebrowsing.provider.google.nextupdatetime";
let gListManager = Cc["@mozilla.org/url-classifier/listmanager;1"]
.getService(Ci.nsIUrlListManager);
// Global test server for serving safebrowsing updates.
let gHttpServ = null;
let gUpdateResponse = "";
let gExpectedUpdateRequest = "";
// Handles request for TEST_TABLE_DATA_ANOTHER.
let gHttpServAnother = null;
// These two variables are used to synchronize the last two racing updates
// (in terms of "update URL") in test_update_all_tables().
let gUpdatedCntForTableData = 0; // For TEST_TABLE_DATA_LIST.
let gIsAnotherUpdated = false; // For TEST_TABLE_DATA_ANOTHER.
prefBranch.setBoolPref("browser.safebrowsing.debug", true);
// Register tables.
TEST_TABLE_DATA_LIST.forEach(function(t) {
gListManager.registerTable(t.tableName,
t.providerName,
t.updateUrl,
t.gethashUrl);
});
gListManager.registerTable(TEST_TABLE_DATA_ANOTHER.tableName,
TEST_TABLE_DATA_ANOTHER.providerName,
TEST_TABLE_DATA_ANOTHER.updateUrl,
TEST_TABLE_DATA_ANOTHER.gethashUrl);
const SERVER_INVOLVED_TEST_CASE_LIST = [
// - Do table0 update.
// - Server would respond "a:5:32:32\n[DATA]".
function test_update_table0() {
disableAllUpdates();
gListManager.enableUpdate(TEST_TABLE_DATA_LIST[0].tableName);
gExpectedUpdateRequest = TEST_TABLE_DATA_LIST[0].tableName + ";\n";
gUpdateResponse = "n:1000\ni:" + TEST_TABLE_DATA_LIST[0].tableName + "\n";
gUpdateResponse += readFileToString("data/digest2.chunk");
forceTableUpdate();
},
// - Do table0 update again. Since chunk 5 was added to table0 in the last
// update, the expected request contains "a:5".
// - Server would respond "s;2-12\n[DATA]".
function test_update_table0_with_existing_chunks() {
disableAllUpdates();
gListManager.enableUpdate(TEST_TABLE_DATA_LIST[0].tableName);
gExpectedUpdateRequest = TEST_TABLE_DATA_LIST[0].tableName + ";a:5\n";
gUpdateResponse = "n:1000\ni:" + TEST_TABLE_DATA_LIST[0].tableName + "\n";
gUpdateResponse += readFileToString("data/digest1.chunk");
forceTableUpdate();
},
// - Do all-table update.
// - Server would respond no chunk control.
//
// Note that this test MUST be the last one in the array since we rely on
// the number of sever-involved test case to synchronize the racing last
// two udpates for different URL.
function test_update_all_tables() {
disableAllUpdates();
// Enable all tables including TEST_TABLE_DATA_ANOTHER!
TEST_TABLE_DATA_LIST.forEach(function(t) {
gListManager.enableUpdate(t.tableName);
});
gListManager.enableUpdate(TEST_TABLE_DATA_ANOTHER.tableName);
gExpectedUpdateRequest = TEST_TABLE_DATA_LIST[0].tableName + ";a:5:s:2-12\n" +
TEST_TABLE_DATA_LIST[1].tableName + ";\n" +
TEST_TABLE_DATA_LIST[2].tableName + ";\n";
gUpdateResponse = "n:1000\n";
forceTableUpdate();
},
];
SERVER_INVOLVED_TEST_CASE_LIST.forEach(t => add_test(t));
// Tests nsIUrlListManager.getGethashUrl.
add_test(function test_getGethashUrl() {
TEST_TABLE_DATA_LIST.forEach(function (t) {
equal(gListManager.getGethashUrl(t.tableName), t.gethashUrl);
});
equal(gListManager.getGethashUrl(TEST_TABLE_DATA_ANOTHER.tableName),
TEST_TABLE_DATA_ANOTHER.gethashUrl);
run_next_test();
});
function run_test() {
// Setup primary testing server.
gHttpServ = new HttpServer();
gHttpServ.registerDirectory("/", do_get_cwd());
gHttpServ.registerPathHandler("/safebrowsing/update", function(request, response) {
let body = NetUtil.readInputStreamToString(request.bodyInputStream,
request.bodyInputStream.available());
// Verify if the request is as expected.
equal(body, gExpectedUpdateRequest);
// Respond the update which is controlled by the test case.
response.setHeader("Content-Type",
"application/vnd.google.safebrowsing-update", false);
response.setStatusLine(request.httpVersion, 200, "OK");
response.bodyOutputStream.write(gUpdateResponse, gUpdateResponse.length);
gUpdatedCntForTableData++;
if (gUpdatedCntForTableData !== SERVER_INVOLVED_TEST_CASE_LIST.length) {
// This is not the last test case so run the next once upon the
// the update success.
waitForUpdateSuccess(run_next_test);
return;
}
if (gIsAnotherUpdated) {
run_next_test(); // All tests are done. Just finish.
return;
}
do_print("Waiting for TEST_TABLE_DATA_ANOTHER to be tested ...");
});
gHttpServ.start(4444);
// Setup another testing server for the different update URL.
gHttpServAnother = new HttpServer();
gHttpServAnother.registerDirectory("/", do_get_cwd());
gHttpServAnother.registerPathHandler("/safebrowsing/update", function(request, response) {
let body = NetUtil.readInputStreamToString(request.bodyInputStream,
request.bodyInputStream.available());
// Verify if the request is as expected.
equal(body, TEST_TABLE_DATA_ANOTHER.tableName + ";\n");
// Respond with no chunk control.
response.setHeader("Content-Type",
"application/vnd.google.safebrowsing-update", false);
response.setStatusLine(request.httpVersion, 200, "OK");
let content = "n:1000\n";
response.bodyOutputStream.write(content, content.length);
gIsAnotherUpdated = true;
if (gUpdatedCntForTableData === SERVER_INVOLVED_TEST_CASE_LIST.length) {
// All tests are done!
run_next_test();
return;
}
do_print("Wait for all sever-involved tests to be done ...");
});
gHttpServAnother.start(5555);
run_next_test();
}
// A trick to force updating tables. However, before calling this, we have to
// call disableAllUpdates() first to clean up the updateCheckers in listmanager.
function forceTableUpdate() {
prefBranch.setCharPref(PREF_NEXTUPDATETIME, "1");
gListManager.maybeToggleUpdateChecking();
}
function disableAllUpdates() {
TEST_TABLE_DATA_LIST.forEach(t => gListManager.disableUpdate(t.tableName));
gListManager.disableUpdate(TEST_TABLE_DATA_ANOTHER.tableName);
}
// Since there's no public interface on listmanager to know the update success,
// we could only rely on the refresh of "nextupdatetime".
function waitForUpdateSuccess(callback) {
let nextupdatetime = parseInt(prefBranch.getCharPref(PREF_NEXTUPDATETIME));
do_print("nextupdatetime: " + nextupdatetime);
if (nextupdatetime !== 1) {
callback();
return;
}
do_timeout(1000, waitForUpdateSuccess.bind(null, callback));
}
// Construct an update from a file.
function readFileToString(aFilename) {
let f = do_get_file(aFilename);
let stream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
stream.init(f, -1, 0, 0);
let buf = NetUtil.readInputStreamToString(stream, stream.available());
return buf;
}

View File

@ -17,3 +17,4 @@ support-files =
[test_provider_url.js]
[test_streamupdater.js]
[test_digest256.js]
[test_listmanager.js]

View File

@ -1326,6 +1326,22 @@
</body>
</method>
<method name="print">
<parameter name="aPrintSettings"/>
<parameter name="aPrintProgressListener"/>
<body>
<![CDATA[
var owner = this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
if (!owner.frameLoader) {
throw Components.Exception("No frame loader.",
Components.results.NS_ERROR_FAILURE);
}
owner.frameLoader.print(aPrintSettings, aPrintProgressListener);
]]>
</body>
</method>
<!-- This will go away if the binding has been removed for some reason. -->
<field name="_alive">true</field>
</implementation>

View File

@ -25,7 +25,8 @@ nsPrintOptionsAndroid::~nsPrintOptionsAndroid()
{
}
NS_IMETHODIMP nsPrintOptionsAndroid::CreatePrintSettings(nsIPrintSettings **_retval)
nsresult
nsPrintOptionsAndroid::_CreatePrintSettings(nsIPrintSettings** _retval)
{
nsPrintSettings * printSettings = new nsPrintSettingsAndroid();
NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY);

View File

@ -17,7 +17,7 @@ public:
nsPrintOptionsAndroid();
virtual ~nsPrintOptionsAndroid();
NS_IMETHOD CreatePrintSettings(nsIPrintSettings **_retval);
nsresult _CreatePrintSettings(nsIPrintSettings** _retval) override;
};
#endif /* nsPrintOptionsAndroid_h__ */

View File

@ -431,11 +431,6 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const char16_
return NS_OK;
}
NS_IMETHODIMP nsPrinterEnumeratorGTK::DisplayPropertiesDlg(const char16_t *aPrinter, nsIPrintSettings *aPrintSettings)
{
return NS_OK;
}
//----------------------------------------------------------------------
nsresult GlobalPrinters::InitializeGlobalPrinters ()
{

View File

@ -6,25 +6,7 @@
#include "nsISupports.idl"
#include "nsIPrintSettings.idl"
%{ C++
struct nsFont;
namespace mozilla {
namespace embedding {
class PrintData;
}
}
%}
interface nsIStringEnumerator;
interface nsIWebBrowserPrint;
/**
* Native types
*/
[ref] native nsNativeFontRef(nsFont);
[ref] native PrintDataRef(const mozilla::embedding::PrintData);
[ptr] native PrintDataPtr(mozilla::embedding::PrintData);
/**
* Print options interface
@ -41,64 +23,6 @@ interface nsIPrintOptions : nsISupports
* Show Native Print Options dialog, this may not be supported on all platforms
*/
void ShowPrintSetupDialog(in nsIPrintSettings aThePrintSettings);
/**
* Creates a new PrintSettnigs Object
* and initializes it from prefs
*/
nsIPrintSettings CreatePrintSettings();
/**
* Get a prefixed integer pref
*/
int32_t getPrinterPrefInt(in nsIPrintSettings aPrintSettings, in wstring
aPrefName);
/**
* display Printer Job Properties dialog
*/
void displayJobProperties (in wstring aPrinter, in nsIPrintSettings
aPrintSettings, out boolean aDisplayed);
/**
* Native data constants
*/
const short kNativeDataPrintRecord = 0;
[noscript] voidPtr GetNativeData(in short aDataType);
/**
* Given some nsIPrintSettings and (optionally) an nsIWebBrowserPrint, populates
* a PrintData representing them which can be sent over IPC. Values are only
* ever read from aSettings and aWBP.
*
* @param aSettings
* An nsIPrintSettings for a print job.
* @param aWBP (optional)
* The nsIWebBrowserPrint for the print job.
* @param data
* Pointer to a pre-existing PrintData to populate.
*
* @return nsresult
*/
[noscript] void SerializeToPrintData(in nsIPrintSettings aPrintSettings,
in nsIWebBrowserPrint aWebBrowserPrint,
in PrintDataPtr data);
/**
* This function is the opposite of SerializeToPrintData, in that it takes
* a PrintData, and populates a pre-existing nsIPrintSettings with the data
* from PrintData.
*
* @param PrintData
* Printing information sent through IPC.
* @param settings
* A pre-existing nsIPrintSettings to populate with the PrintData.
*
* @return nsresult
*/
[noscript] void DeserializeToPrintSettings(in PrintDataRef data,
in nsIPrintSettings aPrintSettings);
};
[scriptable, uuid(5e738fff-404c-4c94-9189-e8f2cce93e94)]
@ -126,11 +50,5 @@ interface nsIPrinterEnumerator : nsISupports
* The list of printer names
*/
readonly attribute nsIStringEnumerator printerNameList;
/* takes printer selected and will display job properties dlg for that printer
* returns true if dialog displays
*/
void displayPropertiesDlg(in wstring aPrinter, in nsIPrintSettings aPrintSettings);
};

View File

@ -10,6 +10,21 @@
#include "nsISupports.idl"
interface nsIPrintSettings;
interface nsIWebBrowserPrint;
%{ C++
namespace mozilla {
namespace embedding {
class PrintData;
}
}
%}
/**
* Native types
*/
[ref] native PrintDataRef(const mozilla::embedding::PrintData);
[ptr] native PrintDataPtr(mozilla::embedding::PrintData);
[scriptable, uuid(841387C8-72E6-484b-9296-BF6EEA80D58A)]
interface nsIPrintSettingsService : nsISupports
@ -34,7 +49,8 @@ interface nsIPrintSettingsService : nsISupports
* If each browse window was to use the same PrintSettings object
* then it should use "globalPrintSettings"
*
* Initializes the newPrintSettings from the default printer
* Initializes the newPrintSettings from the unprefixed printer
* (Note: this may not happen if there is an OS specific implementation.)
*
*/
readonly attribute nsIPrintSettings newPrintSettings;
@ -97,6 +113,41 @@ interface nsIPrintSettingsService : nsISupports
*/
void savePrintSettingsToPrefs(in nsIPrintSettings aPrintSettings, in boolean aUsePrinterNamePrefix, in unsigned long aFlags);
/**
* Given some nsIPrintSettings and (optionally) an nsIWebBrowserPrint,
* populates a PrintData representing them which can be sent over IPC. Values
* are only ever read from aSettings and aWBP.
*
* @param aSettings
* An nsIPrintSettings for a print job.
* @param aWBP (optional)
* The nsIWebBrowserPrint for the print job.
* @param data
* Pointer to a pre-existing PrintData to populate.
*
* @return nsresult
*/
[noscript]
void SerializeToPrintData(in nsIPrintSettings aPrintSettings,
in nsIWebBrowserPrint aWebBrowserPrint,
in PrintDataPtr data);
/**
* This function is the opposite of SerializeToPrintData, in that it takes
* a PrintData, and populates a pre-existing nsIPrintSettings with the data
* from PrintData.
*
* @param PrintData
* Printing information sent through IPC.
* @param settings
* A pre-existing nsIPrintSettings to populate with the PrintData.
*
* @return nsresult
*/
[noscript]
void DeserializeToPrintSettings(in PrintDataRef data,
in nsIPrintSettings aPrintSettings);
};
%{C++

View File

@ -12,9 +12,9 @@
#include "nsReadableUtils.h"
#include "nsPrintSettingsImpl.h"
#include "nsIPrintSession.h"
#include "nsServiceManagerUtils.h"
#include "nsIDOMWindow.h"
#include "nsIServiceManager.h"
#include "nsIDialogParamBlock.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
@ -105,6 +105,16 @@ nsPrintOptions::SerializeToPrintData(nsIPrintSettings* aSettings,
nsIWebBrowserPrint* aWBP,
PrintData* data)
{
nsCOMPtr<nsIPrintSession> session;
nsresult rv = aSettings->GetPrintSession(getter_AddRefs(session));
if (NS_SUCCEEDED(rv) && session) {
RefPtr<RemotePrintJobChild> remotePrintJob;
rv = session->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv)) {
data->remotePrintJobChild() = remotePrintJob;
}
}
aSettings->GetStartPageRange(&data->startPageRange());
aSettings->GetEndPageRange(&data->endPageRange());
@ -965,33 +975,6 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName,
return NS_OK;
}
NS_IMETHODIMP
nsPrintOptions::DisplayJobProperties(const char16_t *aPrinter,
nsIPrintSettings* aPrintSettings,
bool *aDisplayed)
{
NS_ENSURE_ARG_POINTER(aPrinter);
*aDisplayed = false;
nsresult rv;
nsCOMPtr<nsIPrinterEnumerator> propDlg =
do_CreateInstance(NS_PRINTER_ENUMERATOR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_ARG_POINTER(aPrintSettings);
rv = propDlg->DisplayPropertiesDlg(aPrinter, aPrintSettings);
NS_ENSURE_SUCCESS(rv, rv);
*aDisplayed = true;
return rv;
}
NS_IMETHODIMP nsPrintOptions::GetNativeData(int16_t aDataType, void * *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsPrintOptions::_CreatePrintSettings(nsIPrintSettings **_retval)
{
// does not initially ref count
@ -1011,17 +994,12 @@ nsresult nsPrintOptions::_CreatePrintSettings(nsIPrintSettings **_retval)
return NS_OK;
}
NS_IMETHODIMP nsPrintOptions::CreatePrintSettings(nsIPrintSettings **_retval)
{
return _CreatePrintSettings(_retval);
}
NS_IMETHODIMP
nsPrintOptions::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
{
nsresult rv;
rv = CreatePrintSettings(getter_AddRefs(mGlobalPrintSettings));
rv = _CreatePrintSettings(getter_AddRefs(mGlobalPrintSettings));
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aGlobalPrintSettings = mGlobalPrintSettings.get());
@ -1032,7 +1010,7 @@ nsPrintOptions::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
NS_IMETHODIMP
nsPrintOptions::GetNewPrintSettings(nsIPrintSettings * *aNewPrintSettings)
{
return CreatePrintSettings(aNewPrintSettings);
return _CreatePrintSettings(aNewPrintSettings);
}
NS_IMETHODIMP
@ -1104,6 +1082,7 @@ nsPrintOptions::InitPrintSettingsFromPrinter(const char16_t *aPrinterName,
return rv;
}
#ifndef MOZ_X11
/** ---------------------------------------------------
* Helper function - Returns either the name or sets the length to zero
*/
@ -1143,31 +1122,7 @@ GetAdjustedPrinterName(nsIPrintSettings* aPS, bool aUsePNP,
}
return NS_OK;
}
NS_IMETHODIMP
nsPrintOptions::GetPrinterPrefInt(nsIPrintSettings *aPrintSettings,
const char16_t *aPrefName, int32_t *_retval)
{
NS_ENSURE_ARG_POINTER(aPrintSettings);
NS_ENSURE_ARG_POINTER(aPrefName);
nsAutoString prtName;
// Get the Printer Name from the PrintSettings
// to use as a prefix for Pref Names
GetAdjustedPrinterName(aPrintSettings, true, prtName);
const char* prefName =
GetPrefName(NS_LossyConvertUTF16toASCII(aPrefName).get(), prtName);
NS_ENSURE_TRUE(prefName, NS_ERROR_FAILURE);
int32_t iVal;
nsresult rv = Preferences::GetInt(prefName, &iVal);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = iVal;
return rv;
}
#endif
NS_IMETHODIMP
nsPrintOptions::InitPrintSettingsFromPrefs(nsIPrintSettings* aPS,

Some files were not shown because too many files have changed in this diff Show More