| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_ICON_TRANSCODER_SVG_ICON_TRANSCODER_H_ |
| #define CHROME_BROWSER_ICON_TRANSCODER_SVG_ICON_TRANSCODER_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_process_host_observer.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/image/image.h" |
| #include "url/gurl.h" |
| |
| namespace content { |
| class BrowserContext; |
| class WebContents; |
| } // namespace content |
| |
| namespace apps { |
| |
| using IconContentCallback = base::OnceCallback<void(std::string)>; |
| |
| // SvgIconTranscoder uses WebContents to transform an svg icon (as a file or |
| // as string data) into an SkBitmap and thence into png compressed data which |
| // can be written to a png file. In principal, this technique should work for |
| // any data:image/ mime-types supported by WebContents, but svg is all we need |
| // right now. File handling happens in the browser process. |
| // Some validation of svg data is performed prior to asking a WebContents |
| // renderer process (which could potentially die on bad data) to render the |
| // image. Since a renderer process can be destroyed for many valid reasons, |
| // SvgIconTranscoder always checks if its WebContents must be recreated. |
| class SvgIconTranscoder : public content::RenderProcessHostObserver { |
| public: |
| explicit SvgIconTranscoder(content::BrowserContext* context); |
| |
| SvgIconTranscoder(const SvgIconTranscoder&) = delete; |
| SvgIconTranscoder& operator=(const SvgIconTranscoder&) = delete; |
| ~SvgIconTranscoder() override; |
| |
| // Reads the svg data at svg_path and invokes the string Transcode method. |
| // |callback| is invoked with and empty string on failure. Blocking call. |
| void Transcode(const base::FilePath&& svg_path, |
| const base::FilePath&& png_path, |
| gfx::Size preferred_size, |
| IconContentCallback callback); |
| |
| // Validates and trims the svg_data before base64 encoding and dispatching to |
| // |web_contents_| in a data: URI. |callback| is invoked with and empty |
| // string on failure. Blocking call. |
| void Transcode(const std::string& svg_data, |
| const base::FilePath&& png_path, |
| gfx::Size preferred_size, |
| IconContentCallback callback); |
| |
| base::WeakPtr<SvgIconTranscoder> GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| private: |
| void MaybeCreateWebContents(); |
| |
| bool PrepareWebContents(); |
| |
| void RemoveObserver(); |
| |
| // content::RenderProcessHostObserver: |
| void RenderProcessReady(content::RenderProcessHost* host) override; |
| // content::RenderProcessHostObserver: |
| void RenderProcessExited( |
| content::RenderProcessHost* host, |
| const content::ChildProcessTerminationInfo& info) override; |
| |
| // Compresses the first received bitmap and saves compressed data to |
| // |png_path| if non-empty. If the file can't be saved, that's not considered |
| // and error. Next time lucky. |
| void OnDownloadImage(base::FilePath png_path, |
| IconContentCallback callback, |
| int id, |
| int http_status_code, |
| const GURL& image_url, |
| const std::vector<SkBitmap>& bitmaps, |
| const std::vector<gfx::Size>& sizes); |
| |
| const raw_ptr<content::BrowserContext, DanglingUntriaged> browser_context_; |
| std::unique_ptr<content::WebContents> web_contents_; |
| bool web_contents_ready_{false}; |
| base::WeakPtrFactory<SvgIconTranscoder> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace apps |
| |
| #endif // CHROME_BROWSER_ICON_TRANSCODER_SVG_ICON_TRANSCODER_H_ |