Commit baef6561 authored by Nicolas Ouellet-payeur's avatar Nicolas Ouellet-payeur Committed by Commit Bot

[BrowserSwitcher] Internals page: add "XML sitelists" section

This section shows:
- URL configured for each of the 3 sitelists
- Time of last refresh
- Time of next refresh
- A "Download now" button, to immediately refresh

To make the "download now" button more usable, the entire page's
contents also automatically refresh when LBS prefs change, or after
XML sitelists are downloaded.

https://imgur.com/a/yhRZnpZ

Bug: 959379
Change-Id: I7517491d95bc9c570232d2080ee5aeead270b674
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1632001Reviewed-by: default avatarJulian Pastarmov <pastarmovj@chromium.org>
Commit-Queue: Nicolas Ouellet-Payeur <nicolaso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#667292}
parent a7a1388b
...@@ -90,10 +90,9 @@ RulesetSource::~RulesetSource() = default; ...@@ -90,10 +90,9 @@ RulesetSource::~RulesetSource() = default;
XmlDownloader::XmlDownloader(Profile* profile, XmlDownloader::XmlDownloader(Profile* profile,
BrowserSwitcherService* service, BrowserSwitcherService* service,
std::vector<RulesetSource> sources, base::TimeDelta first_fetch_delay,
base::RepeatingCallback<void()> all_done_callback) base::RepeatingCallback<void()> all_done_callback)
: service_(service), : service_(service),
sources_(std::move(sources)),
all_done_callback_(std::move(all_done_callback)), all_done_callback_(std::move(all_done_callback)),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
file_url_factory_ = file_url_factory_ =
...@@ -102,14 +101,15 @@ XmlDownloader::XmlDownloader(Profile* profile, ...@@ -102,14 +101,15 @@ XmlDownloader::XmlDownloader(Profile* profile,
content::BrowserContext::GetDefaultStoragePartition(profile) content::BrowserContext::GetDefaultStoragePartition(profile)
->GetURLLoaderFactoryForBrowserProcess(); ->GetURLLoaderFactoryForBrowserProcess();
sources_ = service_->GetRulesetSources();
for (auto& source : sources_) { for (auto& source : sources_) {
if (!source.url.is_valid()) if (!source.url.is_valid())
DoneParsing(&source, ParsedXml({})); DoneParsing(&source, ParsedXml({}));
} }
// Schedule a fetch in 1 minute, but avoid doing unnecessary work. // Fetch in 1 minute.
if (HasValidSources()) ScheduleRefresh(first_fetch_delay);
ScheduleRefresh(service_->fetch_delay());
} }
XmlDownloader::~XmlDownloader() = default; XmlDownloader::~XmlDownloader() = default;
...@@ -120,6 +120,14 @@ bool XmlDownloader::HasValidSources() const { ...@@ -120,6 +120,14 @@ bool XmlDownloader::HasValidSources() const {
[](const RulesetSource& source) { return source.url.is_valid(); }); [](const RulesetSource& source) { return source.url.is_valid(); });
} }
base::Time XmlDownloader::last_refresh_time() const {
return last_refresh_time_;
}
base::Time XmlDownloader::next_refresh_time() const {
return next_refresh_time_;
}
void XmlDownloader::FetchXml() { void XmlDownloader::FetchXml() {
for (auto& source : sources_) { for (auto& source : sources_) {
if (!source.url.is_valid()) { if (!source.url.is_valid()) {
...@@ -181,16 +189,23 @@ void XmlDownloader::DoneParsing(RulesetSource* source, ParsedXml xml) { ...@@ -181,16 +189,23 @@ void XmlDownloader::DoneParsing(RulesetSource* source, ParsedXml xml) {
DCHECK(counter_ <= sources_.size()); DCHECK(counter_ <= sources_.size());
if (counter_ == sources_.size()) { if (counter_ == sources_.size()) {
all_done_callback_.Run(); all_done_callback_.Run();
if (HasValidSources())
last_refresh_time_ = base::Time::Now();
ScheduleRefresh(service_->refresh_delay()); ScheduleRefresh(service_->refresh_delay());
} }
} }
void XmlDownloader::ScheduleRefresh(base::TimeDelta delay) { void XmlDownloader::ScheduleRefresh(base::TimeDelta delay) {
// Avoid doing unnecessary work.
if (!HasValidSources())
return;
// Refresh in 30 minutes, so the sitelists are never too stale. // Refresh in 30 minutes, so the sitelists are never too stale.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&XmlDownloader::Refresh, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&XmlDownloader::Refresh, weak_ptr_factory_.GetWeakPtr()),
delay); delay);
next_refresh_time_ = base::Time::Now() + delay;
} }
void XmlDownloader::Refresh() { void XmlDownloader::Refresh() {
...@@ -218,18 +233,16 @@ BrowserSwitcherService::BrowserSwitcherService(Profile* profile) ...@@ -218,18 +233,16 @@ BrowserSwitcherService::BrowserSwitcherService(Profile* profile)
BrowserSwitcherService::~BrowserSwitcherService() = default; BrowserSwitcherService::~BrowserSwitcherService() = default;
void BrowserSwitcherService::Init() { void BrowserSwitcherService::Init() {
auto sources = GetRulesetSources(); StartDownload(fetch_delay());
StartDownload(std::move(sources));
} }
void BrowserSwitcherService::StartDownload( void BrowserSwitcherService::StartDownload(base::TimeDelta delay) {
std::vector<RulesetSource>&& sources) {
LoadRulesFromPrefs(); LoadRulesFromPrefs();
// This destroys the previous XmlDownloader, which cancels any scheduled // This destroys the previous XmlDownloader, which cancels any scheduled
// refresh operations. // refresh operations.
sitelist_downloader_ = std::make_unique<XmlDownloader>( sitelist_downloader_ = std::make_unique<XmlDownloader>(
profile_, this, std::move(sources), profile_, this, delay,
base::BindRepeating(&BrowserSwitcherService::OnAllRulesetsParsed, base::BindRepeating(&BrowserSwitcherService::OnAllRulesetsParsed,
base::Unretained(this))); base::Unretained(this)));
} }
...@@ -250,6 +263,10 @@ BrowserSwitcherPrefs& BrowserSwitcherService::prefs() { ...@@ -250,6 +263,10 @@ BrowserSwitcherPrefs& BrowserSwitcherService::prefs() {
return prefs_; return prefs_;
} }
XmlDownloader* BrowserSwitcherService::sitelist_downloader() {
return sitelist_downloader_.get();
}
base::TimeDelta BrowserSwitcherService::fetch_delay() { base::TimeDelta BrowserSwitcherService::fetch_delay() {
return fetch_delay_; return fetch_delay_;
} }
...@@ -295,7 +312,15 @@ void BrowserSwitcherService::LoadRulesFromPrefs() { ...@@ -295,7 +312,15 @@ void BrowserSwitcherService::LoadRulesFromPrefs() {
ParsedXml(prefs().GetCachedExternalGreylist(), base::nullopt)); ParsedXml(prefs().GetCachedExternalGreylist(), base::nullopt));
} }
void BrowserSwitcherService::OnAllRulesetsParsed() {} void BrowserSwitcherService::OnAllRulesetsParsed() {
callback_list_.Notify(this);
}
std::unique_ptr<BrowserSwitcherService::CallbackSubscription>
BrowserSwitcherService::RegisterAllRulesetsParsedCallback(
AllRulesetsParsedCallback callback) {
return callback_list_.Add(callback);
}
void BrowserSwitcherService::OnBrowserSwitcherPrefsChanged( void BrowserSwitcherService::OnBrowserSwitcherPrefsChanged(
BrowserSwitcherPrefs* prefs, BrowserSwitcherPrefs* prefs,
...@@ -311,7 +336,7 @@ void BrowserSwitcherService::OnBrowserSwitcherPrefsChanged( ...@@ -311,7 +336,7 @@ void BrowserSwitcherService::OnBrowserSwitcherPrefsChanged(
}); });
if (should_redownload) if (should_redownload)
StartDownload(std::move(sources)); StartDownload(fetch_delay());
} }
void BrowserSwitcherService::OnExternalSitelistParsed(ParsedXml xml) { void BrowserSwitcherService::OnExternalSitelistParsed(ParsedXml xml) {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <string> #include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/callback_list.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h" #include "url/gurl.h"
class BrowserSwitchHandler;
class Profile; class Profile;
namespace browser_switcher { namespace browser_switcher {
...@@ -55,19 +57,15 @@ class BrowserSwitcherService; ...@@ -55,19 +57,15 @@ class BrowserSwitcherService;
class XmlDownloader { class XmlDownloader {
public: public:
// Posts a task to start downloading+parsing the rulesets after 1
// minute. Calls each source's callback once they're done (or failed). In
// addition, calls |all_done_callback| once all the rulesets have been
// processed.
//
// Schedules a refresh every 30 minutes, unless this object gets deleted
// in the meantime.
XmlDownloader(Profile* profile, XmlDownloader(Profile* profile,
BrowserSwitcherService* service, BrowserSwitcherService* service,
std::vector<RulesetSource> sources, base::TimeDelta first_fetch_delay,
base::RepeatingCallback<void()> all_done_callback); base::RepeatingCallback<void()> all_done_callback);
virtual ~XmlDownloader(); virtual ~XmlDownloader();
base::Time last_refresh_time() const;
base::Time next_refresh_time() const;
private: private:
// Returns true if any of the sources requires downloads. This is used to // Returns true if any of the sources requires downloads. This is used to
// avoid scheduling download tasks unnecessarily. // avoid scheduling download tasks unnecessarily.
...@@ -107,17 +105,25 @@ class XmlDownloader { ...@@ -107,17 +105,25 @@ class XmlDownloader {
// trigger the callback once they've all been parsed. // trigger the callback once they've all been parsed.
unsigned int counter_ = 0; unsigned int counter_ = 0;
base::Time last_refresh_time_;
base::Time next_refresh_time_;
base::WeakPtrFactory<XmlDownloader> weak_ptr_factory_; base::WeakPtrFactory<XmlDownloader> weak_ptr_factory_;
}; };
// Manages per-profile resources for BrowserSwitcher. // Manages per-profile resources for BrowserSwitcher.
class BrowserSwitcherService : public KeyedService { class BrowserSwitcherService : public KeyedService {
private:
using AllRulesetsParsedCallbackSignature = void(BrowserSwitcherService*);
using AllRulesetsParsedCallback =
base::RepeatingCallback<AllRulesetsParsedCallbackSignature>;
using CallbackSubscription =
base::CallbackList<AllRulesetsParsedCallbackSignature>::Subscription;
public: public:
explicit BrowserSwitcherService(Profile* profile); explicit BrowserSwitcherService(Profile* profile);
~BrowserSwitcherService() override; ~BrowserSwitcherService() override;
void Init();
// KeyedService: // KeyedService:
void Shutdown() override; void Shutdown() override;
...@@ -152,10 +158,31 @@ class BrowserSwitcherService : public KeyedService { ...@@ -152,10 +158,31 @@ class BrowserSwitcherService : public KeyedService {
static base::TimeDelta refresh_delay_; static base::TimeDelta refresh_delay_;
private: private:
void StartDownload(std::vector<RulesetSource>&& sources); // chrome://browser-switch/internals has access to some
// implementation-specific methods to query this object's state, listen for
// events and trigger a re-download immediately.
friend class ::BrowserSwitchHandler;
void Init();
void OnExternalSitelistParsed(ParsedXml xml); void OnExternalSitelistParsed(ParsedXml xml);
void OnExternalGreylistParsed(ParsedXml xml); void OnExternalGreylistParsed(ParsedXml xml);
// Load cached rules from the PrefStore, then re-download the sitelists after
// |delay|.
void StartDownload(base::TimeDelta delay);
XmlDownloader* sitelist_downloader();
// Triggers a sitelist refresh immediately. Used by
// chrome://browser-switch/internals.
void DownloadNow();
// Registers a callback that triggers after the sitelists are done downloading
// and all rules are applied.
std::unique_ptr<CallbackSubscription> RegisterAllRulesetsParsedCallback(
AllRulesetsParsedCallback callback);
std::unique_ptr<XmlDownloader> sitelist_downloader_; std::unique_ptr<XmlDownloader> sitelist_downloader_;
Profile* profile_; Profile* profile_;
...@@ -163,6 +190,9 @@ class BrowserSwitcherService : public KeyedService { ...@@ -163,6 +190,9 @@ class BrowserSwitcherService : public KeyedService {
std::unique_ptr<BrowserSwitcherPrefs::CallbackSubscription> std::unique_ptr<BrowserSwitcherPrefs::CallbackSubscription>
prefs_subscription_; prefs_subscription_;
// CallbackList for OnAllRulesetsParsed() listeners.
base::CallbackList<AllRulesetsParsedCallbackSignature> callback_list_;
// Per-profile helpers. // Per-profile helpers.
std::unique_ptr<AlternativeBrowserDriver> driver_; std::unique_ptr<AlternativeBrowserDriver> driver_;
std::unique_ptr<BrowserSwitcherSitelist> sitelist_; std::unique_ptr<BrowserSwitcherSitelist> sitelist_;
......
...@@ -183,6 +183,8 @@ void BrowserSwitcherServiceWin::LoadRulesFromPrefs() { ...@@ -183,6 +183,8 @@ void BrowserSwitcherServiceWin::LoadRulesFromPrefs() {
} }
void BrowserSwitcherServiceWin::OnAllRulesetsParsed() { void BrowserSwitcherServiceWin::OnAllRulesetsParsed() {
BrowserSwitcherService::OnAllRulesetsParsed();
if (!prefs().IsEnabled()) if (!prefs().IsEnabled())
return; return;
......
...@@ -40,16 +40,16 @@ ...@@ -40,16 +40,16 @@
#url-checker-input { #url-checker-input {
width: 400px; width: 400px;
} }
#xml-not-fetched-yet,
#xml-last-fetch {
display: none;
}
</style> </style>
</head> </head>
<body> <body>
<h1>Legacy Browser Support Internals</h1> <h1>Legacy Browser Support Internals</h1>
<p>
If an XML sitelist is configured, wait 1 minute after browser
startup for it to download, and then refresh this page.
</p>
<!-- TODO(crbug/959379): Hide all this and show a message if <!-- TODO(crbug/959379): Hide all this and show a message if
BrowserSwitcherEnabled is false. --> BrowserSwitcherEnabled is false. -->
...@@ -73,6 +73,30 @@ ...@@ -73,6 +73,30 @@
<h2>Greylist</h2> <h2>Greylist</h2>
<table id="greylist"></table> <table id="greylist"></table>
<h2>XML sitelists</h2>
<table id="xml-sitelists"></table>
<div id="xml-description-wrapper">
<p id="xml-not-fetched-yet">
XML sitelists have not been fetched yet.
</p>
<p id="xml-last-fetch">
XML sitelists were last downloaded at
<span id="last-fetch-placeholder"></span>.
</p>
<p id="xml-next-fetch">
Next download is at
<span id="next-fetch-placeholder"></span>.
</p>
<p>
<button id="refresh-xml-button">Download now</button>
</p>
</div>
<template id="header-row-template"> <template id="header-row-template">
<tr> <tr>
<th>Rule</th> <th>Rule</th>
...@@ -91,6 +115,20 @@ ...@@ -91,6 +115,20 @@
</tr> </tr>
</template> </template>
<template id="xml-header-row-template">
<tr>
<th>Source policy</th>
<th>URL</th>
</tr>
</template>
<template id="xml-row-template">
<tr>
<td></td>
<td></td>
</tr>
</template>
<script src="/internals/browser_switch_internals.js"></script> <script src="/internals/browser_switch_internals.js"></script>
</body> </body>
</html> </html>
...@@ -21,13 +21,46 @@ let RuleSet; ...@@ -21,13 +21,46 @@ let RuleSet;
*/ */
let RuleSetList; let RuleSetList;
/**
* Returned by getRulesetSources().
* @typedef {{
* browser_switcher: Object<string, string>!,
* }}
*/
let RulesetSources;
/**
* Returned by getTimestamps().
* @typedef {{
* last_fetch: number,
* next_fetch: number,
* }}
*/
let TimestampPair;
/**
* Converts 'this_word' to 'ThisWord'
* @param {string} symbol
* @return {string}
*/
function snakeCaseToUpperCamelCase(symbol) {
if (!symbol) {
return symbol;
}
return symbol.replace(/(?:^|_)([a-z])/g, (_, letter) => {
return letter.toUpperCase();
});
}
/** /**
* Clears the table, and inserts a header row. * Clears the table, and inserts a header row.
* @param {HTMLTableElement} table * @param {HTMLTableElement} table
* @param {HTMLTemplateElement} headerTemplate
* Template to use to re-create the header row.
*/ */
function clearTable(table) { function clearTable(table, headerTemplate) {
table.innerHTML = ''; table.innerHTML = '';
const headerRow = document.importNode($('header-row-template').content, true); const headerRow = document.importNode(headerTemplate.content, true);
table.appendChild(headerRow); table.appendChild(headerRow);
} }
...@@ -67,8 +100,10 @@ function createRowForRule(rule, rulesetName) { ...@@ -67,8 +100,10 @@ function createRowForRule(rule, rulesetName) {
* @param {RuleSetList} rulesets * @param {RuleSetList} rulesets
*/ */
function updateTables(rulesets) { function updateTables(rulesets) {
clearTable(/** @type {HTMLTableElement} */ ($('sitelist'))); const headerTemplate =
clearTable(/** @type {HTMLTableElement} */ ($('greylist'))); /** @type {HTMLTemplateElement} */ ($('header-row-template'));
clearTable(/** @type {HTMLTableElement} */ ($('sitelist')), headerTemplate);
clearTable(/** @type {HTMLTableElement} */ ($('greylist')), headerTemplate);
for (const [rulesetName, ruleset] of Object.entries(rulesets)) { for (const [rulesetName, ruleset] of Object.entries(rulesets)) {
for (const [listName, rules] of Object.entries(ruleset)) { for (const [listName, rules] of Object.entries(ruleset)) {
...@@ -80,8 +115,6 @@ function updateTables(rulesets) { ...@@ -80,8 +115,6 @@ function updateTables(rulesets) {
} }
} }
cr.sendWithPromise('getAllRulesets').then(updateTables);
function checkUrl() { function checkUrl() {
const url = $('url-checker-input').value; const url = $('url-checker-input').value;
if (!url) { if (!url) {
...@@ -101,4 +134,91 @@ function checkUrl() { ...@@ -101,4 +134,91 @@ function checkUrl() {
} }
$('url-checker-input').addEventListener('input', checkUrl); $('url-checker-input').addEventListener('input', checkUrl);
checkUrl();
/**
* Formats |date| as "HH:MM:SS".
* @param {Date} date
* @return {string}
*/
function formatTime(date) {
const hh = date.getHours().toString().padStart(2, '0');
const mm = date.getMinutes().toString().padStart(2, '0');
const ss = date.getSeconds().toString().padStart(2, '0');
return `${hh}:${mm}:${ss}`;
}
/**
* Update the paragraphs under the "XML sitelists" section.
* @param {TimestampPair?} timestamps
*/
function updateTimestamps(timestamps) {
if (!timestamps) {
return;
}
const lastFetch = new Date(timestamps.last_fetch);
const nextFetch = new Date(timestamps.next_fetch);
if (lastFetch.valueOf() == 0) {
// Not fetched yet.
$('xml-not-fetched-yet').style.display = 'block';
$('xml-last-fetch').style.display = 'none';
} else {
// Already fetched.
$('xml-not-fetched-yet').style.display = 'none';
$('xml-last-fetch').style.display = 'block';
}
$('xml-next-fetch').style.display = nextFetch.valueOf() ? 'block' : 'none';
$('last-fetch-placeholder').innerText = formatTime(lastFetch);
$('next-fetch-placeholder').innerText = formatTime(nextFetch);
}
/**
* Update the table under the "XML sitelists" section.
* @param {RulesetSources} sources
*/
function updateXmlTable({browser_switcher: sources}) {
const headerTemplate =
/** @type {HTMLTemplateElement} */ ($('xml-header-row-template'));
clearTable(
/** @type {HTMLTableElement} */ ($('xml-sitelists')), headerTemplate);
for (const [prefName, url] of Object.entries(sources)) {
// Hacky: guess the policy name from the pref name by converting 'foo_bar'
// to 'BrowserSwitcherFooBar'. This relies on prefs having the same name as
// the associated policy.
const policyName = 'BrowserSwitcher' + snakeCaseToUpperCamelCase(prefName);
const row = document.importNode($('xml-row-template').content, true);
const cells = row.querySelectorAll('td');
cells[0].innerText = policyName;
cells[1].innerText = url || '(not configured)';
cells[1].className = 'url';
$('xml-sitelists').appendChild(row);
}
// Hide/show the description paragraphs depending on whether any XML sitelist
// is configured.
const enabled = Object.values(sources).some(x => !!x);
$('xml-description-wrapper').style.display = enabled ? 'block' : 'none';
}
/**
* Called by C++ when we need to update everything on the page.
*/
function updateEverything() {
cr.sendWithPromise('getAllRulesets').then(updateTables);
cr.sendWithPromise('getTimestamps').then(updateTimestamps);
cr.sendWithPromise('getRulesetSources').then(updateXmlTable);
checkUrl();
}
// TODO(crbug/959379): Keep the page up-to-date at all times: updateEverything()
// when LBS prefs are updated, and after sitelists get refreshed.
updateEverything();
$('refresh-xml-button').addEventListener('click', () => {
chrome.send('refreshXml');
});
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/browser_switcher/alternative_browser_driver.h" #include "chrome/browser/browser_switcher/alternative_browser_driver.h"
#include "chrome/browser/browser_switcher/browser_switcher_service.h" #include "chrome/browser/browser_switcher/browser_switcher_service.h"
...@@ -153,6 +154,8 @@ content::WebUIDataSource* CreateBrowserSwitchUIHTMLSource( ...@@ -153,6 +154,8 @@ content::WebUIDataSource* CreateBrowserSwitchUIHTMLSource(
return source; return source;
} }
} // namespace
class BrowserSwitchHandler : public content::WebUIMessageHandler { class BrowserSwitchHandler : public content::WebUIMessageHandler {
public: public:
BrowserSwitchHandler(); BrowserSwitchHandler();
...@@ -160,8 +163,19 @@ class BrowserSwitchHandler : public content::WebUIMessageHandler { ...@@ -160,8 +163,19 @@ class BrowserSwitchHandler : public content::WebUIMessageHandler {
// WebUIMessageHandler // WebUIMessageHandler
void RegisterMessages() override; void RegisterMessages() override;
void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
private: private:
void OnAllRulesetsParsed(browser_switcher::BrowserSwitcherService* service);
void OnBrowserSwitcherPrefsChanged(
browser_switcher::BrowserSwitcherPrefs* prefs,
const std::vector<std::string>& changed_prefs);
// For the internals page: tell JS to update all the page contents.
void UpdateEverything();
// Launches the given URL in the configured alternative browser. Acts as a // Launches the given URL in the configured alternative browser. Acts as a
// bridge for |AlternativeBrowserDriver::TryLaunch()|. Then, if that succeeds, // bridge for |AlternativeBrowserDriver::TryLaunch()|. Then, if that succeeds,
// closes the current tab. // closes the current tab.
...@@ -196,10 +210,42 @@ class BrowserSwitchHandler : public content::WebUIMessageHandler { ...@@ -196,10 +210,42 @@ class BrowserSwitchHandler : public content::WebUIMessageHandler {
// } // }
void HandleGetDecision(const base::ListValue* args); void HandleGetDecision(const base::ListValue* args);
// Resolves a promise with the time of the last policy fetch and next policy
// fetch, as JS timestamps.
//
// {
// "last_fetch": 123456789,
// "next_fetch": 234567890
// }
void HandleGetTimestamps(const base::ListValue* args);
// Resolves a promise with the configured sitelist XML download URLs. The keys
// are the name of the pref associated with the sitelist.
//
// {
// "browser_switcher": {
// "use_ie_sitelist": "http://example.com/sitelist.xml",
// "external_sitelist_url": "http://example.com/other_sitelist.xml",
// "external_greylist_url": null
// }
// }
void HandleGetRulesetSources(const base::ListValue* args);
// Immediately re-download and apply XML rules.
void HandleRefreshXml(const base::ListValue* args);
std::unique_ptr<browser_switcher::BrowserSwitcherPrefs::CallbackSubscription>
prefs_subscription_;
std::unique_ptr<
browser_switcher::BrowserSwitcherService::CallbackSubscription>
service_subscription_;
DISALLOW_COPY_AND_ASSIGN(BrowserSwitchHandler); DISALLOW_COPY_AND_ASSIGN(BrowserSwitchHandler);
}; };
BrowserSwitchHandler::BrowserSwitchHandler() = default; BrowserSwitchHandler::BrowserSwitchHandler() {}
BrowserSwitchHandler::~BrowserSwitchHandler() = default; BrowserSwitchHandler::~BrowserSwitchHandler() = default;
void BrowserSwitchHandler::RegisterMessages() { void BrowserSwitchHandler::RegisterMessages() {
...@@ -220,6 +266,47 @@ void BrowserSwitchHandler::RegisterMessages() { ...@@ -220,6 +266,47 @@ void BrowserSwitchHandler::RegisterMessages() {
"getDecision", "getDecision",
base::BindRepeating(&BrowserSwitchHandler::HandleGetDecision, base::BindRepeating(&BrowserSwitchHandler::HandleGetDecision,
base::Unretained(this))); base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getTimestamps",
base::BindRepeating(&BrowserSwitchHandler::HandleGetTimestamps,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getRulesetSources",
base::BindRepeating(&BrowserSwitchHandler::HandleGetRulesetSources,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"refreshXml", base::BindRepeating(&BrowserSwitchHandler::HandleRefreshXml,
base::Unretained(this)));
}
void BrowserSwitchHandler::OnJavascriptAllowed() {
auto* service = GetBrowserSwitcherService(web_ui());
prefs_subscription_ = service->prefs().RegisterPrefsChangedCallback(
base::BindRepeating(&BrowserSwitchHandler::OnBrowserSwitcherPrefsChanged,
base::Unretained(this)));
service_subscription_ =
service->RegisterAllRulesetsParsedCallback(base::BindRepeating(
&BrowserSwitchHandler::OnAllRulesetsParsed, base::Unretained(this)));
}
void BrowserSwitchHandler::OnJavascriptDisallowed() {
prefs_subscription_.reset();
service_subscription_.reset();
}
void BrowserSwitchHandler::OnAllRulesetsParsed(
browser_switcher::BrowserSwitcherService* service) {
UpdateEverything();
}
void BrowserSwitchHandler::OnBrowserSwitcherPrefsChanged(
browser_switcher::BrowserSwitcherPrefs* prefs,
const std::vector<std::string>& changed_prefs) {
UpdateEverything();
}
void BrowserSwitchHandler::UpdateEverything() {
CallJavascriptFunction("updateEverything", base::Value());
} }
void BrowserSwitchHandler::HandleLaunchAlternativeBrowserAndCloseTab( void BrowserSwitchHandler::HandleLaunchAlternativeBrowserAndCloseTab(
...@@ -335,7 +422,55 @@ void BrowserSwitchHandler::HandleGetDecision(const base::ListValue* args) { ...@@ -335,7 +422,55 @@ void BrowserSwitchHandler::HandleGetDecision(const base::ListValue* args) {
ResolveJavascriptCallback(args->GetList()[0], retval); ResolveJavascriptCallback(args->GetList()[0], retval);
} }
} // namespace void BrowserSwitchHandler::HandleGetTimestamps(const base::ListValue* args) {
DCHECK(args);
AllowJavascript();
auto* service = GetBrowserSwitcherService(web_ui());
auto* downloader = service->sitelist_downloader();
if (!downloader) {
ResolveJavascriptCallback(args->GetList()[0], base::Value());
return;
}
base::DictionaryValue retval;
retval.Set("last_fetch", std::make_unique<base::Value>(
downloader->last_refresh_time().ToJsTime()));
retval.Set("next_fetch", std::make_unique<base::Value>(
downloader->next_refresh_time().ToJsTime()));
ResolveJavascriptCallback(args->GetList()[0], retval);
}
void BrowserSwitchHandler::HandleGetRulesetSources(
const base::ListValue* args) {
DCHECK(args);
AllowJavascript();
auto* service = GetBrowserSwitcherService(web_ui());
std::vector<browser_switcher::RulesetSource> sources =
service->GetRulesetSources();
base::DictionaryValue retval;
for (const auto& source : sources) {
std::unique_ptr<base::Value> val;
if (source.url.is_valid())
val = std::make_unique<base::Value>(source.url.spec());
else
val = std::make_unique<base::Value>();
// |pref_name| is something like "browser_switcher.blah", so this will be in
// a nested object.
retval.Set(source.pref_name, std::move(val));
}
ResolveJavascriptCallback(args->GetList()[0], retval);
}
void BrowserSwitchHandler::HandleRefreshXml(const base::ListValue* args) {
DCHECK(args);
auto* service = GetBrowserSwitcherService(web_ui());
service->StartDownload(base::TimeDelta());
}
BrowserSwitchUI::BrowserSwitchUI(content::WebUI* web_ui) BrowserSwitchUI::BrowserSwitchUI(content::WebUI* web_ui)
: WebUIController(web_ui) { : WebUIController(web_ui) {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_BROWSER_SWITCH_BROWSER_SWITCH_UI_H_ #define CHROME_BROWSER_UI_WEBUI_BROWSER_SWITCH_BROWSER_SWITCH_UI_H_
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
#include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_controller.h"
class BrowserSwitchUI : public content::WebUIController { class BrowserSwitchUI : public content::WebUIController {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment