blob: 716fff6c1c3e98b45258dc49ce655bfab050822f [file] [log] [blame]
// 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 "components/dom_distiller/content/browser/distillability_driver.h"
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/observer_list.h"
#include "build/build_config.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/page_user_data.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
namespace dom_distiller {
namespace {
class DistillabilityResultPageData
: public content::PageUserData<DistillabilityResultPageData> {
public:
explicit DistillabilityResultPageData(content::Page& page);
DistillabilityResultPageData(const DistillabilityResultPageData&) = delete;
DistillabilityResultPageData& operator=(const DistillabilityResultPageData&) =
delete;
~DistillabilityResultPageData() override;
DistillabilityResult distillability_result;
PAGE_USER_DATA_KEY_DECL();
};
DistillabilityResultPageData::DistillabilityResultPageData(content::Page& page)
: PageUserData<DistillabilityResultPageData>(page) {}
DistillabilityResultPageData::~DistillabilityResultPageData() = default;
PAGE_USER_DATA_KEY_IMPL(DistillabilityResultPageData);
} // namespace
// Implementation of the Mojo DistillabilityService. This is called by the
// renderer to notify the browser that a page is distillable.
class DistillabilityServiceImpl : public mojom::DistillabilityService {
public:
explicit DistillabilityServiceImpl(
base::WeakPtr<DistillabilityDriver> distillability_driver)
: distillability_driver_(distillability_driver) {}
~DistillabilityServiceImpl() override = default;
void NotifyIsDistillable(bool is_distillable,
bool is_last_update,
bool is_long_article,
bool is_mobile_friendly) override {
if (!distillability_driver_)
return;
DistillabilityResult result;
result.is_distillable = is_distillable;
result.is_last = is_last_update;
result.is_long_article = is_long_article;
result.is_mobile_friendly = is_mobile_friendly;
DVLOG(1) << "Notifying observers of distillability service result: "
<< result;
distillability_driver_->OnDistillability(result);
}
private:
base::WeakPtr<DistillabilityDriver> distillability_driver_;
};
DistillabilityDriver::DistillabilityDriver(content::WebContents* web_contents)
: content::WebContentsUserData<DistillabilityDriver>(*web_contents),
content::WebContentsObserver(web_contents) {}
DistillabilityDriver::~DistillabilityDriver() = default;
void DistillabilityDriver::CreateDistillabilityService(
mojo::PendingReceiver<mojom::DistillabilityService> receiver) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<DistillabilityServiceImpl>(weak_factory_.GetWeakPtr()),
std::move(receiver));
}
void DistillabilityDriver::SetIsSecureCallback(
base::RepeatingCallback<bool(content::WebContents*)> is_secure_check) {
is_secure_check_ = std::move(is_secure_check);
}
void DistillabilityDriver::PrimaryPageChanged(content::Page& page) {
DistillabilityResultPageData* page_data =
DistillabilityResultPageData::GetForPage(page);
if (page_data) {
OnDistillability(page_data->distillability_result);
}
}
void DistillabilityDriver::OnDistillability(
const DistillabilityResult& result) {
#if !BUILDFLAG(IS_ANDROID)
if (result.is_distillable) {
if (!is_secure_check_ || !is_secure_check_.Run(&GetWebContents())) {
DistillabilityResult not_distillable;
not_distillable.is_distillable = false;
not_distillable.is_last = result.is_last;
not_distillable.is_long_article = result.is_long_article;
not_distillable.is_mobile_friendly = result.is_mobile_friendly;
latest_result_ = not_distillable;
for (auto& observer : observers_)
observer.OnResult(not_distillable);
return;
}
}
#endif // !BUILDFLAG(IS_ANDROID)
DistillabilityResultPageData::CreateForPage(
GetWebContents().GetPrimaryPage());
DistillabilityResultPageData* page_data =
DistillabilityResultPageData::GetForPage(
GetWebContents().GetPrimaryPage());
page_data->distillability_result = result;
latest_result_ = result;
for (auto& observer : observers_)
observer.OnResult(result);
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(DistillabilityDriver);
} // namespace dom_distiller