Chromium Code Reviews| Index: chrome/browser/ui/webui/snippets_internals_message_handler.cc |
| diff --git a/chrome/browser/ui/webui/snippets_internals_message_handler.cc b/chrome/browser/ui/webui/snippets_internals_message_handler.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..46210af24b9edeadd8aea3dbbf0557963497e710 |
| --- /dev/null |
| +++ b/chrome/browser/ui/webui/snippets_internals_message_handler.cc |
| @@ -0,0 +1,230 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "snippets_internals_message_handler.h" |
| + |
| +#include <set> |
| +#include <sstream> |
| +#include <vector> |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/command_line.h" |
| +#include "base/feature_list.h" |
| +#include "base/i18n/time_formatting.h" |
| +#include "base/logging.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/strings/string_piece.h" |
| +#include "base/strings/string_split.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/android/chrome_feature_list.h" |
| +#include "chrome/browser/ntp_snippets/ntp_snippets_service_factory.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "components/ntp_snippets/ntp_snippet.h" |
| +#include "components/ntp_snippets/switches.h" |
| +#include "content/public/browser/web_ui.h" |
| + |
| +namespace { |
| + |
| +scoped_ptr<base::DictionaryValue> PrepareSnippet( |
| + const ntp_snippets::NTPSnippet& snippet, |
| + int index, |
| + bool discarded) { |
| + scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); |
| + entry->SetString("title", snippet.title()); |
| + entry->SetString("siteTitle", snippet.site_title()); |
| + entry->SetString("snippet", snippet.snippet()); |
| + entry->SetString("published", |
| + TimeFormatShortDateAndTime(snippet.publish_date())); |
| + entry->SetString("expires", |
| + TimeFormatShortDateAndTime(snippet.expiry_date())); |
| + entry->SetString("url", snippet.url().spec()); |
| + entry->SetString("faviconUrl", snippet.favicon_url().spec()); |
| + entry->SetString("salientImageUrl", snippet.salient_image_url().spec()); |
| + |
| + if (discarded) |
| + entry->SetString("id", "discarded-snippet-" + base::IntToString(index)); |
| + else |
| + entry->SetString("id", "snippet-" + base::IntToString(index)); |
| + |
| + return entry; |
| +} |
| + |
| +} // namespace |
| + |
| +SnippetsInternalsMessageHandler::SnippetsInternalsMessageHandler() {} |
| + |
| +SnippetsInternalsMessageHandler::~SnippetsInternalsMessageHandler() {} |
| + |
| +void SnippetsInternalsMessageHandler::NTPSnippetsServiceShutdown() {} |
| + |
| +void SnippetsInternalsMessageHandler::NTPSnippetsServiceLoaded() { |
| + ntp_snippets::NTPSnippetsService* ntp_snippets_service = |
| + NTPSnippetsServiceFactory::GetInstance()->GetForProfile( |
| + Profile::FromWebUI(web_ui())); |
| + |
| + SendSnippets(ntp_snippets_service); |
| + SendDiscardedSnippets(ntp_snippets_service); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::RegisterMessages() { |
| + web_ui()->RegisterMessageCallback( |
| + "loaded", |
| + base::Bind(&SnippetsInternalsMessageHandler::HandleLoaded, |
| + base::Unretained(this))); |
| + |
| + web_ui()->RegisterMessageCallback( |
| + "clear", base::Bind(&SnippetsInternalsMessageHandler::HandleClear, |
| + base::Unretained(this))); |
| + |
| + web_ui()->RegisterMessageCallback( |
| + "download", base::Bind(&SnippetsInternalsMessageHandler::HandleDownload, |
| + base::Unretained(this))); |
| + |
| + web_ui()->RegisterMessageCallback( |
| + "clearDiscarded", |
| + base::Bind(&SnippetsInternalsMessageHandler::HandleClearDiscarded, |
| + base::Unretained(this))); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::HandleLoaded( |
| + const base::ListValue* args) { |
| + DCHECK(args->empty()); |
| + |
| + ntp_snippets::NTPSnippetsService* ntp_snippets_service = |
| + NTPSnippetsServiceFactory::GetInstance()->GetForProfile( |
| + Profile::FromWebUI(web_ui())); |
| + |
| + // On page reloads it is necessary to first remove the observer. |
|
Marc Treib
2016/04/13 08:45:51
Why?
Also: On the initial load, you're trying to r
jkrcal
2016/04/14 15:27:00
Done.
On page reload, nothing is destroyed, Handl
Marc Treib
2016/04/14 15:43:44
IMO this class should handle not adding itself twi
|
| + ntp_snippets_service->RemoveObserver(this); |
| + ntp_snippets_service->AddObserver(this); |
| + |
| + ntp_snippets_service->FetchSnippets(); |
| + |
| + SendInitialData(ntp_snippets_service); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::HandleClear(const base::ListValue* args) { |
| + DCHECK_EQ(0u, args->GetSize()); |
| + |
| + ntp_snippets::NTPSnippetsService* ntp_snippets_service = |
| + NTPSnippetsServiceFactory::GetInstance()->GetForProfile( |
| + Profile::FromWebUI(web_ui())); |
| + |
| + ntp_snippets_service->ClearSnippets(); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::HandleClearDiscarded( |
| + const base::ListValue* args) { |
| + DCHECK_EQ(0u, args->GetSize()); |
| + |
| + ntp_snippets::NTPSnippetsService* ntp_snippets_service = |
| + NTPSnippetsServiceFactory::GetInstance()->GetForProfile( |
| + Profile::FromWebUI(web_ui())); |
| + |
| + ntp_snippets_service->ClearDiscardedSnippets(); |
| + SendDiscardedSnippets(ntp_snippets_service); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::HandleDownload( |
| + const base::ListValue* args) { |
| + DCHECK_EQ(1u, args->GetSize()); |
| + |
| + std::string hosts_string; |
| + args->GetString(0, &hosts_string); |
| + base::StringPiece hosts_piece(hosts_string); |
|
Marc Treib
2016/04/13 08:45:51
I think this conversion happens automatically, i.e
jkrcal
2016/04/14 15:27:00
Done.
|
| + |
| + std::vector<std::string> hosts_vector = base::SplitString( |
| + hosts_piece, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| + std::set<std::string> hosts(hosts_vector.begin(), hosts_vector.end()); |
| + |
| + ntp_snippets::NTPSnippetsService* ntp_snippets_service = |
| + NTPSnippetsServiceFactory::GetInstance()->GetForProfile( |
| + Profile::FromWebUI(web_ui())); |
| + |
| + ntp_snippets_service->FetchSnippetsFromHosts(hosts); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::SendInitialData( |
| + ntp_snippets::NTPSnippetsService* service){ |
| + SendHosts(service); |
| + |
| + SendBoolean("flag-snippets", base::FeatureList::IsEnabled( |
| + chrome::android::kNTPSnippetsFeature)); |
| + |
| + bool restricted = !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + ntp_snippets::switches::kDontRestrict); |
| + SendBoolean("switch-restrict-to-hosts", restricted); |
| + const std::string help(restricted ? "cannot be empty" |
| + : "unrestricted if empty"); |
| + SendString("hosts-help", help); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::SendSnippets( |
| + ntp_snippets::NTPSnippetsService* service) { |
| + scoped_ptr<base::ListValue> snippets_list(new base::ListValue); |
| + |
| + int index = 0; |
| + for (auto& snippet : *service) |
| + snippets_list->Append(PrepareSnippet(snippet, index++, false)); |
| + |
| + base::DictionaryValue result; |
| + result.Set("list", std::move(snippets_list)); |
| + web_ui()->CallJavascriptFunction("chrome.snippets_internals.receiveSnippets", |
| + result); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::SendDiscardedSnippets( |
| + ntp_snippets::NTPSnippetsService* service) { |
| + scoped_ptr<base::ListValue> snippets_list(new base::ListValue); |
| + |
| + int index = 0; |
| + for (auto& snippet : service->GetDiscardedSnippets()) |
| + snippets_list->Append(PrepareSnippet(*snippet, index++, true)); |
| + |
| + base::DictionaryValue result; |
| + result.Set("list", std::move(snippets_list)); |
| + web_ui()->CallJavascriptFunction( |
| + "chrome.snippets_internals.receiveDiscardedSnippets", result); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::SendHosts( |
| + ntp_snippets::NTPSnippetsService* service) { |
| + scoped_ptr<base::ListValue> hosts_list(new base::ListValue); |
| + |
| + std::set<std::string> hosts = service->GetSuggestionsHosts(); |
| + std::ostringstream hosts_imploded; |
| + |
| + for (const std::string& host : hosts) { |
| + scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); |
| + entry->SetString("url", host); |
| + |
| + hosts_list->Append(std::move(entry)); |
| + hosts_imploded << host << " "; |
| + } |
| + |
| + base::DictionaryValue result; |
| + result.Set("list", std::move(hosts_list)); |
| + web_ui()->CallJavascriptFunction("chrome.snippets_internals.receiveHosts", |
| + result); |
| + |
| + base::StringValue hosts_value(hosts_imploded.str()); |
| + web_ui()->CallJavascriptFunction( |
| + "chrome.snippets_internals.receiveHostsInput", hosts_value); |
|
Marc Treib
2016/04/13 08:45:51
Any particular reason for sending this separately?
jkrcal
2016/04/14 15:27:00
Done.
|
| +} |
| + |
| +void SnippetsInternalsMessageHandler::SendBoolean(const std::string& name, |
| + bool value) { |
| + const std::string string_value(value ? "True" : "False"); |
|
Marc Treib
2016/04/13 08:45:51
Might as well just inline this below.
jkrcal
2016/04/14 15:27:00
Done.
|
| + SendString(name, string_value); |
| +} |
| + |
| +void SnippetsInternalsMessageHandler::SendString(const std::string& name, |
| + const std::string& value) { |
| + base::StringValue string_name(name); |
| + base::StringValue string_value(value); |
| + |
| + web_ui()->CallJavascriptFunction("chrome.snippets_internals.receiveProperty", |
| + string_name, string_value); |
| +} |