File: image_fetcher_impl.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (141 lines) | stat: -rw-r--r-- 5,391 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/image_fetcher/core/image_fetcher_impl.h"

#include <string>

#include "base/functional/bind.h"
#include "base/task/single_thread_task_runner.h"
#include "net/base/load_flags.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/gfx/image/image.h"

namespace image_fetcher {

ImageFetcherImpl::ImageFetcherImpl(
    std::unique_ptr<ImageDecoder> image_decoder,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
    : url_loader_factory_(url_loader_factory),
      image_decoder_(std::move(image_decoder)),
      image_data_fetcher_(new ImageDataFetcher(url_loader_factory)) {}

ImageFetcherImpl::~ImageFetcherImpl() = default;

ImageFetcherImpl::ImageRequest::ImageRequest() = default;
ImageFetcherImpl::ImageRequest::ImageRequest(ImageRequest&& other) = default;

ImageFetcherImpl::ImageRequest::~ImageRequest() = default;

void ImageFetcherImpl::FetchImageAndData(
    const GURL& image_url,
    ImageDataFetcherCallback image_data_callback,
    ImageFetcherCallback image_callback,
    ImageFetcherParams params) {
  // Before starting to fetch the image. Look for a request in progress for
  // `image_url`, and queue if appropriate.
  auto it = pending_net_requests_.find(image_url);
  if (it == pending_net_requests_.end()) {
    ImageRequest request;
    request.id = image_url.spec();
    if (image_callback) {
      request.image_callbacks.push_back(std::move(image_callback));
    }
    if (image_data_callback) {
      request.image_data_callbacks.push_back(std::move(image_data_callback));
    }
    pending_net_requests_.emplace(image_url, std::move(request));

    image_data_fetcher_->SetImageDownloadLimit(params.max_download_size());
    image_data_fetcher_->FetchImageData(
        image_url,
        base::BindOnce(&ImageFetcherImpl::OnImageURLFetched,
                       base::Unretained(this), image_url, params),
        params);
  } else {
    ImageRequest* request = &it->second;
    // Request in progress. Register as an interested callback.
    // TODO(treib,markusheintz): We're not guaranteed that the ID also matches.
    //                           We probably have to store them all.
    if (image_callback) {
      request->image_callbacks.push_back(std::move(image_callback));
    }
    // Call callback if data is already fetched, otherwise register it for
    // later.
    if (image_data_callback) {
      if (!request->image_data.empty()) {
        base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
            FROM_HERE,
            base::BindOnce(&ImageFetcherImpl::RunImageDataCallback,
                           weak_ptr_factory_.GetWeakPtr(),
                           std::move(image_data_callback), request->image_data,
                           request->request_metadata));
      } else {
        request->image_data_callbacks.push_back(std::move(image_data_callback));
      }
    }
  }
}

void ImageFetcherImpl::OnImageURLFetched(const GURL& image_url,
                                         ImageFetcherParams params,
                                         const std::string& image_data,
                                         const RequestMetadata& metadata) {
  auto it = pending_net_requests_.find(image_url);
  CHECK(it != pending_net_requests_.end());
  ImageRequest* request = &it->second;
  DCHECK(request->image_data.empty());
  DCHECK_EQ(RequestMetadata::RESPONSE_CODE_INVALID,
            request->request_metadata.http_response_code);
  for (auto& callback : request->image_data_callbacks) {
    std::move(callback).Run(image_data, metadata);
  }
  request->image_data_callbacks.clear();

  if (image_data.empty() || request->image_callbacks.empty()) {
    for (auto& callback : request->image_callbacks) {
      std::move(callback).Run(gfx::Image(), metadata);
    }
    pending_net_requests_.erase(it);
    return;
  }
  request->image_data = image_data;
  request->request_metadata = metadata;
  image_decoder_->DecodeImage(
      image_data, params.frame_size(), params.data_decoder(),
      base::BindOnce(&ImageFetcherImpl::OnImageDecoded,
                     weak_ptr_factory_.GetWeakPtr(), image_url, metadata));
}

void ImageFetcherImpl::OnImageDecoded(const GURL& image_url,
                                      const RequestMetadata& metadata,
                                      const gfx::Image& image) {
  // Get request for the given image_url from the request queue.
  auto image_iter = pending_net_requests_.find(image_url);
  CHECK(image_iter != pending_net_requests_.end());
  ImageRequest* request = &image_iter->second;

  // Run all image callbacks.
  for (auto& callback : request->image_callbacks) {
    std::move(callback).Run(image, metadata);
  }

  // Erase the completed ImageRequest.
  DCHECK(request->image_data_callbacks.empty());
  pending_net_requests_.erase(image_iter);
}

void ImageFetcherImpl::RunImageDataCallback(
    ImageDataFetcherCallback image_data_callback,
    std::string image_data,
    RequestMetadata request_metadata) {
  std::move(image_data_callback)
      .Run(std::move(image_data), std::move(request_metadata));
}

ImageDecoder* ImageFetcherImpl::GetImageDecoder() {
  return image_decoder_.get();
}

}  // namespace image_fetcher