910e62b5创建于 1月15日历史提交
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {assert} from 'chrome://resources/js/assert.js';

import {ImageCache} from './cache.js';
import type {ImageTransformParam} from './image_orientation.js';
import {ImageOrientation} from './image_orientation.js';
import {ImageRequestTask} from './image_request_task.js';
import type {LoadImageRequest, LoadImageResponse} from './load_image_request.js';
import {Scheduler} from './scheduler.js';

let instance: ImageLoader|null = null;

/**
 * Loads and resizes an image.
 */
export class ImageLoader {
  /**
   * Persistent cache object.
   */
  private cache_: ImageCache = new ImageCache();

  /**
   * Manages pending requests and runs them in order of priorities.
   */
  private scheduler_: Scheduler = new Scheduler();

  constructor() {
    // Initialize the cache and then start the scheduler.
    this.cache_.initialize(() => this.scheduler_.start());
  }

  /**
   * Handles a request. Depending on type of the request, starts or stops
   * an image task.
   * @return True if the message channel should stay alive until the
   *     sendResponse callback is called.
   */
  handle(
      request: LoadImageRequest,
      sendResponse: (r: LoadImageResponse) => void): boolean {
    assert(request.imageLoaderRequestId);
    if (request.cancel) {
      this.scheduler_.remove(request.imageLoaderRequestId);
      return false;
    }

    // When manually debugging the Image Loader extension, you can reply with
    // a placeholder image here by patching in https://crrev.com/c/5796592

    // Sending a response may fail if the receiver already went offline.
    // This is not an error, but a normal and quite common situation.
    const failSafeSendResponse = function(response: LoadImageResponse) {
      try {
        sendResponse(response);
      } catch (e) {
        // Ignore the error.
      }
    };
    // Incoming requests won't have the full type.
    assert(!(request.orientation instanceof ImageOrientation));
    assert(typeof request.orientation !== 'number');

    if (request.orientation) {
      request.orientation = ImageOrientation.fromRotationAndScale(
          request.orientation as ImageTransformParam);
    } else {
      request.orientation = new ImageOrientation(1, 0, 0, 1);
    }

    // Add a new request task to the scheduler (queue).
    this.scheduler_.add(new ImageRequestTask(
        request.imageLoaderRequestId, this.cache_, request,
        failSafeSendResponse));
    return true;
  }

  /**
   * Returns a singleton instance.
   */
  static getInstance(): ImageLoader {
    if (!instance) {
      instance = new ImageLoader();
    }
    return instance;
  }
}