chromium/ios/chrome/browser/dom_distiller/model/distiller_viewer.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ios/chrome/browser/dom_distiller/model/distiller_viewer.h"

#include <string>
#include <utility>

#include "base/base64.h"
#include "base/functional/bind.h"
#include "base/rand_util.h"
#include "components/dom_distiller/core/distilled_page_prefs.h"
#include "components/dom_distiller/core/distiller.h"
#include "components/dom_distiller/core/dom_distiller_request_view_base.h"
#include "components/dom_distiller/core/dom_distiller_service.h"
#include "components/dom_distiller/core/proto/distilled_article.pb.h"
#include "components/dom_distiller/core/task_tracker.h"
#include "components/dom_distiller/core/viewer.h"
#include "ui/gfx/geometry/size.h"

namespace dom_distiller {

DistillerViewer::DistillerViewer(
    dom_distiller::DomDistillerService* distillerService,
    PrefService* prefs,
    const GURL& url,
    DistillationFinishedCallback callback)
    : DistillerViewerInterface(prefs),
      url_(url),
      csp_nonce_(base::Base64Encode(base::RandBytesAsVector(16))),
      callback_(std::move(callback)) {
  DCHECK(distillerService);
  DCHECK(url.is_valid());
  std::unique_ptr<dom_distiller::DistillerPage> page =
      distillerService->CreateDefaultDistillerPage(gfx::Size());
  std::unique_ptr<ViewerHandle> viewer_handle =
      distillerService->ViewUrl(this, std::move(page), url);
  TakeViewerHandle(std::move(viewer_handle));
}

DistillerViewer::DistillerViewer(
    dom_distiller::DistillerFactory* distiller_factory,
    std::unique_ptr<dom_distiller::DistillerPage> page,
    PrefService* prefs,
    const GURL& url,
    DistillationFinishedCallback callback)
    : DistillerViewerInterface(prefs),
      url_(url),
      csp_nonce_(base::Base64Encode(base::RandBytesAsVector(16))),
      callback_(std::move(callback)) {
  DCHECK(url.is_valid());
  SendCommonJavaScript();
  distiller_ = distiller_factory->CreateDistillerForUrl(url);
  distiller_->DistillPage(
      url, std::move(page),
      base::BindOnce(&DistillerViewer::OnDistillerFinished,
                     weak_ptr_factory_.GetWeakPtr()),
      base::BindRepeating(&DistillerViewer::OnArticleDistillationUpdated,
                          weak_ptr_factory_.GetWeakPtr()));
}

DistillerViewer::~DistillerViewer() {}

void DistillerViewer::OnArticleDistillationUpdated(
    const dom_distiller::ArticleDistillationUpdate& article_update) {}

void DistillerViewer::OnDistillerFinished(
    std::unique_ptr<dom_distiller::DistilledArticleProto> distilled_article) {
  OnArticleReady(distilled_article.get());
}

void DistillerViewer::OnArticleReady(
    const dom_distiller::DistilledArticleProto* article_proto) {
  DCHECK(!callback_.is_null());
  DomDistillerRequestViewBase::OnArticleReady(article_proto);
  bool is_empty = article_proto->pages_size() == 0 ||
                  article_proto->pages(0).html().empty();
  if (!is_empty) {
    std::vector<ImageInfo> images;
    for (int p = 0; p < article_proto->pages_size(); p++) {
      for (int i = 0; i < article_proto->pages(p).image_size(); i++) {
        auto image = article_proto->pages(p).image(i);
        images.push_back(ImageInfo{GURL(image.url()), image.data()});
      }
    }

    const std::string html = viewer::GetArticleTemplateHtml(
        distilled_page_prefs_->GetTheme(),
        distilled_page_prefs_->GetFontFamily(), csp_nonce_);

    std::string html_and_script(html);
    html_and_script += "<script nonce=\"" + csp_nonce_ + "\">" +
                       "distillerOnIos = true; " + js_buffer_ + "</script>";

    std::move(callback_).Run(url_, html_and_script, images,
                             article_proto->title(), csp_nonce_);
  } else {
    std::move(callback_).Run(url_, std::string(), {}, std::string(),
                             std::string());
  }
}

void DistillerViewer::SendJavaScript(const std::string& buffer) {
  js_buffer_ += buffer;
}

std::string DistillerViewer::GetCspNonce() {
  return csp_nonce_;
}

}  // namespace dom_distiller