| Index: chrome/browser/search/local_ntp_source.cc
|
| diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
|
| index d1a46a43edc3f9e3d5d641e51f2a9d61bd55c9ba..e988450c3244f78c398ff9fee07761bb1db3e2ab 100644
|
| --- a/chrome/browser/search/local_ntp_source.cc
|
| +++ b/chrome/browser/search/local_ntp_source.cc
|
| @@ -4,11 +4,11 @@
|
|
|
| #include "chrome/browser/search/local_ntp_source.h"
|
|
|
| -#include <stddef.h>
|
| -
|
| #include "base/base64.h"
|
| #include "base/command_line.h"
|
| +#include "base/feature_list.h"
|
| #include "base/json/json_string_value_serializer.h"
|
| +#include "base/json/json_writer.h"
|
| #include "base/logging.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/memory/ref_counted_memory.h"
|
| @@ -16,8 +16,12 @@
|
| #include "base/strings/stringprintf.h"
|
| #include "base/values.h"
|
| #include "build/build_config.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/search/instant_io_context.h"
|
| #include "chrome/browser/search/local_files_ntp_source.h"
|
| +#include "chrome/browser/search/one_google_bar/one_google_bar_data.h"
|
| +#include "chrome/browser/search/one_google_bar/one_google_bar_service.h"
|
| +#include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h"
|
| #include "chrome/browser/search_engines/template_url_service_factory.h"
|
| #include "chrome/browser/themes/theme_properties.h"
|
| #include "chrome/browser/themes/theme_service.h"
|
| @@ -43,12 +47,20 @@
|
|
|
| namespace {
|
|
|
| +base::Feature kOneGoogleBarOnLocalNtpFeature{"OneGoogleBarOnLocalNtp",
|
| + base::FEATURE_DISABLED_BY_DEFAULT};
|
| +
|
| // Signifies a locally constructed resource, i.e. not from grit/.
|
| const int kLocalResource = -1;
|
|
|
| const char kConfigDataFilename[] = "config.js";
|
| const char kThemeCSSFilename[] = "theme.css";
|
| const char kMainHtmlFilename[] = "local-ntp.html";
|
| +const char kOneGoogleBarScriptFilename[] = "one-google.js";
|
| +const char kOneGoogleBarInHeadStyleFilename[] = "one-google/in-head.css";
|
| +const char kOneGoogleBarInHeadScriptFilename[] = "one-google/in-head.js";
|
| +const char kOneGoogleBarAfterBarScriptFilename[] = "one-google/after-bar.js";
|
| +const char kOneGoogleBarEndOfBodyScriptFilename[] = "one-google/end-of-body.js";
|
|
|
| const struct Resource{
|
| const char* filename;
|
| @@ -63,6 +75,11 @@ const struct Resource{
|
| {"images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png"},
|
| {"images/close_4_button.png", IDR_CLOSE_4_BUTTON, "image/png"},
|
| {"images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png"},
|
| + {kOneGoogleBarScriptFilename, kLocalResource, "text/javascript"},
|
| + {kOneGoogleBarInHeadStyleFilename, kLocalResource, "text/css"},
|
| + {kOneGoogleBarInHeadScriptFilename, kLocalResource, "text/javascript"},
|
| + {kOneGoogleBarAfterBarScriptFilename, kLocalResource, "text/javascript"},
|
| + {kOneGoogleBarEndOfBodyScriptFilename, kLocalResource, "text/javascript"},
|
| };
|
|
|
| // Strips any query parameters from the specified path.
|
| @@ -160,6 +177,16 @@ bool DefaultSearchProviderIsGoogleImpl(
|
| SEARCH_ENGINE_GOOGLE);
|
| }
|
|
|
| +std::unique_ptr<base::DictionaryValue> ConvertOGBDataToDict(
|
| + const OneGoogleBarData& og) {
|
| + auto result = base::MakeUnique<base::DictionaryValue>();
|
| + // Only provide the html parts here. The js and css are injected separately
|
| + // via <script src=...> and <link rel="stylesheet" href=...>.
|
| + result->SetString("html", og.bar_html);
|
| + result->SetString("end_of_body_html", og.end_of_body_html);
|
| + return result;
|
| +}
|
| +
|
| } // namespace
|
|
|
| class LocalNtpSource::GoogleSearchProviderTracker
|
| @@ -205,11 +232,23 @@ class LocalNtpSource::GoogleSearchProviderTracker
|
|
|
| LocalNtpSource::LocalNtpSource(Profile* profile)
|
| : profile_(profile),
|
| + one_google_bar_service_(nullptr),
|
| + one_google_bar_service_observer_(this),
|
| default_search_provider_is_google_(false),
|
| default_search_provider_is_google_io_thread_(false),
|
| weak_ptr_factory_(this) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
| + if (base::FeatureList::IsEnabled(kOneGoogleBarOnLocalNtpFeature)) {
|
| + one_google_bar_service_ =
|
| + OneGoogleBarServiceFactory::GetForProfile(profile_);
|
| + }
|
| +
|
| + // |one_google_bar_service_| is null in incognito, or when the feature is
|
| + // disabled.
|
| + if (one_google_bar_service_)
|
| + one_google_bar_service_observer_.Add(one_google_bar_service_);
|
| +
|
| TemplateURLService* template_url_service =
|
| TemplateURLServiceFactory::GetForProfile(profile_);
|
| if (template_url_service) {
|
| @@ -247,6 +286,46 @@ void LocalNtpSource::StartDataRequest(
|
| return;
|
| }
|
|
|
| + if (base::StartsWith(stripped_path, "one-google",
|
| + base::CompareCase::SENSITIVE)) {
|
| + if (!one_google_bar_service_) {
|
| + callback.Run(nullptr);
|
| + return;
|
| + }
|
| +
|
| + const base::Optional<OneGoogleBarData>& data =
|
| + one_google_bar_service_->one_google_bar_data();
|
| +
|
| + // The OneGoogleBar injector helper.
|
| + if (stripped_path == kOneGoogleBarScriptFilename) {
|
| + one_google_callbacks_.push_back(callback);
|
| +
|
| + // If there already is (cached) OGB data, serve it immediately.
|
| + if (data.has_value())
|
| + ServeOneGoogleBar(*data);
|
| +
|
| + // In any case, request a refresh.
|
| + one_google_bar_service_->Refresh();
|
| + } else {
|
| + // The actual OneGoogleBar sources.
|
| + std::string result;
|
| + if (data.has_value()) {
|
| + if (stripped_path == kOneGoogleBarInHeadStyleFilename) {
|
| + result = data->in_head_style;
|
| + } else if (stripped_path == kOneGoogleBarInHeadScriptFilename) {
|
| + result = data->in_head_script;
|
| + } else if (stripped_path == kOneGoogleBarAfterBarScriptFilename) {
|
| + result = data->after_bar_script;
|
| + } else if (stripped_path == kOneGoogleBarEndOfBodyScriptFilename) {
|
| + result = data->end_of_body_script;
|
| + }
|
| + }
|
| + callback.Run(base::RefCountedString::TakeString(&result));
|
| + }
|
| +
|
| + return;
|
| + }
|
| +
|
| #if !defined(GOOGLE_CHROME_BUILD)
|
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
| if (command_line->HasSwitch(switches::kLocalNtpReload)) {
|
| @@ -343,17 +422,65 @@ std::string LocalNtpSource::GetContentSecurityPolicyScriptSrc() const {
|
| GetIntegritySha256Value(
|
| GetConfigData(default_search_provider_is_google_io_thread_)) +
|
| "' "
|
| - "'sha256-g38WaUaxnOIWY7E2LtLZ5ff9r5sn1dBj80jevt/kmx0=';";
|
| + "'sha256-ROPmcormZEipZzy3Ff+o345FFrhHWsAZjBpGIyZzCYY=';";
|
| }
|
|
|
| std::string LocalNtpSource::GetContentSecurityPolicyChildSrc() const {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
|
|
| - // Allow embedding of most visited iframes.
|
| + if (one_google_bar_service_) {
|
| + // Allow embedding of the most visited iframe, as well as the account
|
| + // switcher and the notifications dropdown from the One Google Bar.
|
| + // TODO(treib): Figure out a way to also allow staging instances.
|
| + return base::StringPrintf(
|
| + "child-src %s https://accounts.google.com/ https://docs.google.com "
|
| + "https://notifications.google.com;",
|
| + chrome::kChromeSearchMostVisitedUrl);
|
| + }
|
| + // Allow embedding of the most visited iframe.
|
| return base::StringPrintf("child-src %s;",
|
| chrome::kChromeSearchMostVisitedUrl);
|
| }
|
|
|
| +void LocalNtpSource::OnOneGoogleBarDataChanged() {
|
| + const base::Optional<OneGoogleBarData>& data =
|
| + one_google_bar_service_->one_google_bar_data();
|
| + if (data.has_value())
|
| + ServeOneGoogleBar(*data);
|
| + else
|
| + ServeNullOneGoogleBar();
|
| +}
|
| +
|
| +void LocalNtpSource::OnOneGoogleBarFetchFailed() {
|
| + ServeNullOneGoogleBar();
|
| +}
|
| +
|
| +void LocalNtpSource::OnOneGoogleBarServiceShuttingDown() {
|
| + one_google_bar_service_observer_.RemoveAll();
|
| + one_google_bar_service_ = nullptr;
|
| +}
|
| +
|
| +void LocalNtpSource::ServeOneGoogleBar(const OneGoogleBarData& data) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + if (one_google_callbacks_.empty())
|
| + return;
|
| +
|
| + std::string json;
|
| + base::JSONWriter::Write(*ConvertOGBDataToDict(data), &json);
|
| + for (auto& callback : one_google_callbacks_) {
|
| + std::string data = "var og = " + json + ";";
|
| + callback.Run(base::RefCountedString::TakeString(&data));
|
| + }
|
| + one_google_callbacks_.clear();
|
| +}
|
| +
|
| +void LocalNtpSource::ServeNullOneGoogleBar() {
|
| + for (auto& callback : one_google_callbacks_)
|
| + callback.Run(nullptr);
|
| + one_google_callbacks_.clear();
|
| +}
|
| +
|
| void LocalNtpSource::DefaultSearchProviderIsGoogleChanged(bool is_google) {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
|
|