Merge inbound to mozilla-central. a=merge

This commit is contained in:
shindli 2019-05-22 18:26:18 +03:00
commit bdf94edb89
31 changed files with 2287 additions and 431 deletions

View File

@ -26,6 +26,10 @@
#include "IDecodingTask.h"
#include "RasterImage.h"
#if defined(XP_WIN)
# include <objbase.h>
#endif
using std::max;
using std::min;
@ -333,7 +337,22 @@ DecodePool* DecodePool::Singleton() {
/* static */
uint32_t DecodePool::NumberOfCores() { return sNumCores; }
DecodePool::DecodePool() : mMutex("image::DecodePool") {
#if defined(XP_WIN)
class IOThreadIniter final : public Runnable {
public:
explicit IOThreadIniter() : Runnable("image::IOThreadIniter") {}
NS_IMETHOD Run() override {
MOZ_ASSERT(!NS_IsMainThread());
CoInitialize(nullptr);
return NS_OK;
}
};
#endif
DecodePool::DecodePool() : mMutex("image::IOThread") {
// Determine the number of threads we want.
int32_t prefLimit = gfxPrefs::ImageMTDecodingLimit();
uint32_t limit;
@ -379,7 +398,16 @@ DecodePool::DecodePool() : mMutex("image::DecodePool") {
mImpl = new DecodePoolImpl(limit, idleLimit, idleTimeout);
// Initialize the I/O thread.
#if defined(XP_WIN)
// On Windows we use the io thread to get icons from the system. Any thread
// that makes system calls needs to call CoInitialize. And these system calls
// (SHGetFileInfo) should only be called from one thread at a time, in case
// we ever create more than on io thread.
nsCOMPtr<nsIRunnable> initer = new IOThreadIniter();
nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread), initer);
#else
nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread));
#endif
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOThread,
"Should successfully create image I/O thread");

View File

@ -286,7 +286,7 @@ void Downscaler::DownscaleInputLine() {
// Shift the buffer. We're just moving pointers here, so this is cheap.
mLinesInBuffer -= diff;
mLinesInBuffer = min(max(mLinesInBuffer, 0), mWindowCapacity);
mLinesInBuffer = std::min(std::max(mLinesInBuffer, 0), mWindowCapacity);
// If we already have enough rows to satisfy the filter, there is no need
// to swap as we won't be writing more before the next convolution.

View File

@ -219,14 +219,23 @@ DynamicImage::Draw(gfxContext* aContext, const nsIntSize& aSize,
}
NS_IMETHODIMP
DynamicImage::StartDecoding(uint32_t aFlags) { return NS_OK; }
DynamicImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
return NS_OK;
}
bool DynamicImage::StartDecodingWithResult(uint32_t aFlags) { return true; }
bool DynamicImage::StartDecodingWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return true;
}
bool DynamicImage::RequestDecodeWithResult(uint32_t aFlags) { return true; }
bool DynamicImage::RequestDecodeWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return true;
}
NS_IMETHODIMP
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) {
return NS_OK;
}

View File

@ -92,6 +92,27 @@ FrozenImage::Draw(gfxContext* aContext, const nsIntSize& aSize,
aSamplingFilter, aSVGContext, aFlags, aOpacity);
}
NS_IMETHODIMP
FrozenImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
return InnerImage()->StartDecoding(aFlags, FRAME_FIRST);
}
bool FrozenImage::StartDecodingWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return InnerImage()->StartDecodingWithResult(aFlags, FRAME_FIRST);
}
bool FrozenImage::RequestDecodeWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return InnerImage()->RequestDecodeWithResult(aFlags, FRAME_FIRST);
}
NS_IMETHODIMP
FrozenImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) {
return InnerImage()->RequestDecodeForSize(aSize, aFlags, FRAME_FIRST);
}
NS_IMETHODIMP_(void)
FrozenImage::RequestRefresh(const TimeStamp& aTime) {
// Do nothing.

View File

@ -59,6 +59,13 @@ class FrozenImage : public ImageWrapper {
uint32_t aWhichFrame, gfx::SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext, uint32_t aFlags,
float aOpacity) override;
NS_IMETHOD StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) override;
NS_IMETHOD_(bool)
StartDecodingWithResult(uint32_t aFlags, uint32_t aWhichFrame) override;
NS_IMETHOD_(bool)
RequestDecodeWithResult(uint32_t aFlags, uint32_t aWhichFrame) override;
NS_IMETHOD RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) override;
NS_IMETHOD_(void) RequestRefresh(const TimeStamp& aTime) override;
NS_IMETHOD GetAnimationMode(uint16_t* aAnimationMode) override;
NS_IMETHOD SetAnimationMode(uint16_t aAnimationMode) override;

View File

@ -193,21 +193,24 @@ ImageWrapper::Draw(gfxContext* aContext, const nsIntSize& aSize,
}
NS_IMETHODIMP
ImageWrapper::StartDecoding(uint32_t aFlags) {
return mInnerImage->StartDecoding(aFlags);
ImageWrapper::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
return mInnerImage->StartDecoding(aFlags, aWhichFrame);
}
bool ImageWrapper::StartDecodingWithResult(uint32_t aFlags) {
return mInnerImage->StartDecodingWithResult(aFlags);
bool ImageWrapper::StartDecodingWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return mInnerImage->StartDecodingWithResult(aFlags, aWhichFrame);
}
bool ImageWrapper::RequestDecodeWithResult(uint32_t aFlags) {
return mInnerImage->RequestDecodeWithResult(aFlags);
bool ImageWrapper::RequestDecodeWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return mInnerImage->RequestDecodeWithResult(aFlags, aWhichFrame);
}
NS_IMETHODIMP
ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
return mInnerImage->RequestDecodeForSize(aSize, aFlags);
ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) {
return mInnerImage->RequestDecodeForSize(aSize, aFlags, aWhichFrame);
}
NS_IMETHODIMP

View File

@ -1046,7 +1046,7 @@ bool RasterImage::CanDiscard() {
}
NS_IMETHODIMP
RasterImage::StartDecoding(uint32_t aFlags) {
RasterImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
if (mError) {
return NS_ERROR_FAILURE;
}
@ -1058,10 +1058,11 @@ RasterImage::StartDecoding(uint32_t aFlags) {
uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST |
FLAG_HIGH_QUALITY_SCALING;
return RequestDecodeForSize(mSize, flags);
return RequestDecodeForSize(mSize, flags, aWhichFrame);
}
bool RasterImage::StartDecodingWithResult(uint32_t aFlags) {
bool RasterImage::StartDecodingWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
if (mError) {
return false;
}
@ -1073,11 +1074,13 @@ bool RasterImage::StartDecodingWithResult(uint32_t aFlags) {
uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST |
FLAG_HIGH_QUALITY_SCALING;
DrawableSurface surface = RequestDecodeForSizeInternal(mSize, flags);
DrawableSurface surface =
RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
return surface && surface->IsFinished();
}
bool RasterImage::RequestDecodeWithResult(uint32_t aFlags) {
bool RasterImage::RequestDecodeWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
MOZ_ASSERT(NS_IsMainThread());
if (mError) {
@ -1085,27 +1088,33 @@ bool RasterImage::RequestDecodeWithResult(uint32_t aFlags) {
}
uint32_t flags = aFlags | FLAG_ASYNC_NOTIFY;
DrawableSurface surface = RequestDecodeForSizeInternal(mSize, flags);
DrawableSurface surface =
RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
return surface && surface->IsFinished();
}
NS_IMETHODIMP
RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags) {
RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) {
MOZ_ASSERT(NS_IsMainThread());
if (mError) {
return NS_ERROR_FAILURE;
}
RequestDecodeForSizeInternal(aSize, aFlags);
RequestDecodeForSizeInternal(aSize, aFlags, aWhichFrame);
return NS_OK;
}
DrawableSurface RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize,
uint32_t aFlags) {
DrawableSurface RasterImage::RequestDecodeForSizeInternal(
const IntSize& aSize, uint32_t aFlags, uint32_t aWhichFrame) {
MOZ_ASSERT(NS_IsMainThread());
if (aWhichFrame > FRAME_MAX_VALUE) {
return DrawableSurface();
}
if (mError) {
return DrawableSurface();
}
@ -1125,10 +1134,8 @@ DrawableSurface RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize,
shouldSyncDecodeIfFast ? aFlags : aFlags & ~FLAG_SYNC_DECODE_IF_FAST;
// Perform a frame lookup, which will implicitly start decoding if needed.
PlaybackType playbackType =
mAnimationState ? PlaybackType::eAnimated : PlaybackType::eStatic;
LookupResult result =
LookupFrame(aSize, flags, playbackType, /* aMarkUsed = */ false);
LookupResult result = LookupFrame(aSize, flags, ToPlaybackType(aWhichFrame),
/* aMarkUsed = */ false);
return std::move(result.Surface());
}
@ -1697,7 +1704,8 @@ void RasterImage::NotifyDecodeComplete(
if (mWantFullDecode) {
mWantFullDecode = false;
RequestDecodeForSize(mSize,
DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING);
DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING,
FRAME_CURRENT);
}
}
}

View File

@ -452,7 +452,8 @@ class RasterImage final : public ImageResource,
bool IsOpaque();
DrawableSurface RequestDecodeForSizeInternal(const gfx::IntSize& aSize,
uint32_t aFlags);
uint32_t aFlags,
uint32_t aWhichFrame);
protected:
explicit RasterImage(nsIURI* aURI = nullptr);

View File

@ -1202,23 +1202,26 @@ void VectorImage::RecoverFromLossOfSurfaces() {
}
NS_IMETHODIMP
VectorImage::StartDecoding(uint32_t aFlags) {
VectorImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
// Nothing to do for SVG images
return NS_OK;
}
bool VectorImage::StartDecodingWithResult(uint32_t aFlags) {
bool VectorImage::StartDecodingWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
// SVG images are ready to draw when they are loaded
return mIsFullyLoaded;
}
bool VectorImage::RequestDecodeWithResult(uint32_t aFlags) {
bool VectorImage::RequestDecodeWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
// SVG images are ready to draw when they are loaded
return mIsFullyLoaded;
}
NS_IMETHODIMP
VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) {
// Nothing to do for SVG images, though in theory we could rasterize to the
// provided size ahead of time if we supported off-main-thread SVG
// rasterization...

View File

@ -8,4 +8,8 @@ SOURCES += [
'nsIconChannel.cpp',
]
LOCAL_INCLUDES += [
'/image',
]
FINAL_LIBRARY = 'xul'

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ArrayUtils.h"
#include "mozilla/Monitor.h"
#include "nsIconChannel.h"
#include "nsIIconURI.h"
@ -17,7 +18,6 @@
#include "nsMemory.h"
#include "nsIStringStream.h"
#include "nsIURL.h"
#include "nsIOutputStream.h"
#include "nsIPipe.h"
#include "nsNetCID.h"
#include "nsIFile.h"
@ -29,6 +29,10 @@
#include "nsContentSecurityManager.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "Decoder.h"
#include "DecodePool.h"
// we need windows.h to read out registry information...
#include <windows.h>
@ -38,6 +42,7 @@
#include <wchar.h>
using namespace mozilla;
using namespace mozilla::image;
struct ICONFILEHEADER {
uint16_t ifhReserved;
@ -61,6 +66,95 @@ static SHSTOCKICONID GetStockIconIDForName(const nsACString& aStockName) {
return aStockName.EqualsLiteral("uac-shield") ? SIID_SHIELD : SIID_INVALID;
}
class nsIconChannel::IconAsyncOpenTask final : public Runnable {
public:
IconAsyncOpenTask(nsIconChannel* aChannel, nsIEventTarget* aTarget,
nsCOMPtr<nsIFile>&& aLocalFile, nsAutoString& aPath,
UINT aInfoFlags)
: Runnable("IconAsyncOpenTask"),
mChannel(aChannel),
mTarget(aTarget),
mLocalFile(std::move(aLocalFile)),
mPath(aPath),
mInfoFlags(aInfoFlags) {}
NS_IMETHOD Run() override;
private:
RefPtr<nsIconChannel> mChannel;
nsCOMPtr<nsIEventTarget> mTarget;
nsCOMPtr<nsIFile> mLocalFile;
nsAutoString mPath;
UINT mInfoFlags;
};
NS_IMETHODIMP nsIconChannel::IconAsyncOpenTask::Run() {
HICON hIcon = nullptr;
nsresult rv =
mChannel->GetHIconFromFile(mLocalFile, mPath, mInfoFlags, &hIcon);
nsCOMPtr<nsIRunnable> task = NewRunnableMethod<HICON, nsresult>(
"nsIconChannel::FinishAsyncOpen", mChannel,
&nsIconChannel::FinishAsyncOpen, hIcon, rv);
mTarget->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
return NS_OK;
}
class nsIconChannel::IconSyncOpenTask final : public Runnable {
public:
IconSyncOpenTask(nsIconChannel* aChannel, nsIEventTarget* aTarget,
nsCOMPtr<nsIFile>&& aLocalFile, nsAutoString& aPath,
UINT aInfoFlags)
: Runnable("IconSyncOpenTask"),
mMonitor("IconSyncOpenTask"),
mDone(false),
mChannel(aChannel),
mTarget(aTarget),
mLocalFile(std::move(aLocalFile)),
mPath(aPath),
mInfoFlags(aInfoFlags),
mHIcon(nullptr),
mRv(NS_OK) {}
NS_IMETHOD Run() override;
Monitor& GetMonitor() { return mMonitor; }
bool Done() const {
mMonitor.AssertCurrentThreadOwns();
return mDone;
}
HICON GetHIcon() const {
mMonitor.AssertCurrentThreadOwns();
return mHIcon;
}
nsresult GetRv() const {
mMonitor.AssertCurrentThreadOwns();
return mRv;
}
private:
Monitor mMonitor;
bool mDone;
// Parameters in
RefPtr<nsIconChannel> mChannel;
nsCOMPtr<nsIEventTarget> mTarget;
nsCOMPtr<nsIFile> mLocalFile;
nsAutoString mPath;
UINT mInfoFlags;
// Return values
HICON mHIcon;
nsresult mRv;
};
NS_IMETHODIMP
nsIconChannel::IconSyncOpenTask::Run() {
MonitorAutoLock lock(mMonitor);
mRv = mChannel->GetHIconFromFile(mLocalFile, mPath, mInfoFlags, &mHIcon);
mDone = true;
mMonitor.NotifyAll();
return NS_OK;
}
// nsIconChannel methods
nsIconChannel::nsIconChannel() {}
@ -162,7 +256,13 @@ nsIconChannel::Open(nsIInputStream** aStream) {
nsContentSecurityManager::doContentSecurityCheck(this, listener);
NS_ENSURE_SUCCESS(rv, rv);
return MakeInputStream(aStream, false);
HICON hIcon = nullptr;
rv = GetHIcon(/* aNonBlocking */ false, &hIcon);
if (NS_FAILED(rv)) {
return rv;
}
return MakeInputStream(aStream, /* aNonBlocking */ false, hIcon);
}
nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
@ -191,6 +291,39 @@ nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
return file->Clone(aLocalFile);
}
void nsIconChannel::OnAsyncError(nsresult aStatus) {
OnStartRequest(this);
OnStopRequest(this, aStatus);
}
void nsIconChannel::FinishAsyncOpen(HICON aIcon, nsresult aStatus) {
MOZ_ASSERT(NS_IsMainThread());
if (NS_FAILED(aStatus)) {
OnAsyncError(aStatus);
return;
}
nsCOMPtr<nsIInputStream> inStream;
nsresult rv = MakeInputStream(getter_AddRefs(inStream),
/* aNonBlocking */ true, aIcon);
if (NS_FAILED(rv)) {
OnAsyncError(rv);
return;
}
rv = mPump->Init(inStream, 0, 0, false, mListenerTarget);
if (NS_FAILED(rv)) {
OnAsyncError(rv);
return;
}
rv = mPump->AsyncRead(this, nullptr);
if (NS_FAILED(rv)) {
OnAsyncError(rv);
}
}
NS_IMETHODIMP
nsIconChannel::AsyncOpen(nsIStreamListener* aListener) {
nsCOMPtr<nsIStreamListener> listener = aListener;
@ -210,34 +343,41 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener) {
"security flags in loadInfo but doContentSecurityCheck() not called");
nsCOMPtr<nsIInputStream> inStream;
rv = MakeInputStream(getter_AddRefs(inStream), true);
rv = EnsurePipeCreated(/* aIconSize */ 0, /* aNonBlocking */ true);
if (NS_FAILED(rv)) {
mCallbacks = nullptr;
return rv;
}
// Init our streampump
nsCOMPtr<nsIEventTarget> target = nsContentUtils::GetEventTargetByLoadInfo(
mListenerTarget = nsContentUtils::GetEventTargetByLoadInfo(
mLoadInfo, mozilla::TaskCategory::Other);
rv = mPump->Init(inStream, 0, 0, false, target);
if (!mListenerTarget) {
mListenerTarget = do_GetMainThread();
}
// If we pass aNonBlocking as true, GetHIcon will always have dispatched
// upon success.
HICON hIcon = nullptr;
rv = GetHIcon(/* aNonBlocking */ true, &hIcon);
if (NS_FAILED(rv)) {
mCallbacks = nullptr;
mInputStream = nullptr;
mOutputStream = nullptr;
mListenerTarget = nullptr;
return rv;
}
rv = mPump->AsyncRead(this, nullptr);
if (NS_SUCCEEDED(rv)) {
// Store our real listener
mListener = aListener;
// Add ourself to the load group, if available
if (mLoadGroup) {
mLoadGroup->AddRequest(this, nullptr);
}
} else {
mCallbacks = nullptr;
// We shouldn't have the icon yet if it is non-blocking.
MOZ_ASSERT(!hIcon);
// Add ourself to the load group, if available
if (mLoadGroup) {
mLoadGroup->AddRequest(this, nullptr);
}
return rv;
// Store our real listener
mListener = aListener;
return NS_OK;
}
static DWORD GetSpecialFolderIcon(nsIFile* aFile, int aFolder,
@ -276,7 +416,7 @@ static UINT GetSizeInfoFlag(uint32_t aDesiredImageSize) {
return (UINT)(aDesiredImageSize > 16 ? SHGFI_SHELLICONSIZE : SHGFI_SMALLICON);
}
nsresult nsIconChannel::GetHIconFromFile(HICON* hIcon) {
nsresult nsIconChannel::GetHIconFromFile(bool aNonBlocking, HICON* hIcon) {
nsCString contentType;
nsCString fileExt;
nsCOMPtr<nsIFile> localFile; // file we want an icon for
@ -287,7 +427,6 @@ nsresult nsIconChannel::GetHIconFromFile(HICON* hIcon) {
// if the file exists, we are going to use it's real attributes...
// otherwise we only want to use it for it's extension...
SHFILEINFOW sfi;
UINT infoFlags = SHGFI_ICON;
bool fileExists = false;
@ -334,13 +473,41 @@ nsresult nsIconChannel::GetHIconFromFile(HICON* hIcon) {
filePath = NS_LITERAL_STRING(".") + NS_ConvertUTF8toUTF16(defFileExt);
}
if (aNonBlocking) {
RefPtr<nsIEventTarget> target = DecodePool::Singleton()->GetIOEventTarget();
RefPtr<IconAsyncOpenTask> task = new IconAsyncOpenTask(
this, mListenerTarget, std::move(localFile), filePath, infoFlags);
target->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
return NS_OK;
}
// We cannot call SHGetFileInfo on more than one thread (at a time), so it
// must be called on the same thread every time, even now when we need sync
// behaviour. So we synchronously wait on the other thread to finish.
RefPtr<nsIEventTarget> target = DecodePool::Singleton()->GetIOEventTarget();
RefPtr<IconSyncOpenTask> task = new IconSyncOpenTask(
this, mListenerTarget, std::move(localFile), filePath, infoFlags);
MonitorAutoLock lock(task->GetMonitor());
target->Dispatch(task, NS_DISPATCH_NORMAL);
do {
task->GetMonitor().Wait();
} while (!task->Done());
*hIcon = task->GetHIcon();
return task->GetRv();
}
nsresult nsIconChannel::GetHIconFromFile(nsIFile* aLocalFile,
const nsAutoString& aPath,
UINT aInfoFlags, HICON* hIcon) {
SHFILEINFOW sfi;
// Is this the "Desktop" folder?
DWORD shellResult =
GetSpecialFolderIcon(localFile, CSIDL_DESKTOP, &sfi, infoFlags);
GetSpecialFolderIcon(aLocalFile, CSIDL_DESKTOP, &sfi, aInfoFlags);
if (!shellResult) {
// Is this the "My Documents" folder?
shellResult =
GetSpecialFolderIcon(localFile, CSIDL_PERSONAL, &sfi, infoFlags);
GetSpecialFolderIcon(aLocalFile, CSIDL_PERSONAL, &sfi, aInfoFlags);
}
// There are other "Special Folders" and Namespace entities that we
@ -351,17 +518,16 @@ nsresult nsIconChannel::GetHIconFromFile(HICON* hIcon) {
// Not a special folder, or something else failed above.
if (!shellResult) {
shellResult = ::SHGetFileInfoW(filePath.get(), FILE_ATTRIBUTE_ARCHIVE, &sfi,
sizeof(sfi), infoFlags);
shellResult = ::SHGetFileInfoW(aPath.get(), FILE_ATTRIBUTE_ARCHIVE, &sfi,
sizeof(sfi), aInfoFlags);
}
if (shellResult && sfi.hIcon) {
*hIcon = sfi.hIcon;
} else {
rv = NS_ERROR_NOT_AVAILABLE;
if (!shellResult || !sfi.hIcon) {
return NS_ERROR_NOT_AVAILABLE;
}
return rv;
*hIcon = sfi.hIcon;
return NS_OK;
}
nsresult nsIconChannel::GetStockHIcon(nsIMozIconURI* aIconURI, HICON* hIcon) {
@ -454,32 +620,43 @@ static BITMAPINFO* CreateBitmapInfo(BITMAPINFOHEADER* aHeader,
return bmi;
}
nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval,
bool aNonBlocking) {
nsresult nsIconChannel::EnsurePipeCreated(uint32_t aIconSize,
bool aNonBlocking) {
if (mInputStream || mOutputStream) {
return NS_OK;
}
return NS_NewPipe(getter_AddRefs(mInputStream), getter_AddRefs(mOutputStream),
aIconSize, aIconSize > 0 ? aIconSize : UINT32_MAX,
aNonBlocking);
}
nsresult nsIconChannel::GetHIcon(bool aNonBlocking, HICON* aIcon) {
// Check whether the icon requested's a file icon or a stock icon
nsresult rv = NS_ERROR_NOT_AVAILABLE;
// GetDIBits does not exist on windows mobile.
HICON hIcon = nullptr;
nsCOMPtr<nsIMozIconURI> iconURI(do_QueryInterface(mUrl, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString stockIcon;
iconURI->GetStockIcon(stockIcon);
if (!stockIcon.IsEmpty()) {
rv = GetStockHIcon(iconURI, &hIcon);
} else {
rv = GetHIconFromFile(&hIcon);
return GetStockHIcon(iconURI, aIcon);
}
NS_ENSURE_SUCCESS(rv, rv);
return GetHIconFromFile(aNonBlocking, aIcon);
}
if (hIcon) {
nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval,
bool aNonBlocking, HICON aIcon) {
nsresult rv = NS_ERROR_FAILURE;
if (aIcon) {
// we got a handle to an icon. Now we want to get a bitmap for the icon
// using GetIconInfo....
ICONINFO iconInfo;
if (GetIconInfo(hIcon, &iconInfo)) {
if (GetIconInfo(aIcon, &iconInfo)) {
// we got the bitmaps, first find out their size
HDC hDC = CreateCompatibleDC(nullptr); // get a device context for
// the screen.
@ -560,16 +737,12 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval,
GetDIBits(hDC, iconInfo.hbmMask, 0, maskHeader.biHeight,
whereTo, maskInfo, DIB_RGB_COLORS)) {
// Now, create a pipe and stuff our data into it
nsCOMPtr<nsIInputStream> inStream;
nsCOMPtr<nsIOutputStream> outStream;
rv = NS_NewPipe(getter_AddRefs(inStream),
getter_AddRefs(outStream), iconSize, iconSize,
aNonBlocking);
rv = EnsurePipeCreated(iconSize, aNonBlocking);
if (NS_SUCCEEDED(rv)) {
uint32_t written;
rv = outStream->Write(buffer.get(), iconSize, &written);
rv = mOutputStream->Write(buffer.get(), iconSize, &written);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*_retval = inStream);
NS_ADDREF(*_retval = mInputStream);
}
}
@ -584,13 +757,16 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval,
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
} // if we got icon info
DestroyIcon(hIcon);
DestroyIcon(aIcon);
} // if we got an hIcon
// If we didn't make a stream, then fail.
if (!*_retval && NS_SUCCEEDED(rv)) {
rv = NS_ERROR_NOT_AVAILABLE;
}
mInputStream = nullptr;
mOutputStream = nullptr;
return rv;
}
@ -728,6 +904,7 @@ nsIconChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) {
// Drop notification callbacks to prevent cycles.
mCallbacks = nullptr;
mListenerTarget = nullptr;
return NS_OK;
}

View File

@ -18,6 +18,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIURI.h"
#include "nsIInputStreamPump.h"
#include "nsIOutputStream.h"
#include "nsIStreamListener.h"
#include "nsIIconURI.h"
@ -40,6 +41,13 @@ class nsIconChannel final : public nsIChannel, public nsIStreamListener {
nsresult Init(nsIURI* uri);
protected:
class IconAsyncOpenTask;
class IconSyncOpenTask;
void OnAsyncError(nsresult aStatus);
void FinishAsyncOpen(HICON aIcon, nsresult aStatus);
nsresult EnsurePipeCreated(uint32_t aIconSize, bool aNonBlocking);
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsILoadGroup> mLoadGroup;
@ -48,14 +56,21 @@ class nsIconChannel final : public nsIChannel, public nsIStreamListener {
nsCOMPtr<nsILoadInfo> mLoadInfo;
nsCOMPtr<nsIInputStreamPump> mPump;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsIEventTarget> mListenerTarget;
nsresult ExtractIconInfoFromUrl(nsIFile** aLocalFile,
uint32_t* aDesiredImageSize,
nsCString& aContentType,
nsCString& aFileExtension);
nsresult GetHIconFromFile(HICON* hIcon);
nsresult MakeInputStream(nsIInputStream** _retval, bool nonBlocking);
nsresult GetHIcon(bool aNonBlocking, HICON* hIcon);
nsresult GetHIconFromFile(bool aNonBlocking, HICON* hIcon);
nsresult GetHIconFromFile(nsIFile* aLocalFile, const nsAutoString& aPath,
UINT aInfoFlags, HICON* hIcon);
nsresult MakeInputStream(nsIInputStream** _retval, bool aNonBlocking,
HICON aIcon);
// Functions specific to Vista and above
protected:

View File

@ -467,8 +467,15 @@ interface imgIContainer : nsISupports
*
* @param aFlags Flags of the FLAG_* variety. Only FLAG_ASYNC_NOTIFY
* is accepted; all others are ignored.
* @param aWhichFrame Frame specifier of the FRAME_* variety.
*/
[noscript] void startDecoding(in uint32_t aFlags);
[noscript] void startDecoding(in uint32_t aFlags, in uint32_t aWhichFrame);
%{C++
nsresult StartDecoding(uint32_t aFlags) {
return StartDecoding(aFlags, FRAME_CURRENT);
}
%}
/*
* Exactly like startDecoding above except returns whether the current frame
@ -476,8 +483,15 @@ interface imgIContainer : nsISupports
*
* @param aFlags Flags of the FLAG_* variety. Only FLAG_ASYNC_NOTIFY
* is accepted; all others are ignored.
* @param aWhichFrame Frame specifier of the FRAME_* variety.
*/
[noscript, notxpcom] boolean startDecodingWithResult(in uint32_t aFlags);
[noscript, notxpcom] boolean startDecodingWithResult(in uint32_t aFlags, in uint32_t aWhichFrame);
%{C++
bool StartDecodingWithResult(uint32_t aFlags) {
return StartDecodingWithResult(aFlags, FRAME_CURRENT);
}
%}
/*
* This method triggers decoding for an image, but unlike startDecoding() it
@ -485,10 +499,17 @@ interface imgIContainer : nsISupports
* request.
*
* @param aFlags Flags of the FLAG_* variety.
* @param aWhichFrame Frame specifier of the FRAME_* variety.
* @return True there is a surface that satisfies the request and it is
* fully decoded, else false.
*/
[noscript, notxpcom] boolean requestDecodeWithResult(in uint32_t aFlags);
[noscript, notxpcom] boolean requestDecodeWithResult(in uint32_t aFlags, in uint32_t aWhichFrame);
%{C++
bool RequestDecodeWithResult(uint32_t aFlags) {
return RequestDecodeWithResult(aFlags, FRAME_CURRENT);
}
%}
/*
* This method triggers decoding for an image, but unlike startDecoding() it
@ -499,9 +520,17 @@ interface imgIContainer : nsISupports
* if possible. If the image cannot be scaled to this size while
* being decoded, it will be decoded at its intrinsic size.
* @param aFlags Flags of the FLAG_* variety.
* @param aWhichFrame Frame specifier of the FRAME_* variety.
*/
[noscript] void requestDecodeForSize([const] in nsIntSize aSize,
in uint32_t aFlags);
in uint32_t aFlags,
in uint32_t aWhichFrame);
%{C++
nsresult RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
return RequestDecodeForSize(aSize, aFlags, FRAME_CURRENT);
}
%}
/**
* Increments the lock count on the image. An image will not be discarded

View File

@ -68,7 +68,6 @@ UNIFIED_SOURCES += [
'AnimationSurfaceProvider.cpp',
'ClippedImage.cpp',
'DecodedSurfaceProvider.cpp',
'DecodePool.cpp',
'Decoder.cpp',
'DecoderFactory.cpp',
'DynamicImage.cpp',
@ -102,6 +101,11 @@ UNIFIED_SOURCES += [
if CONFIG['MOZ_ENABLE_SKIA']:
UNIFIED_SOURCES += [ 'Downscaler.cpp']
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
SOURCES += [ 'DecodePool.cpp']
else:
UNIFIED_SOURCES += [ 'DecodePool.cpp']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -3533,12 +3533,7 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
// callbacks have been called:
mAutoBeforeAndAfterPrint = std::move(autoBeforeAndAfterPrint);
}
dom::Element* root = mDocument->GetRootElement();
if (root &&
root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
printJob->SetDisallowSelectionPrint(true);
}
rv = printJob->Print(aPrintSettings, aWebProgressListener);
rv = printJob->Print(mDocument, aPrintSettings, aWebProgressListener);
if (NS_FAILED(rv)) {
OnDonePrinting();
}
@ -3618,12 +3613,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
// callbacks have been called:
mAutoBeforeAndAfterPrint = std::move(autoBeforeAndAfterPrint);
}
dom::Element* root = doc->GetRootElement();
if (root &&
root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) {
PR_PL(("PrintPreview: found mozdisallowselectionprint"));
printJob->SetDisallowSelectionPrint(true);
}
rv = printJob->PrintPreview(doc, aPrintSettings, aWebProgressListener);
mPrintPreviewZoomed = false;
if (NS_FAILED(rv)) {

View File

@ -857,6 +857,17 @@ void ReflowInput::InitDynamicReflowRoot() {
canBeDynamicReflowRoot = false;
}
// Subgrids are never reflow roots, but 'contain:layout/paint' prevents
// creating a subgrid in the first place.
if (canBeDynamicReflowRoot &&
(mStylePosition->GridTemplateColumns().mIsSubgrid ||
mStylePosition->GridTemplateRows().mIsSubgrid) &&
!(mStyleDisplay->IsContainLayout() || mStyleDisplay->IsContainPaint())) {
// NOTE: we could check that 'display' of our content's primary frame is
// '[inline-]grid' here but that's probably not worth it in practice.
canBeDynamicReflowRoot = false;
}
if (canBeDynamicReflowRoot) {
mFrame->AddStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
} else {

File diff suppressed because it is too large Load Diff

View File

@ -105,6 +105,7 @@ class nsGridContainerFrame final : public nsContainerFrame {
nsReflowStatus& aStatus) override;
void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
void DidSetComputedStyle(ComputedStyle* aOldStyle) override;
nscoord GetMinISize(gfxContext* aRenderingContext) override;
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
void MarkIntrinsicISizesDirty() override;
@ -151,9 +152,8 @@ class nsGridContainerFrame final : public nsContainerFrame {
void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
nsFrameList& aFrameList) override;
void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
uint16_t CSSAlignmentForAbsPosChild(
const ReflowInput& aChildRI,
mozilla::LogicalAxis aLogicalAxis) const override;
uint16_t CSSAlignmentForAbsPosChild(const ReflowInput& aChildRI,
LogicalAxis aLogicalAxis) const override;
#ifdef DEBUG
void SetInitialChildList(ChildListID aListID,
@ -218,7 +218,7 @@ class nsGridContainerFrame final : public nsContainerFrame {
}
/** Return true if this frame is subgridded in its aAxis. */
bool IsSubgrid(mozilla::LogicalAxis aAxis) const {
bool IsSubgrid(LogicalAxis aAxis) const {
return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock
? NS_STATE_GRID_IS_ROW_SUBGRID
: NS_STATE_GRID_IS_COL_SUBGRID);
@ -232,7 +232,7 @@ class nsGridContainerFrame final : public nsContainerFrame {
}
/** Return true if this frame has an item that is subgridded in our aAxis. */
bool HasSubgridItems(mozilla::LogicalAxis aAxis) const {
bool HasSubgridItems(LogicalAxis aAxis) const {
return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock
? NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM
: NS_STATE_GRID_HAS_COL_SUBGRID_ITEM);
@ -257,6 +257,8 @@ class nsGridContainerFrame final : public nsContainerFrame {
MOZ_CAN_RUN_SCRIPT_BOUNDARY
static nsGridContainerFrame* GetGridFrameWithComputedInfo(nsIFrame* aFrame);
struct Subgrid;
struct UsedTrackSizes;
struct TrackSize;
struct GridItemInfo;
struct GridReflowInput;
@ -267,6 +269,9 @@ class nsGridContainerFrame final : public nsContainerFrame {
bool mIsInEdgeTrack;
};
/** Return our parent grid container; |this| MUST be a subgrid. */
nsGridContainerFrame* ParentGridContainerForSubgrid() const;
protected:
static const uint32_t kAutoLine;
// The maximum line number, in the zero-based translated grid.
@ -286,6 +291,7 @@ class nsGridContainerFrame final : public nsContainerFrame {
class LineNameMap;
struct LineRange;
struct SharedGridData;
struct SubgridFallbackTrackSizingFunctions;
struct TrackSizingFunctions;
struct Tracks;
struct TranslatedLineRange;
@ -313,6 +319,8 @@ class nsGridContainerFrame final : public nsContainerFrame {
void AddImplicitNamedAreas(
const nsTArray<nsTArray<nsString>>& aLineNameLists);
void NormalizeChildLists();
/**
* Reflow and place our children.
* @return the consumed size of all of this grid container's continuations
@ -376,8 +384,7 @@ class nsGridContainerFrame final : public nsContainerFrame {
* Synthesize a Grid container baseline for aGroup.
*/
nscoord SynthesizeBaseline(const FindItemInGridOrderResult& aItem,
mozilla::LogicalAxis aAxis,
BaselineSharingGroup aGroup,
LogicalAxis aAxis, BaselineSharingGroup aGroup,
const nsSize& aCBPhysicalSize, nscoord aCBSize,
WritingMode aCBWM);
/**
@ -408,6 +415,19 @@ class nsGridContainerFrame final : public nsContainerFrame {
void SanityCheckGridItemsBeforeReflow() const;
#endif // DEBUG
/**
* Update our NS_STATE_GRID_IS_COL/ROW_SUBGRID bits and related subgrid state
* on our entire continuation chain based on the current style.
* This is needed because grid-template-columns/rows style changes only
* trigger a reflow so we need to update this dynamically.
*/
void UpdateSubgridFrameState();
/**
* Return the NS_STATE_GRID_IS_COL/ROW_SUBGRID bits we ought to have.
*/
nsFrameState ComputeSelfSubgridBits() const;
private:
// Helpers for ReflowChildren
struct Fragmentainer {
@ -463,6 +483,13 @@ class nsGridContainerFrame final : public nsContainerFrame {
const LogicalRect& aContentArea,
ReflowOutput& aDesiredSize, nsReflowStatus& aStatus);
// Return the stored UsedTrackSizes, if any.
UsedTrackSizes* GetUsedTrackSizes() const;
// Store the given TrackSizes in aAxis on a UsedTrackSizes frame property.
void StoreUsedTrackSizes(LogicalAxis aAxis,
const nsTArray<TrackSize>& aSizes);
/**
* Cached values to optimize GetMinISize/GetPrefISize.
*/

View File

@ -411,6 +411,52 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1508420
gridContainer.remove(); // clean up
}
let gridSubgridSubtests = [
{ desc: "subgrid",
candStyle: "grid: subgrid / subgrid",
},
{ desc: "subgrid-rows",
candStyle: "grid: subgrid / 20px",
},
{ desc: "subgrid-columns",
candStyle: "grid: 20px / subgrid",
},
];
// Test that a subgrid is not a reflow root.
function runGridSubgridSubtest(subtest) {
// We create a 4x4 grid container a with one grid item:
// - a reflow root display:grid that we'll style as a subgrid from
// the list above. We place an item inside it that we'll tweak
// the size of, which should affect the outer grid track sizes.
let gridContainer = createStyledDiv("display: grid; \
width: 100px; \
height: 100px; \
grid: 1fr auto / 1fr auto; \
border: 2px solid teal");
// The reflow root candidate
let cand = createStyledDiv(gReflowRootCandidateStyles +
"display: grid;" +
"grid-area: 2/2;" +
"background: blue;" +
"min-width: 10px; min-height: 10px;" +
subtest.candStyle);
// Something whose size we can adjust, inside the subgrid:
let inner = createStyledDiv("height:20px; width:20px;");
cand.appendChild(inner);
gridContainer.appendChild(cand);
gFBody.appendChild(gridContainer);
let tweakFunc = function() {
inner.style.width = inner.style.height = "40px";
};
tweakAndCompareSnapshots(tweakFunc, subtest.desc);
gridContainer.remove(); // clean up
}
let tableSubtests = [
{ desc: "table",
/* Testing the default "display:table" styling that runTableTest uses: */
@ -711,6 +757,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1508420
for (let subtest of gridContainerSubtests) {
runGridContainerSubtest(subtest);
}
if (SpecialPowers.getBoolPref("layout.css.grid-template-subgrid-value.enabled")) {
for (let subtest of gridSubgridSubtests) {
runGridSubgridSubtest(subtest);
}
}
for (let subtest of gridItemSubtests) {
runGridItemSubtest(subtest);
}

View File

@ -498,6 +498,37 @@ static nsresult EnsureSettingsHasPrinterNameSet(
#endif
}
static bool DocHasPrintCallbackCanvas(Document* aDoc, void* aData) {
if (!aDoc) {
return true;
}
Element* root = aDoc->GetRootElement();
if (!root) {
return true;
}
RefPtr<nsContentList> canvases =
NS_GetContentList(root, kNameSpaceID_XHTML, NS_LITERAL_STRING("canvas"));
uint32_t canvasCount = canvases->Length(true);
for (uint32_t i = 0; i < canvasCount; ++i) {
HTMLCanvasElement* canvas =
HTMLCanvasElement::FromNodeOrNull(canvases->Item(i, false));
if (canvas && canvas->GetMozPrintCallback()) {
// This subdocument has a print callback. Set result and return false to
// stop iteration.
*static_cast<bool*>(aData) = true;
return false;
}
}
return true;
}
static bool AnySubdocHasPrintCallbackCanvas(Document* aDoc) {
bool result = false;
aDoc->EnumerateSubDocuments(&DocHasPrintCallbackCanvas,
static_cast<void*>(&result));
return result;
}
//-------------------------------------------------------
NS_IMPL_ISUPPORTS(nsPrintJob, nsIWebProgressListener, nsISupportsWeakReference,
@ -550,6 +581,28 @@ nsresult nsPrintJob::Initialize(nsIDocumentViewerPrint* aDocViewerPrint,
// here instead.
mOriginalDoc = aOriginalDoc;
// Anything state that we need from aOriginalDoc must be fetched and stored
// here, since the document that the user selected to print may mutate
// across consecutive PrintPreview() calls.
Element* root = aOriginalDoc->GetRootElement();
mDisallowSelectionPrint =
root &&
root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint);
nsCOMPtr<nsIDocShellTreeOwner> owner;
aDocShell->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(owner);
if (browserChrome) {
browserChrome->IsWindowModal(&mIsForModalWindow);
}
bool hasMozPrintCallback = false;
DocHasPrintCallbackCanvas(aOriginalDoc,
static_cast<void*>(&hasMozPrintCallback));
mHasMozPrintCallback =
hasMozPrintCallback || AnySubdocHasPrintCallbackCanvas(aOriginalDoc);
return NS_OK;
}
@ -1033,14 +1086,15 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
}
//---------------------------------------------------------------------------------
nsresult nsPrintJob::Print(nsIPrintSettings* aPrintSettings,
nsresult nsPrintJob::Print(Document* aSourceDoc,
nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener) {
// If we have a print preview document, use that instead of the original
// mDocument. That way animated images etc. get printed using the same state
// as in print preview.
Document* doc = mPrtPreview && mPrtPreview->mPrintObject
? mPrtPreview->mPrintObject->mDocument
: mOriginalDoc;
? mPrtPreview->mPrintObject->mDocument.get()
: aSourceDoc;
return CommonPrint(false, aPrintSettings, aWebProgressListener, doc);
}
@ -1214,23 +1268,15 @@ void nsPrintJob::ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify) {
nsCOMPtr<nsIPrintingPromptService> printPromptService(
do_GetService(kPrintingPromptService));
if (printPromptService) {
nsPIDOMWindowOuter* domWin = mOriginalDoc->GetWindow();
if (!domWin) return;
nsCOMPtr<nsIDocShell> docShell = domWin->GetDocShell();
if (!docShell) return;
nsCOMPtr<nsIDocShellTreeOwner> owner;
docShell->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(owner);
if (!browserChrome) return;
bool isModal = true;
browserChrome->IsWindowModal(&isModal);
if (isModal) {
if (mIsForModalWindow) {
// Showing a print progress dialog when printing a modal window
// isn't supported. See bug 301560.
return;
}
nsPIDOMWindowOuter* domWin = mOriginalDoc->GetWindow();
if (!domWin) return;
nsCOMPtr<nsIWebProgressListener> printProgressListener;
nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint));
@ -2579,53 +2625,6 @@ void nsPrintJob::EllipseLongString(nsAString& aStr, const uint32_t aLen,
}
}
static bool DocHasPrintCallbackCanvas(Document* aDoc, void* aData) {
if (!aDoc) {
return true;
}
Element* root = aDoc->GetRootElement();
if (!root) {
return true;
}
RefPtr<nsContentList> canvases =
NS_GetContentList(root, kNameSpaceID_XHTML, NS_LITERAL_STRING("canvas"));
uint32_t canvasCount = canvases->Length(true);
for (uint32_t i = 0; i < canvasCount; ++i) {
HTMLCanvasElement* canvas =
HTMLCanvasElement::FromNodeOrNull(canvases->Item(i, false));
if (canvas && canvas->GetMozPrintCallback()) {
// This subdocument has a print callback. Set result and return false to
// stop iteration.
*static_cast<bool*>(aData) = true;
return false;
}
}
return true;
}
static bool DocHasPrintCallbackCanvas(Document* aDoc) {
bool result = false;
aDoc->EnumerateSubDocuments(&DocHasPrintCallbackCanvas,
static_cast<void*>(&result));
return result;
}
/**
* Checks to see if the document this print engine is associated with has any
* canvases that have a mozPrintCallback.
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement#Properties
*/
bool nsPrintJob::HasPrintCallbackCanvas() {
if (!mOriginalDoc) {
return false;
}
// First check this mOriginalDoc.
bool result = false;
DocHasPrintCallbackCanvas(mOriginalDoc, static_cast<void*>(&result));
// Also check the sub documents.
return result || DocHasPrintCallbackCanvas(mOriginalDoc);
}
//-------------------------------------------------------
bool nsPrintJob::PrePrintPage() {
NS_ASSERTION(mPageSeqFrame.IsAlive(), "mPageSeqFrame is not alive!");

View File

@ -93,7 +93,8 @@ class nsPrintJob final : public nsIObserver,
* May be called immediately after initialization, or after one or more
* PrintPreview calls.
*/
nsresult Print(nsIPrintSettings* aPrintSettings,
nsresult Print(mozilla::dom::Document* aSourceDoc,
nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener);
/**
@ -158,8 +159,14 @@ class nsPrintJob final : public nsIObserver,
*/
void SuppressPrintPreviewUserEvents();
// nsIDocumentViewerPrint Printing Methods
bool HasPrintCallbackCanvas();
// nsIDocumentViewerPrint Printing Methods:
/**
* Checks to see if the document this print engine is associated with has any
* canvases that have a mozPrintCallback.
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement#Properties
*/
bool HasPrintCallbackCanvas() { return mHasMozPrintCallback; }
bool PrePrintPage();
bool PrintPage(nsPrintObject* aPOect, bool& aInRange);
bool DonePrintingPages(nsPrintObject* aPO, nsresult aResult);
@ -226,10 +233,6 @@ class nsPrintJob final : public nsIObserver,
bool GetIsPrintPreview() { return mIsDoingPrintPreview; }
bool GetIsCreatingPrintPreview() { return mIsCreatingPrintPreview; }
void SetDisallowSelectionPrint(bool aDisallowSelectionPrint) {
mDisallowSelectionPrint = aDisallowSelectionPrint;
}
private:
nsPrintJob& operator=(const nsPrintJob& aOther) = delete;
@ -308,6 +311,8 @@ class nsPrintJob final : public nsIObserver,
bool mDidLoadDataForPrinting = false;
bool mIsDestroying = false;
bool mDisallowSelectionPrint = false;
bool mIsForModalWindow = false;
bool mHasMozPrintCallback = false;
};
#endif // nsPrintJob_h

View File

@ -1191,11 +1191,17 @@ VARCACHE_PREF(
)
// Is support for CSS "grid-template-{columns,rows}: subgrid X" enabled?
#ifdef NIGHTLY_BUILD
# define PREF_VALUE true
#else
# define PREF_VALUE false
#endif
VARCACHE_PREF(
"layout.css.grid-template-subgrid-value.enabled",
layout_css_grid_template_subgrid_value_enabled,
bool, false
bool, PREF_VALUE
)
#undef PREF_VALUE
// Pref to control whether line-height: -moz-block-height is exposed to content.
VARCACHE_PREF(

View File

@ -53,10 +53,8 @@ Communication
The mailing list for Firefox remote debugging discussion is
`dev-remote@lists.mozilla.org`_ (`subscribe`_, `archive`_).
If you prefer real-time chat, there is often someone in the *#remote*
IRC channel on irc.mozilla.org. Dont ask if you may ask a
question just go ahead and ask, and please wait for an answer as
we might not be in your timezone.
If you prefer real-time chat, there is often someone in the *#remote* channel
on the <a href=https://devtools-html.slack.com/>DevTools Slack</a> instance.
.. _dev-remote@lists.mozilla.org: mailto:dev-remote@lists.mozilla.org
.. _subscribe: https://lists.mozilla.org/listinfo/dev-remote

View File

@ -0,0 +1,45 @@
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>CSS-contain test: layout/paint containment on subgrid</title>
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
<meta name=assert content="layout/paint containment inhibits subgrid">
<link rel="match" href="reference/contain-subgrid-001.html">
<link rel=help href="https://drafts.csswg.org/css-contain/#containment-layout">
<link rel=help href="https://drafts.csswg.org/css-contain/#containment-paint">
<link rel=help href="https://drafts.csswg.org/css-grid-2/">
<style>
.grid {
display: grid;
width: 40px;
height: 40px;
grid: [a] repeat(2,15px) [b] / [a] repeat(2,15px) [b];
gap: 10px;
}
.subgrid {
display: grid;
grid: subgrid;
background: lightgrey;
grid-area:1/1/3/3;
}
.layout { contain: layout; }
.paint { contain: paint; }
.inner {
background: blue;
grid-area:a/a/b/b;
}
.p {
place-self: start;
width:100%;
height:100%;
}
</style>
<div class="grid"><div class="subgrid layout"><div class="inner"></div></div></div>
<div class="grid"><div class="subgrid paint"><div class="inner"></div></div></div>
<div class="grid"><div class="subgrid layout"><div class="inner p"></div></div></div>
<div class="grid"><div class="subgrid paint"><div class="inner p"></div></div></div>

View File

@ -0,0 +1,35 @@
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>CSS-contain reference: layout/paint containment on subgrid</title>
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
<style>
.grid {
display: grid;
width: 40px;
height: 40px;
grid: [a] repeat(2,15px) [b] / [a] repeat(2,15px) [b];
gap: 10px;
}
.subgrid {
display: grid;
grid: none;
background: lightgrey;
grid-area:1/1/3/3;
}
.layout { contain: layout; }
.paint { contain: paint; }
.inner {
background: blue;
grid-area:a/a/b/b;
}
</style>
<div class="grid"><div class="subgrid layout"><div class="inner"></div></div></div>
<div class="grid"><div class="subgrid paint"><div class="inner"></div></div></div>
<div class="grid"><div class="subgrid layout"><div class="inner"></div></div></div>
<div class="grid"><div class="subgrid paint"><div class="inner"></div></div></div>

View File

@ -7,4 +7,4 @@ support-files =
tags=searchconfig searchconfig1
[include:xpcshell-common.ini]
skip-if = toolkit == 'android'
skip-if = toolkit == 'android' || appname == "thunderbird"

View File

@ -7,4 +7,4 @@ support-files =
tags=searchconfig searchconfig2
[include:xpcshell-common.ini]
skip-if = toolkit == 'android'
skip-if = toolkit == 'android' || appname == "thunderbird"

View File

@ -7,4 +7,4 @@ support-files =
tags=searchconfig searchconfig3
[include:xpcshell-common.ini]
skip-if = toolkit == 'android'
skip-if = toolkit == 'android' || appname == "thunderbird"

View File

@ -7,4 +7,4 @@ support-files =
tags=searchconfig searchconfig4
[include:xpcshell-common.ini]
skip-if = toolkit == 'android'
skip-if = toolkit == 'android' || appname == "thunderbird"

View File

@ -21,8 +21,7 @@ requesttimeoutfactor = 3
[test_ebay.js]
# This is an extensive test and currently takes a long time. Therefore skip on
# debug/asan and extend the timeout length otherwise.
# Thunderbird doesn't provide eBay search engines.
skip-if = debug || asan || appname == "thunderbird"
skip-if = debug || asan
requesttimeoutfactor = 3
[test_google.js]
# This is an extensive test and currently takes a long time. Therefore skip on

View File

@ -37,7 +37,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=348233
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.expectAssertions(14, 38);
SimpleTest.expectAssertions(14, 52);
/** Test for Bug 437844 and Bug 348233 **/
SimpleTest.waitForExplicitFinish();