/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights
 * reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "third_party/blink/renderer/core/loader/image_loader.h"

#include <memory>
#include <utility>

#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_client_hints_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/increment_load_event_delay_count.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame_owner.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_video.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
#include "third_party/blink/renderer/core/loader/importance_attribute.h"
#include "third_party/blink/renderer/core/loader/lazy_image_helper.h"
#include "third_party/blink/renderer/core/probe/async_task_id.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"

namespace blink {

namespace {

bool CheckForUnoptimizedImagePolicy(const Document& document,
                                    ImageResourceContent* new_image) {
  if (!new_image)
    return false;

  // Render the image as a placeholder image if the image is not sufficiently
  // well-compressed, according to the unoptimized image feature policies on
  // |document|.
  if (RuntimeEnabledFeatures::UnoptimizedImagePoliciesEnabled(&document) &&
      !new_image->IsAcceptableCompressionRatio(
          *document.ToExecutionContext())) {
    return true;
  }

  return false;
}

}  // namespace

static ImageLoader::BypassMainWorldBehavior ShouldBypassMainWorldCSP(
    ImageLoader* loader) {
  DCHECK(loader);
  DCHECK(loader->GetElement());
  if (ContentSecurityPolicy::ShouldBypassMainWorld(
          loader->GetElement()->GetDocument().ToExecutionContext())) {
    return ImageLoader::kBypassMainWorldCSP;
  }
  return ImageLoader::kDoNotBypassMainWorldCSP;
}

class ImageLoader::Task {
 public:
  Task(ImageLoader* loader,
       const KURL& request_url,
       UpdateFromElementBehavior update_behavior,
       network::mojom::ReferrerPolicy referrer_policy)
      : loader_(loader),
        should_bypass_main_world_csp_(ShouldBypassMainWorldCSP(loader)),
        update_behavior_(update_behavior),
        referrer_policy_(referrer_policy),
        request_url_(request_url) {
    ExecutionContext* context =
        loader_->GetElement()->GetDocument().ToExecutionContext();
    probe::AsyncTaskScheduled(context, "Image", &async_task_id_);
    v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
    v8::HandleScope scope(isolate);
    // If we're invoked from C++ without a V8 context on the stack, we should
    // run the microtask in the context of the element's document's main world.
    if (!isolate->GetCurrentContext().IsEmpty()) {
      script_state_ = ScriptState::Current(isolate);
    } else {
      script_state_ = ToScriptStateForMainWorld(
          loader->GetElement()->GetDocument().GetFrame());
      DCHECK(script_state_);
    }
  }

  void Run() {
    if (!loader_)
      return;
    ExecutionContext* context =
        loader_->GetElement()->GetDocument().ToExecutionContext();
    probe::AsyncTask async_task(context, &async_task_id_);
    if (script_state_ && script_state_->ContextIsValid()) {
      ScriptState::Scope scope(script_state_);
      loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
                                   update_behavior_, request_url_,
                                   referrer_policy_);
    } else {
      // This call does not access v8::Context internally.
      loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
                                   update_behavior_, request_url_,
                                   referrer_policy_);
    }
  }

  void ClearLoader() {
    loader_ = nullptr;
    script_state_ = nullptr;
  }

  base::WeakPtr<Task> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }

 private:
  WeakPersistent<ImageLoader> loader_;
  BypassMainWorldBehavior should_bypass_main_world_csp_;
  UpdateFromElementBehavior update_behavior_;
  WeakPersistent<ScriptState> script_state_;
  network::mojom::ReferrerPolicy referrer_policy_;
  KURL request_url_;
  probe::AsyncTaskId async_task_id_;
  base::WeakPtrFactory<Task> weak_factory_{this};
};

ImageLoader::ImageLoader(Element* element)
    : element_(element),
      image_complete_(true),
      suppress_error_events_(false),
      was_fully_deferred_(false),
      lazy_image_load_state_(LazyImageLoadState::kNone) {
  RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this;
}

ImageLoader::~ImageLoader() = default;

void ImageLoader::Dispose() {
  RESOURCE_LOADING_DVLOG(1)
      << "~ImageLoader " << this
      << "; has pending load event=" << pending_load_event_.IsActive()
      << ", has pending error event=" << pending_error_event_.IsActive();

  if (image_content_) {
    image_content_->RemoveObserver(this);
    image_content_ = nullptr;
    image_content_for_image_document_ = nullptr;
    delay_until_image_notify_finished_ = nullptr;
  }
}

void ImageLoader::DispatchDecodeRequestsIfComplete() {
  // If the current image isn't complete, then we can't dispatch any decodes.
  // This function will be called again when the current image completes.
  if (!image_complete_)
    return;

  bool is_active = GetElement()->GetDocument().IsActive();
  // If any of the following conditions hold, we either have an inactive
  // document or a broken/non-existent image. In those cases, we reject any
  // pending decodes.
  if (!is_active || !GetContent() || GetContent()->ErrorOccurred()) {
    RejectPendingDecodes();
    return;
  }

  LocalFrame* frame = GetElement()->GetDocument().GetFrame();
  for (auto& request : decode_requests_) {
    // If the image already in kDispatched state or still in kPEndingMicrotask
    // state, then we don't dispatch decodes for it. So, the only case to handle
    // is if we're in kPendingLoad state.
    if (request->state() != DecodeRequest::kPendingLoad)
      continue;
    Image* image = GetContent()->GetImage();

    // ImageLoader should be kept alive when decode is still pending. JS may
    // invoke 'decode' without capturing the Image object. If GC kicks in,
    // ImageLoader will be destroyed, leading to unresolved/unrejected Promise.
    frame->GetChromeClient().RequestDecode(
        frame, image->PaintImageForCurrentFrame(),
        WTF::Bind(&ImageLoader::DecodeRequestFinished,
                  WrapCrossThreadPersistent(this), request->request_id()));
    request->NotifyDecodeDispatched();
  }
}

void ImageLoader::DecodeRequestFinished(uint64_t request_id, bool success) {
  // First we find the corresponding request id, then we either resolve or
  // reject it and remove it from the list.
  for (auto* it = decode_requests_.begin(); it != decode_requests_.end();
       ++it) {
    auto& request = *it;
    if (request->request_id() != request_id)
      continue;

    if (success)
      request->Resolve();
    else
      request->Reject();
    decode_requests_.erase(it);
    break;
  }
}

void ImageLoader::RejectPendingDecodes(UpdateType update_type) {
  // Normally, we only reject pending decodes that have passed the
  // kPendingMicrotask state, since pending mutation requests still have an
  // outstanding microtask that will run and might act on a different image than
  // the current one. However, as an optimization, there are cases where we
  // synchronously update the image (see UpdateFromElement). In those cases, we
  // have to reject even the pending mutation requests because conceptually they
  // would have been scheduled before the synchronous update ran, so they
  // referred to the old image.
  for (auto* it = decode_requests_.begin(); it != decode_requests_.end();) {
    auto& request = *it;
    if (update_type == UpdateType::kAsync &&
        request->state() == DecodeRequest::kPendingMicrotask) {
      ++it;
      continue;
    }
    request->Reject();
    it = decode_requests_.erase(it);
  }
}

void ImageLoader::Trace(Visitor* visitor) {
  visitor->Trace(image_content_);
  visitor->Trace(image_content_for_image_document_);
  visitor->Trace(element_);
  visitor->Trace(decode_requests_);
}

void ImageLoader::SetImageForTest(ImageResourceContent* new_image) {
  DCHECK(new_image);
  SetImageWithoutConsideringPendingLoadEvent(new_image);
}

bool ImageLoader::ShouldUpdateOnInsertedInto(
    ContainerNode& insertion_point,
    network::mojom::ReferrerPolicy referrer_policy) const {
  // If we're being inserted into a disconnected tree, we don't need to update.
  if (!insertion_point.isConnected())
    return false;

  // If the base element URL changed, it means that we might be in the process
  // of fetching a wrong image. We should update to ensure we fetch the correct
  // image. This can happen when inserting content into an iframe which has a
  // base element. See crbug.com/897545 for more details.
  if (element_->GetDocument().ValidBaseElementURL() != last_base_element_url_)
    return true;

  // If we already have image content, then we don't need an update.
  if (image_content_)
    return false;

  // Finally, try to update if we're idle. This could be an indication that we
  // skipped a previous load when inserted into an inactive document. Note that
  // if we're not idle, we should also update our referrer policy if it has
  // changed.
  return !HasPendingActivity() || referrer_policy != last_referrer_policy_;
}

bool ImageLoader::ImageIsPotentiallyAvailable() const {
  bool image_has_loaded = image_content_ && !image_content_->IsLoading() &&
                          !image_content_->ErrorOccurred();
  bool image_still_loading = !image_has_loaded && HasPendingActivity() &&
                             !HasPendingError() &&
                             !element_->ImageSourceURL().IsEmpty();
  bool image_has_image = image_content_ && image_content_->HasImage();
  bool image_is_document = element_->GetDocument().IsImageDocument() &&
                           image_content_ && !image_content_->ErrorOccurred();

  // Icky special case for deferred images:
  // A deferred image is not loading, does have pending activity, does not
  // have an error, but it does have an ImageResourceContent associated
  // with it, so |image_has_loaded| will be true even though the image hasn't
  // actually loaded. Fixing the definition of |image_has_loaded| isn't
  // sufficient, because a deferred image does have pending activity, does not
  // have a pending error, and does have a source URL, so if |image_has_loaded|
  // was correct, |image_still_loading| would become wrong.
  //
  // Instead of dealing with that, there's a separate check that the
  // ImageResourceContent has non-null image data associated with it, which
  // isn't folded into |image_has_loaded| above.
  return (image_has_loaded && image_has_image) || image_still_loading ||
         image_is_document;
}

void ImageLoader::ClearImage() {
  SetImageWithoutConsideringPendingLoadEvent(nullptr);
}

void ImageLoader::SetImageWithoutConsideringPendingLoadEvent(
    ImageResourceContent* new_image_content) {
  DCHECK(failed_load_url_.IsEmpty());
  ImageResourceContent* old_image_content = image_content_.Get();
  if (new_image_content != old_image_content) {
    if (pending_load_event_.IsActive())
      pending_load_event_.Cancel();
    if (pending_error_event_.IsActive())
      pending_error_event_.Cancel();
    UpdateImageState(new_image_content);
    if (new_image_content) {
      new_image_content->AddObserver(this);
    }
    if (old_image_content) {
      old_image_content->RemoveObserver(this);
    }
  }

  if (LayoutImageResource* image_resource = GetLayoutImageResource())
    image_resource->ResetAnimation();
}

static void ConfigureRequest(
    FetchParameters& params,
    ImageLoader::BypassMainWorldBehavior bypass_behavior,
    Element& element,
    const ClientHintsPreferences& client_hints_preferences) {
  if (bypass_behavior == ImageLoader::kBypassMainWorldCSP) {
    params.SetContentSecurityCheck(
        network::mojom::CSPDisposition::DO_NOT_CHECK);
  }

  CrossOriginAttributeValue cross_origin = GetCrossOriginAttributeValue(
      element.FastGetAttribute(html_names::kCrossoriginAttr));
  if (cross_origin != kCrossOriginAttributeNotSet) {
    params.SetCrossOriginAccessControl(
        element.GetDocument().GetSecurityOrigin(), cross_origin);
  }

  if (RuntimeEnabledFeatures::PriorityHintsEnabled(&element.GetDocument())) {
    mojom::FetchImportanceMode importance_mode =
        GetFetchImportanceAttributeValue(
            element.FastGetAttribute(html_names::kImportanceAttr));
    params.SetFetchImportanceMode(importance_mode);
  }

  auto* html_image_element = DynamicTo<HTMLImageElement>(element);
  if (client_hints_preferences.ShouldSend(
          mojom::WebClientHintsType::kResourceWidth) &&
      html_image_element)
    params.SetResourceWidth(html_image_element->GetResourceWidth());
}

inline void ImageLoader::DispatchErrorEvent() {
  // There can be cases where DispatchErrorEvent() is called when there is
  // already a scheduled error event for the previous load attempt.
  // In such cases we cancel the previous event (by overwriting
  // |pending_error_event_|) and then re-schedule a new error event here.
  // crbug.com/722500
  pending_error_event_ = PostCancellableTask(
      *GetElement()->GetDocument().GetTaskRunner(TaskType::kDOMManipulation),
      FROM_HERE,
      WTF::Bind(&ImageLoader::DispatchPendingErrorEvent, WrapPersistent(this),
                WTF::Passed(std::make_unique<IncrementLoadEventDelayCount>(
                    GetElement()->GetDocument()))));
}

inline void ImageLoader::CrossSiteOrCSPViolationOccurred(
    AtomicString image_source_url) {
  failed_load_url_ = image_source_url;
}

inline void ImageLoader::ClearFailedLoadURL() {
  failed_load_url_ = AtomicString();
}

inline void ImageLoader::EnqueueImageLoadingMicroTask(
    const KURL& request_url,
    UpdateFromElementBehavior update_behavior,
    network::mojom::ReferrerPolicy referrer_policy) {
  auto task = std::make_unique<Task>(this, request_url, update_behavior,
                                     referrer_policy);
  pending_task_ = task->GetWeakPtr();
  Microtask::EnqueueMicrotask(
      WTF::Bind(&Task::Run, WTF::Passed(std::move(task))));
  delay_until_do_update_from_element_ =
      std::make_unique<IncrementLoadEventDelayCount>(element_->GetDocument());
}

void ImageLoader::UpdateImageState(ImageResourceContent* new_image_content) {
  image_content_ = new_image_content;
  if (!new_image_content) {
    image_content_for_image_document_ = nullptr;
    image_complete_ = true;
    if (lazy_image_load_state_ == LazyImageLoadState::kDeferred) {
      LazyImageHelper::StopMonitoring(GetElement());
      lazy_image_load_state_ = LazyImageLoadState::kFullImage;
    }
  } else {
    image_complete_ = false;
    if (lazy_image_load_state_ == LazyImageLoadState::kDeferred)
      LazyImageHelper::StartMonitoring(GetElement());
  }
  delay_until_image_notify_finished_ = nullptr;
}

void ImageLoader::DoUpdateFromElement(
    BypassMainWorldBehavior bypass_behavior,
    UpdateFromElementBehavior update_behavior,
    const KURL& url,
    network::mojom::ReferrerPolicy referrer_policy,
    UpdateType update_type) {
  // FIXME: According to
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#the-img-element:the-img-element-55
  // When "update image" is called due to environment changes and the load
  // fails, onerror should not be called. That is currently not the case.
  //
  // We don't need to call clearLoader here: Either we were called from the
  // task, or our caller updateFromElement cleared the task's loader (and set
  // pending_task_ to null).
  pending_task_.reset();
  // Make sure to only decrement the count when we exit this function
  std::unique_ptr<IncrementLoadEventDelayCount> load_delay_counter;
  load_delay_counter.swap(delay_until_do_update_from_element_);

  Document& document = element_->GetDocument();
  if (!document.IsActive())
    return;

  AtomicString image_source_url = element_->ImageSourceURL();
  ImageResourceContent* new_image_content = nullptr;
  if (!url.IsNull() && !url.IsEmpty()) {
    // Unlike raw <img>, we block mixed content inside of <picture> or
    // <img srcset>.
    ResourceLoaderOptions resource_loader_options;
    resource_loader_options.initiator_info.name = GetElement()->localName();
    ResourceRequest resource_request(url);
    if (update_behavior == kUpdateForcedReload) {
      resource_request.SetCacheMode(mojom::FetchCacheMode::kBypassCache);
      resource_request.SetPreviewsState(WebURLRequest::kPreviewsNoTransform);
    }

    resource_request.SetReferrerPolicy(referrer_policy);

    // Correct the RequestContext if necessary.
    if (IsA<HTMLPictureElement>(GetElement()->parentNode()) ||
        !GetElement()->FastGetAttribute(html_names::kSrcsetAttr).IsNull()) {
      resource_request.SetRequestContext(mojom::RequestContextType::IMAGE_SET);
      resource_request.SetRequestDestination(
          network::mojom::RequestDestination::kImage);
    } else if (IsA<HTMLObjectElement>(GetElement())) {
      resource_request.SetRequestContext(mojom::RequestContextType::OBJECT);
      resource_request.SetRequestDestination(
          network::mojom::RequestDestination::kObject);
    } else if (IsA<HTMLEmbedElement>(GetElement())) {
      resource_request.SetRequestContext(mojom::RequestContextType::EMBED);
      resource_request.SetRequestDestination(
          network::mojom::RequestDestination::kEmbed);
    }

    bool page_is_being_dismissed =
        document.PageDismissalEventBeingDispatched() != Document::kNoDismissal;
    if (page_is_being_dismissed) {
      resource_request.SetHttpHeaderField(http_names::kCacheControl,
                                          "max-age=0");
      resource_request.SetKeepalive(true);
      resource_request.SetRequestContext(mojom::RequestContextType::PING);
    }

    // Plug-ins should not load via service workers as plug-ins may have their
    // own origin checking logic that may get confused if service workers
    // respond with resources from another origin.
    // https://w3c.github.io/ServiceWorker/#implementer-concerns
    auto* html_element = DynamicTo<HTMLElement>(GetElement());
    if (html_element && html_element->IsPluginElement()) {
      resource_request.SetSkipServiceWorker(true);
    }

    DCHECK(document.GetFrame());
    FetchParameters params(std::move(resource_request),
                           resource_loader_options);
    ConfigureRequest(params, bypass_behavior, *element_,
                     document.GetFrame()->GetClientHintsPreferences());

    if (update_behavior != kUpdateForcedReload &&
        lazy_image_load_state_ == LazyImageLoadState::kNone) {
      const auto* frame = document.GetFrame();
      if (auto* html_image = DynamicTo<HTMLImageElement>(GetElement())) {
        switch (LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
            *frame, html_image, params.Url())) {
          case LazyImageHelper::Eligibility::kEnabledFullyDeferred:
            lazy_image_load_state_ = LazyImageLoadState::kDeferred;
            was_fully_deferred_ = true;
            params.SetLazyImageDeferred();
            if (frame->Client()) {
              frame->Client()->DidObserveLazyLoadBehavior(
                  WebLocalFrameClient::LazyLoadBehavior::kDeferredImage);
            }
            break;
          case LazyImageHelper::Eligibility::kEnabledFetchPlaceholder:
            lazy_image_load_state_ = LazyImageLoadState::kDeferred;
            params.SetLazyImagePlaceholder();
            break;
          case LazyImageHelper::Eligibility::kDisabled:
            break;
        }
      }
    }

    // If the image was previously set to full image and had no dimensions, it
    // is a full load of a placeholder image.
    if (!was_fully_deferred_ &&
        lazy_image_load_state_ == LazyImageLoadState::kFullImage) {
      params.SetLazyImageAutoReload();
    }

    // Enable subresource redirect for <img> elements created by parser when
    // data saver is on. Images created from javascript, fetched via XHR/Fetch
    // API should not be subresource redirected due to the additional CORB/CORS
    // handling needed for them.
    // TODO(rajendrant): Disable subresource redirect when CORS,
    // content-security-policy does not allow cross-origin accesses.
    if (auto* html_image = DynamicTo<HTMLImageElement>(GetElement())) {
      if (base::FeatureList::IsEnabled(blink::features::kSubresourceRedirect) &&
          html_image->ElementCreatedByParser() &&
          GetNetworkStateNotifier().SaveDataEnabled()) {
        auto& resource_request = params.MutableResourceRequest();
        resource_request.SetPreviewsState(
            resource_request.GetPreviewsState() |
            WebURLRequest::kSubresourceRedirectOn);
      }
    }

    if (lazy_image_load_state_ == LazyImageLoadState::kDeferred &&
        was_fully_deferred_ && !ShouldLoadImmediately(url)) {
      // TODO(rajendrant): Remove this temporary workaround of creating a 1x1
      // placeholder to fix an intersection observer issue not firing with
      // certain styles (https://crbug.com/992765). Instead
      // NoImageResourceToLoad() should be skipped when the image is deferred.
      // https://crbug.com/999209
      new_image_content = ImageResourceContent::CreateLazyImagePlaceholder();
    } else {
      new_image_content =
          ImageResourceContent::Fetch(params, document.Fetcher());
    }

    // If this load is starting while navigating away, treat it as an auditing
    // keepalive request, and don't report its results back to the element.
    if (page_is_being_dismissed)
      new_image_content = nullptr;

    ClearFailedLoadURL();
  } else {
    if (!image_source_url.IsNull()) {
      // Fire an error event if the url string is not empty, but the KURL is.
      DispatchErrorEvent();
    }
    NoImageResourceToLoad();
  }

  ImageResourceContent* old_image_content = image_content_.Get();
  if (old_image_content != new_image_content)
    RejectPendingDecodes(update_type);

  if (update_behavior == kUpdateSizeChanged && element_->GetLayoutObject() &&
      element_->GetLayoutObject()->IsImage() &&
      new_image_content == old_image_content) {
    ToLayoutImage(element_->GetLayoutObject())->IntrinsicSizeChanged();
  } else {
    // Loading didn't start (loading of images was disabled). We show fallback
    // contents here, while we don't dispatch an 'error' event etc., because
    // spec-wise the image remains in the "Unavailable" state.
    if (new_image_content &&
        new_image_content->GetContentStatus() == ResourceStatus::kNotStarted)
      NoImageResourceToLoad();

    if (pending_load_event_.IsActive())
      pending_load_event_.Cancel();

    // Cancel error events that belong to the previous load, which is now
    // cancelled by changing the src attribute. If newImage is null and
    // has_pending_error_event_ is true, we know the error event has been just
    // posted by this load and we should not cancel the event.
    // FIXME: If both previous load and this one got blocked with an error, we
    // can receive one error event instead of two.
    if (pending_error_event_.IsActive() && new_image_content)
      pending_error_event_.Cancel();

    UpdateImageState(new_image_content);

    UpdateLayoutObject();
    // If newImage exists and is cached, addObserver() will result in the load
    // event being queued to fire. Ensure this happens after beforeload is
    // dispatched.
    if (new_image_content) {
      new_image_content->AddObserver(this);
    }
    if (old_image_content) {
      old_image_content->RemoveObserver(this);
    }
  }

  if (LayoutImageResource* image_resource = GetLayoutImageResource())
    image_resource->ResetAnimation();
}

void ImageLoader::UpdateFromElement(
    UpdateFromElementBehavior update_behavior,
    network::mojom::ReferrerPolicy referrer_policy) {
  AtomicString image_source_url = element_->ImageSourceURL();
  suppress_error_events_ = (update_behavior == kUpdateSizeChanged);
  last_base_element_url_ =
      element_->GetDocument().ValidBaseElementURL().GetString();
  last_referrer_policy_ = referrer_policy;

  if (update_behavior == kUpdateIgnorePreviousError)
    ClearFailedLoadURL();

  if (!failed_load_url_.IsEmpty() && image_source_url == failed_load_url_)
    return;

  // Prevent the creation of a ResourceLoader (and therefore a network request)
  // for ImageDocument loads. In this case, the image contents have already been
  // requested as a main resource and ImageDocumentParser will take care of
  // funneling the main resource bytes into |image_content_for_image_document_|,
  // so just pick up the ImageResourceContent that has been provided.
  if (image_content_for_image_document_) {
    DCHECK_NE(update_behavior, kUpdateForcedReload);
    SetImageWithoutConsideringPendingLoadEvent(
        image_content_for_image_document_);
    image_content_for_image_document_ = nullptr;
    return;
  }

  // If we have a pending task, we have to clear it -- either we're now loading
  // immediately, or we need to reset the task's state.
  if (pending_task_) {
    pending_task_->ClearLoader();
    pending_task_.reset();
    // Here we need to clear delay_until_do_update_from_element to avoid causing
    // a memory leak in case it's already created.
    delay_until_do_update_from_element_ = nullptr;
  }

  KURL url = ImageSourceToKURL(image_source_url);

  if (ShouldLoadImmediately(url)) {
    DoUpdateFromElement(kDoNotBypassMainWorldCSP, update_behavior, url,
                        referrer_policy, UpdateType::kSync);
    return;
  }
  // Allow the idiom "img.src=''; img.src='.." to clear down the image before an
  // asynchronous load completes.
  if (image_source_url.IsEmpty()) {
    ImageResourceContent* image = image_content_.Get();
    if (image) {
      image->RemoveObserver(this);
    }
    image_content_ = nullptr;
    image_content_for_image_document_ = nullptr;
    delay_until_image_notify_finished_ = nullptr;
    if (lazy_image_load_state_ != LazyImageLoadState::kNone) {
      LazyImageHelper::StopMonitoring(GetElement());
      lazy_image_load_state_ = LazyImageLoadState::kNone;
    }
  }

  // Don't load images for inactive documents or active documents without V8
  // context. We don't want to slow down the raw HTML parsing case by loading
  // images we don't intend to display.
  Document& document = element_->GetDocument();
  if (!document.IsContextDestroyed() && document.IsActive())
    EnqueueImageLoadingMicroTask(url, update_behavior, referrer_policy);
}

KURL ImageLoader::ImageSourceToKURL(AtomicString image_source_url) const {
  KURL url;

  // Don't load images for inactive documents. We don't want to slow down the
  // raw HTML parsing case by loading images we don't intend to display.
  Document& document = element_->GetDocument();
  if (!document.IsActive())
    return url;

  // Do not load any image if the 'src' attribute is missing or if it is
  // an empty string.
  if (!image_source_url.IsNull()) {
    String stripped_image_source_url =
        StripLeadingAndTrailingHTMLSpaces(image_source_url);
    if (!stripped_image_source_url.IsEmpty())
      url = document.CompleteURL(stripped_image_source_url);
  }
  return url;
}

bool ImageLoader::ShouldLoadImmediately(const KURL& url) const {
  // We force any image loads which might require alt content through the
  // asynchronous path so that we can add the shadow DOM for the alt-text
  // content when style recalc is over and DOM mutation is allowed again.
  if (!url.IsNull()) {
    Resource* resource = GetMemoryCache()->ResourceForURL(
        url, element_->GetDocument().Fetcher()->GetCacheIdentifier());
    if (resource && !resource->ErrorOccurred())
      return true;
  }
  return (IsA<HTMLObjectElement>(*element_) ||
          IsA<HTMLEmbedElement>(*element_));
}

void ImageLoader::ImageChanged(ImageResourceContent* content,
                               CanDeferInvalidation) {
  DCHECK_EQ(content, image_content_.Get());
  if (image_complete_ || !content->IsLoading() ||
      delay_until_image_notify_finished_)
    return;

  Document& document = element_->GetDocument();
  if (!document.IsActive())
    return;

  delay_until_image_notify_finished_ =
      std::make_unique<IncrementLoadEventDelayCount>(document);
}

void ImageLoader::ImageNotifyFinished(ImageResourceContent* resource) {
  RESOURCE_LOADING_DVLOG(1)
      << "ImageLoader::imageNotifyFinished " << this
      << "; has pending load event=" << pending_load_event_.IsActive();

  DCHECK(failed_load_url_.IsEmpty());
  DCHECK_EQ(resource, image_content_.Get());

  CHECK(!image_complete_);

  if (lazy_image_load_state_ == LazyImageLoadState::kDeferred) {
    // LazyImages: if a placeholder is loaded, suppress load events and do not
    // consider the image as loaded, except for unblocking document load events.
    // The final image load (including load events) occurs when the
    // non-placeholder image loading (triggered by LoadDeferredImage()) is
    // finished.
    if (image_content_ && image_content_->GetImage()->IsPlaceholderImage()) {
      delay_until_image_notify_finished_ = nullptr;
      return;
    }
    // A placeholder was requested, but the result was an error or a full image.
    // In these cases, consider this as the final image and suppress further
    // reloading and proceed to the image load completion process below.
    LazyImageHelper::StopMonitoring(GetElement());
    lazy_image_load_state_ = LazyImageLoadState::kFullImage;
  }

  image_complete_ = true;
  delay_until_image_notify_finished_ = nullptr;

  UpdateLayoutObject();

  if (image_content_ && image_content_->HasImage()) {
    Image& image = *image_content_->GetImage();

    if (auto* svg_image = DynamicTo<SVGImage>(image)) {
      // SVG's document should be completely loaded before access control
      // checks, which can occur anytime after ImageNotifyFinished()
      // (See SVGImage::CurrentFrameHasSingleSecurityOrigin()).
      // We check the document is loaded here to catch violation of the
      // assumption reliably.
      svg_image->CheckLoaded();
      svg_image->UpdateUseCounters(GetElement()->GetDocument());
    }
  }

  // TODO(loonybear): support image policies on other images in addition to
  // HTMLImageElement.
  // crbug.com/930281
  auto* html_image_element = DynamicTo<HTMLImageElement>(element_.Get());
  if (CheckForUnoptimizedImagePolicy(element_->GetDocument(), image_content_) &&
      html_image_element)
    html_image_element->SetImagePolicyViolated();

  DispatchDecodeRequestsIfComplete();

  if (html_image_element)
    LazyImageHelper::RecordMetricsOnLoadFinished(html_image_element);

  if (resource->ErrorOccurred()) {
    pending_load_event_.Cancel();

    base::Optional<ResourceError> error = resource->GetResourceError();
    if (error && error->IsAccessCheck())
      CrossSiteOrCSPViolationOccurred(AtomicString(error->FailingURL()));

    // The error event should not fire if the image data update is a result of
    // environment change.
    // https://html.spec.whatwg.org/C/#the-img-element:the-img-element-55
    if (!suppress_error_events_)
      DispatchErrorEvent();
    return;
  }

  CHECK(!pending_load_event_.IsActive());
  pending_load_event_ = PostCancellableTask(
      *GetElement()->GetDocument().GetTaskRunner(TaskType::kDOMManipulation),
      FROM_HERE,
      WTF::Bind(&ImageLoader::DispatchPendingLoadEvent, WrapPersistent(this),
                WTF::Passed(std::make_unique<IncrementLoadEventDelayCount>(
                    GetElement()->GetDocument()))));
}

LayoutImageResource* ImageLoader::GetLayoutImageResource() {
  LayoutObject* layout_object = element_->GetLayoutObject();

  if (!layout_object)
    return nullptr;

  // We don't return style generated image because it doesn't belong to the
  // ImageLoader. See <https://bugs.webkit.org/show_bug.cgi?id=42840>
  if (layout_object->IsImage() &&
      !ToLayoutImage(layout_object)->IsGeneratedContent())
    return ToLayoutImage(layout_object)->ImageResource();

  if (layout_object->IsSVGImage())
    return ToLayoutSVGImage(layout_object)->ImageResource();

  if (layout_object->IsVideo())
    return ToLayoutVideo(layout_object)->ImageResource();

  return nullptr;
}

void ImageLoader::UpdateLayoutObject() {
  LayoutImageResource* image_resource = GetLayoutImageResource();

  if (!image_resource)
    return;

  // Only update the layoutObject if it doesn't have an image or if what we have
  // is a complete image.  This prevents flickering in the case where a dynamic
  // change is happening between two images.
  ImageResourceContent* cached_image_content = image_resource->CachedImage();
  if (image_content_ != cached_image_content &&
      (image_complete_ || !cached_image_content))
    image_resource->SetImageResource(image_content_.Get());
}

bool ImageLoader::HasPendingEvent() const {
  // Regular image loading is in progress.
  if (image_content_ && !image_complete_)
    return true;

  if (pending_load_event_.IsActive() || pending_error_event_.IsActive())
    return true;

  return false;
}

void ImageLoader::DispatchPendingLoadEvent(
    std::unique_ptr<IncrementLoadEventDelayCount> count) {
  if (!image_content_)
    return;
  CHECK(image_complete_);
  if (GetElement()->GetDocument().GetFrame())
    DispatchLoadEvent();

  // Checks Document's load event synchronously here for performance.
  // This is safe because DispatchPendingLoadEvent() is called asynchronously.
  count->ClearAndCheckLoadEvent();
}

void ImageLoader::DispatchPendingErrorEvent(
    std::unique_ptr<IncrementLoadEventDelayCount> count) {
  if (GetElement()->GetDocument().GetFrame())
    GetElement()->DispatchEvent(*Event::Create(event_type_names::kError));

  // Checks Document's load event synchronously here for performance.
  // This is safe because DispatchPendingErrorEvent() is called asynchronously.
  count->ClearAndCheckLoadEvent();
}

bool ImageLoader::GetImageAnimationPolicy(ImageAnimationPolicy& policy) {
  if (!GetElement()->GetDocument().GetSettings())
    return false;

  policy = GetElement()->GetDocument().GetSettings()->GetImageAnimationPolicy();
  return true;
}

ScriptPromise ImageLoader::Decode(ScriptState* script_state,
                                  ExceptionState& exception_state) {
  // It's possible that |script_state|'s context isn't valid, which means we
  // should immediately reject the request. This is possible in situations like
  // the document that created this image was already destroyed (like an img
  // that comes from iframe.contentDocument.createElement("img") and the iframe
  // is destroyed).
  if (!script_state->ContextIsValid()) {
    exception_state.ThrowDOMException(DOMExceptionCode::kEncodingError,
                                      "The source image cannot be decoded.");
    return ScriptPromise();
  }

  UseCounter::Count(GetElement()->GetDocument(), WebFeature::kImageDecodeAPI);

  auto* request = MakeGarbageCollected<DecodeRequest>(
      this, MakeGarbageCollected<ScriptPromiseResolver>(script_state));
  Microtask::EnqueueMicrotask(
      WTF::Bind(&DecodeRequest::ProcessForTask, WrapWeakPersistent(request)));
  decode_requests_.push_back(request);
  return request->promise();
}

void ImageLoader::LoadDeferredImage(
    network::mojom::ReferrerPolicy referrer_policy) {
  if (lazy_image_load_state_ != LazyImageLoadState::kDeferred)
    return;
  DCHECK(!image_complete_);
  lazy_image_load_state_ = LazyImageLoadState::kFullImage;

  // If the image has been fully deferred (no placeholder fetch), report it as
  // fully loaded now.
  LocalFrame* frame = element_->GetDocument().GetFrame();
  if (was_fully_deferred_ && frame && frame->Client()) {
    frame->Client()->DidObserveLazyLoadBehavior(
        WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedImage);
  }
  UpdateFromElement(kUpdateNormal, referrer_policy);
}

void ImageLoader::ElementDidMoveToNewDocument() {
  if (delay_until_do_update_from_element_) {
    delay_until_do_update_from_element_->DocumentChanged(
        element_->GetDocument());
  }
  if (delay_until_image_notify_finished_) {
    delay_until_image_notify_finished_->DocumentChanged(
        element_->GetDocument());
  }
  ClearFailedLoadURL();
  ClearImage();
}

// Indicates the next available id that we can use to uniquely identify a decode
// request.
uint64_t ImageLoader::DecodeRequest::s_next_request_id_ = 0;

ImageLoader::DecodeRequest::DecodeRequest(ImageLoader* loader,
                                          ScriptPromiseResolver* resolver)
    : request_id_(s_next_request_id_++), resolver_(resolver), loader_(loader) {}

void ImageLoader::DecodeRequest::Resolve() {
  resolver_->Resolve();
  loader_ = nullptr;
}

void ImageLoader::DecodeRequest::Reject() {
  resolver_->Reject(MakeGarbageCollected<DOMException>(
      DOMExceptionCode::kEncodingError, "The source image cannot be decoded."));
  loader_ = nullptr;
}

void ImageLoader::DecodeRequest::ProcessForTask() {
  // We could have already processed (ie rejected) this task due to a sync
  // update in UpdateFromElement. In that case, there's nothing to do here.
  if (!loader_)
    return;

  DCHECK_EQ(state_, kPendingMicrotask);
  state_ = kPendingLoad;
  loader_->DispatchDecodeRequestsIfComplete();
}

void ImageLoader::DecodeRequest::NotifyDecodeDispatched() {
  DCHECK_EQ(state_, kPendingLoad);
  state_ = kDispatched;
}

void ImageLoader::DecodeRequest::Trace(Visitor* visitor) {
  visitor->Trace(resolver_);
  visitor->Trace(loader_);
}

}  // namespace blink
