/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class ImageListener : public MediaDocumentStreamListener { public: // NS_DECL_NSIREQUESTOBSERVER // We only implement OnStartRequest; OnStopRequest is // implemented by MediaDocumentStreamListener
NS_IMETHOD OnStartRequest(nsIRequest* aRequest) override;
// This is an image being loaded as a document, so it's not going to be // detected by the ImageBlocker. However we don't want to call // NS_CheckContentLoadPolicy (with an TYPE_INTERNAL_IMAGE) here, as it would // e.g. make this image load be detectable by CSP.
nsCOMPtr<nsIURI> channelURI;
channel->GetURI(getter_AddRefs(channelURI)); if (image::ImageBlocker::ShouldBlock(channelURI)) {
request->Cancel(NS_ERROR_CONTENT_BLOCKED); return NS_OK;
}
if (BrowsingContext* context = GetBrowsingContext()) {
mIsInObjectOrEmbed = context->IsEmbedderTypeObjectOrEmbed();
}
NS_ASSERTION(aDocListener, "null aDocListener");
*aDocListener = new ImageListener(this);
NS_ADDREF(*aDocListener);
return NS_OK;
}
void ImageDocument::Destroy() { if (RefPtr<HTMLImageElement> img = std::move(mImageContent)) { // Remove our event listener from the image content.
img->RemoveEventListener(u"load"_ns, this, false);
img->RemoveEventListener(u"click"_ns, this, false);
// Break reference cycle with mImageContent, if we have one if (mObservingImageLoader) {
img->RemoveNativeObserver(this);
}
}
MediaDocument::Destroy();
}
void ImageDocument::SetScriptGlobalObject(
nsIScriptGlobalObject* aScriptGlobalObject) { // If the script global object is changing, we need to unhook our event // listeners on the window.
nsCOMPtr<EventTarget> target; if (mScriptGlobalObject && aScriptGlobalObject != mScriptGlobalObject) {
target = do_QueryInterface(mScriptGlobalObject);
target->RemoveEventListener(u"resize"_ns, this, false);
target->RemoveEventListener(u"keypress"_ns, this, false);
}
// Set the script global object on the superclass before doing // anything that might require it....
MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
if (aScriptGlobalObject) { if (!InitialSetupHasBeenDone()) {
MOZ_ASSERT(!GetRootElement(), "Where did the root element come from?"); // Create synthetic document #ifdef DEBUG
nsresult rv = #endif
CreateSyntheticDocument();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
void ImageDocument::ShrinkToFit() { if (!mImageContent) { return;
} if (GetZoomLevel() != mOriginalZoomLevel && mImageIsResized &&
!nsContentUtils::IsChildOfSameType(this)) { // If we're zoomed, so that we don't maintain the invariant that // mImageIsResized if and only if its displayed width/height fit in // mVisibleWidth/mVisibleHeight, then we may need to switch to/from the // overflowingVertical class here, because our viewport size may have // changed and we don't plan to adjust the image size to compensate. Since // mImageIsResized it has a "height" attribute set, and we can just get the // displayed image height by getting .height on the HTMLImageElement. // // Hold strong ref, because Height() can run script.
RefPtr<HTMLImageElement> img = mImageContent;
uint32_t imageHeight = img->Height();
nsDOMTokenList* classList = img->ClassList(); if (imageHeight > mVisibleHeight) {
classList->Add(u"overflowingVertical"_ns, IgnoreErrors());
} else {
classList->Remove(u"overflowingVertical"_ns, IgnoreErrors());
} return;
} if (GetResolution() != mOriginalResolution && mImageIsResized) { // Don't resize if resolution has changed, e.g., through pinch-zooming on // Android. return;
}
// Keep image content alive while changing the attributes.
RefPtr<HTMLImageElement> image = mImageContent;
// The view might have been scrolled when zooming in, scroll back to the // origin now that we're showing a shrunk-to-window version.
ScrollImageTo(0, 0);
// Run this using a script runner because HAS_TRANSPARENCY notifications can // come during painting and this will trigger invalidation. if (aType == imgINotificationObserver::HAS_TRANSPARENCY) {
nsCOMPtr<nsIRunnable> runnable =
NewRunnableMethod("dom::ImageDocument::OnHasTransparency", this,
&ImageDocument::OnHasTransparency);
nsContentUtils::AddScriptRunner(runnable);
}
// Styles have not yet been applied, so we don't know the final size. For now, // default to the image's intrinsic size.
aImage->GetWidth(&mImageWidth);
aImage->GetHeight(&mImageHeight);
// Multipart images send size available for each part; ignore them if it // doesn't change our size. (We may not even support changing size in // multipart images in the future.) if (oldWidth == mImageWidth && oldHeight == mImageHeight) { return;
}
// mImageContent can be null if the document is already destroyed if (NS_FAILED(aStatus) && mImageContent) {
nsAutoCString src;
mDocumentURI->GetSpec(src);
AutoTArray<nsString, 1> formatString;
CopyUTF8toUTF16(src, *formatString.AppendElement());
nsAutoString errorMsg;
FormatStringFromName("InvalidImage", formatString, errorMsg);
void ImageDocument::UpdateSizeFromLayout() { // Pull an updated size from the content frame to account for any size // change due to CSS properties like |image-orientation|. if (!mImageContent) { return;
}
// Need strong ref, because GetPrimaryFrame can run script.
RefPtr<HTMLImageElement> imageContent = mImageContent;
nsIFrame* contentFrame = imageContent->GetPrimaryFrame(FlushType::Frames); if (!contentFrame) { return;
}
if (newSize.width) {
mImageWidth = nsPresContext::AppUnitsToFloatCSSPixels(*newSize.width);
} if (newSize.height) {
mImageHeight = nsPresContext::AppUnitsToFloatCSSPixels(*newSize.height);
}
// Ensure that our information about overflow is up-to-date if needed. if (mImageWidth != oldSize.width || mImageHeight != oldSize.height) {
CheckOverflowing(false);
}
}
void ImageDocument::UpdateRemoteStyle(StyleImageRendering aImageRendering) { if (!mImageContent) { return;
}
// Using ScriptRunner to avoid doing DOM mutation at an unexpected time. if (!nsContentUtils::IsSafeToRunScript()) { return nsContentUtils::AddScriptRunner(
NewRunnableMethod<StyleImageRendering>( "UpdateRemoteStyle", this, &ImageDocument::UpdateRemoteStyle,
aImageRendering));
}
nsCOMPtr<nsICSSDeclaration> style = mImageContent->Style(); switch (aImageRendering) { case StyleImageRendering::Auto: case StyleImageRendering::Smooth: case StyleImageRendering::Optimizequality:
style->SetProperty("image-rendering"_ns, "auto"_ns, ""_ns,
IgnoreErrors()); break; case StyleImageRendering::Optimizespeed: case StyleImageRendering::Pixelated:
style->SetProperty("image-rendering"_ns, "pixelated"_ns, ""_ns,
IgnoreErrors()); break; case StyleImageRendering::CrispEdges:
style->SetProperty("image-rendering"_ns, "crisp-edges"_ns, ""_ns,
IgnoreErrors()); break;
}
}
nsresult ImageDocument::CreateSyntheticDocument() { // Synthesize an html document that refers to the image
nsresult rv = MediaDocument::CreateSyntheticDocument();
NS_ENSURE_SUCCESS(rv, rv);
// Add the image element
RefPtr<Element> body = GetBodyElement(); if (!body) {
NS_WARNING("no body on image document!"); return NS_ERROR_FAILURE;
}
NS_ConvertUTF8toUTF16 srcString(src); // Make sure not to start the image load from here...
mImageContent->SetLoadingEnabled(false);
mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::src, srcString, false);
mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::alt, srcString, false);
if (mIsInObjectOrEmbed) {
SetModeClass(eIsInObjectOrEmbed);
}
void ImageDocument::ResetZoomLevel() { if (nsContentUtils::IsChildOfSameType(this)) { return;
}
if (RefPtr<BrowsingContext> bc = GetBrowsingContext()) { // Resetting the zoom level on a discarded browsing context has no effect.
Unused << bc->SetFullZoom(mOriginalZoomLevel);
}
}
float ImageDocument::GetZoomLevel() { if (BrowsingContext* bc = GetBrowsingContext()) { return bc->FullZoom();
} return mOriginalZoomLevel;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.