// 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.
#include "chrome/browser/feed/rss_links_fetcher.h"
#include "base/functional/callback.h"
#include "components/feed/mojom/rss_link_reader.mojom.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "services/service_manager/public/cpp/interface_provider.h"
namespace feed {
namespace {
mojo::Remote<feed::mojom::RssLinkReader> GetRssLinkReaderRemote(
content::WebContents* web_contents) {
DCHECK(web_contents->GetPrimaryMainFrame()->IsRenderFrameLive());
mojo::Remote<feed::mojom::RssLinkReader> result;
// GetRemoteInterfaces() cannot be null if the render frame is created.
web_contents->GetPrimaryMainFrame()->GetRemoteInterfaces()->GetInterface(
result.BindNewPipeAndPassReceiver());
return result;
}
class RssLinksFetcher {
public:
void Start(const GURL& page_url,
mojo::Remote<feed::mojom::RssLinkReader> link_reader,
base::OnceCallback<void(std::vector<GURL>)> callback) {
page_url_ = page_url;
callback_ = std::move(callback);
link_reader_ = std::move(link_reader);
if (link_reader_) {
// Unretained is OK here. The `mojo::Remote` will not invoke callbacks
// after it is destroyed.
link_reader_.set_disconnect_handler(base::BindOnce(
&RssLinksFetcher::SendResultAndDeleteSelf, base::Unretained(this)));
link_reader_->GetRssLinks(base::BindOnce(
&RssLinksFetcher::GetRssLinksComplete, base::Unretained(this)));
return;
}
SendResultAndDeleteSelf();
}
private:
void GetRssLinksComplete(feed::mojom::RssLinksPtr rss_links) {
if (rss_links) {
if (rss_links->page_url == page_url_) {
for (GURL& link : rss_links->links) {
if (link.is_valid() && link.SchemeIsHTTPOrHTTPS()) {
result_.push_back(std::move(link));
}
}
}
}
SendResultAndDeleteSelf();
}
void SendResultAndDeleteSelf() {
std::move(callback_).Run(std::move(result_));
delete this;
}
GURL page_url_;
mojo::Remote<feed::mojom::RssLinkReader> link_reader_;
std::vector<GURL> result_;
base::OnceCallback<void(std::vector<GURL>)> callback_;
};
void FetchRssLinksHelper(const GURL& url,
mojo::Remote<feed::mojom::RssLinkReader> link_reader,
base::OnceCallback<void(std::vector<GURL>)> callback) {
// RssLinksFetcher is self-deleting.
auto* fetcher = new RssLinksFetcher();
fetcher->Start(url, std::move(link_reader), std::move(callback));
}
} // namespace
void FetchRssLinksForTesting(
const GURL& url,
mojo::Remote<feed::mojom::RssLinkReader> link_reader,
base::OnceCallback<void(std::vector<GURL>)> callback) {
FetchRssLinksHelper(url, std::move(link_reader), std::move(callback));
}
void FetchRssLinks(const GURL& url,
content::WebContents* web_contents,
base::OnceCallback<void(std::vector<GURL>)> callback) {
if (!web_contents) {
std::move(callback).Run(std::vector<GURL>());
return;
}
FetchRssLinksHelper(url, GetRssLinkReaderRemote(web_contents),
std::move(callback));
}
} // namespace feed