mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 16:22:00 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
bdf94edb89
@ -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");
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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...
|
||||
|
@ -8,4 +8,8 @@ SOURCES += [
|
||||
'nsIconChannel.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/image',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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)) {
|
||||
|
@ -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
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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!");
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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. Don’t 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
|
||||
|
@ -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>
|
@ -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>
|
@ -7,4 +7,4 @@ support-files =
|
||||
tags=searchconfig searchconfig1
|
||||
|
||||
[include:xpcshell-common.ini]
|
||||
skip-if = toolkit == 'android'
|
||||
skip-if = toolkit == 'android' || appname == "thunderbird"
|
||||
|
@ -7,4 +7,4 @@ support-files =
|
||||
tags=searchconfig searchconfig2
|
||||
|
||||
[include:xpcshell-common.ini]
|
||||
skip-if = toolkit == 'android'
|
||||
skip-if = toolkit == 'android' || appname == "thunderbird"
|
||||
|
@ -7,4 +7,4 @@ support-files =
|
||||
tags=searchconfig searchconfig3
|
||||
|
||||
[include:xpcshell-common.ini]
|
||||
skip-if = toolkit == 'android'
|
||||
skip-if = toolkit == 'android' || appname == "thunderbird"
|
||||
|
@ -7,4 +7,4 @@ support-files =
|
||||
tags=searchconfig searchconfig4
|
||||
|
||||
[include:xpcshell-common.ini]
|
||||
skip-if = toolkit == 'android'
|
||||
skip-if = toolkit == 'android' || appname == "thunderbird"
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user