This source file includes following definitions.
- SkColorToRGBAColor
- weak_ptr_factory_
- AddInstantProcess
- IsInstantProcess
- AddObserver
- RemoveObserver
- DeleteMostVisitedItem
- UndoMostVisitedDeletion
- UndoAllMostVisitedDeletions
- UpdateThemeInfo
- UpdateMostVisitedItemsInfo
- Shutdown
- Observe
- SendSearchURLsToRenderer
- OnOmniboxStartMarginChanged
- OnRendererProcessTerminated
- OnMostVisitedItemsReceived
- NotifyAboutMostVisitedItems
- OnThemeChanged
- OnGoogleURLUpdated
- OnDefaultSearchProviderChanged
- ResetInstantSearchPrerenderer
#include "chrome/browser/search/instant_service.h"
#include <vector>
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/most_visited_tiles_experiment.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_io_context.h"
#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/search/instant_service_observer.h"
#include "chrome/browser/search/local_ntp_source.h"
#include "chrome/browser/search/most_visited_iframe_source.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/search/suggestions/suggestions_service.h"
#include "chrome/browser/search/suggestions/suggestions_source.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.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"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/webui/favicon_source.h"
#include "chrome/browser/ui/webui/ntp/thumbnail_list_source.h"
#include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/url_data_source.h"
#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "net/url_request/url_request.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/sys_color_change_listener.h"
#include "url/gurl.h"
using content::BrowserThread;
namespace {
const int kSectionBorderAlphaTransparency = 80;
RGBAColor SkColorToRGBAColor(const SkColor& sKColor) {
RGBAColor color;
color.r = SkColorGetR(sKColor);
color.g = SkColorGetG(sKColor);
color.b = SkColorGetB(sKColor);
color.a = SkColorGetA(sKColor);
return color;
}
}
InstantService::InstantService(Profile* profile)
: profile_(profile),
omnibox_start_margin_(chrome::kDisableStartMargin),
weak_ptr_factory_(this) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
return;
ResetInstantSearchPrerenderer();
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_CREATED,
content::NotificationService::AllSources());
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllSources());
history::TopSites* top_sites = profile_->GetTopSites();
if (top_sites) {
registrar_.Add(this,
chrome::NOTIFICATION_TOP_SITES_CHANGED,
content::Source<history::TopSites>(top_sites));
}
instant_io_context_ = new InstantIOContext();
if (profile_ && profile_->GetResourceContext()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&InstantIOContext::SetUserDataOnIO,
profile->GetResourceContext(), instant_io_context_));
}
#if defined(ENABLE_THEMES)
registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
content::Source<ThemeService>(
ThemeServiceFactory::GetForProfile(profile_)));
content::URLDataSource::Add(profile_, new ThemeSource(profile_));
#endif
content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false));
content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true));
content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));
content::URLDataSource::Add(
profile_, new FaviconSource(profile_, FaviconSource::FAVICON));
content::URLDataSource::Add(profile_, new LocalNtpSource(profile_));
content::URLDataSource::Add(profile_, new MostVisitedIframeSource());
if (suggestions::SuggestionsService::IsEnabled()) {
content::URLDataSource::Add(
profile_, new suggestions::SuggestionsSource(profile_));
}
profile_pref_registrar_.Init(profile_->GetPrefs());
profile_pref_registrar_.Add(
prefs::kDefaultSearchProviderID,
base::Bind(&InstantService::OnDefaultSearchProviderChanged,
base::Unretained(this)));
registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
content::Source<Profile>(profile_->GetOriginalProfile()));
}
InstantService::~InstantService() {
}
void InstantService::AddInstantProcess(int process_id) {
process_ids_.insert(process_id);
if (instant_io_context_.get()) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&InstantIOContext::AddInstantProcessOnIO,
instant_io_context_,
process_id));
}
}
bool InstantService::IsInstantProcess(int process_id) const {
return process_ids_.find(process_id) != process_ids_.end();
}
void InstantService::AddObserver(InstantServiceObserver* observer) {
observers_.AddObserver(observer);
}
void InstantService::RemoveObserver(InstantServiceObserver* observer) {
observers_.RemoveObserver(observer);
}
void InstantService::DeleteMostVisitedItem(const GURL& url) {
history::TopSites* top_sites = profile_->GetTopSites();
if (!top_sites)
return;
top_sites->AddBlacklistedURL(url);
}
void InstantService::UndoMostVisitedDeletion(const GURL& url) {
history::TopSites* top_sites = profile_->GetTopSites();
if (!top_sites)
return;
top_sites->RemoveBlacklistedURL(url);
}
void InstantService::UndoAllMostVisitedDeletions() {
history::TopSites* top_sites = profile_->GetTopSites();
if (!top_sites)
return;
top_sites->ClearBlacklistedURLs();
}
void InstantService::UpdateThemeInfo() {
if (!theme_info_)
OnThemeChanged(ThemeServiceFactory::GetForProfile(profile_));
else
OnThemeChanged(NULL);
}
void InstantService::UpdateMostVisitedItemsInfo() {
NotifyAboutMostVisitedItems();
}
void InstantService::Shutdown() {
process_ids_.clear();
if (instant_io_context_.get()) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&InstantIOContext::ClearInstantProcessesOnIO,
instant_io_context_));
}
instant_io_context_ = NULL;
}
void InstantService::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case content::NOTIFICATION_RENDERER_PROCESS_CREATED:
SendSearchURLsToRenderer(
content::Source<content::RenderProcessHost>(source).ptr());
break;
case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
OnRendererProcessTerminated(
content::Source<content::RenderProcessHost>(source)->GetID());
break;
case chrome::NOTIFICATION_TOP_SITES_CHANGED: {
history::TopSites* top_sites = profile_->GetTopSites();
if (top_sites) {
top_sites->GetMostVisitedURLs(
base::Bind(&InstantService::OnMostVisitedItemsReceived,
weak_ptr_factory_.GetWeakPtr()), false);
}
break;
}
#if defined(ENABLE_THEMES)
case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: {
OnThemeChanged(content::Source<ThemeService>(source).ptr());
break;
}
#endif
case chrome::NOTIFICATION_GOOGLE_URL_UPDATED: {
OnGoogleURLUpdated(
content::Source<Profile>(source).ptr(),
content::Details<GoogleURLTracker::UpdatedDetails>(details).ptr());
break;
}
default:
NOTREACHED() << "Unexpected notification type in InstantService.";
}
}
void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) {
rph->Send(new ChromeViewMsg_SetSearchURLs(
chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_)));
}
void InstantService::OnOmniboxStartMarginChanged(int start_margin) {
omnibox_start_margin_ = start_margin;
FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
OmniboxStartMarginChanged(omnibox_start_margin_));
}
void InstantService::OnRendererProcessTerminated(int process_id) {
process_ids_.erase(process_id);
if (instant_io_context_.get()) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&InstantIOContext::RemoveInstantProcessOnIO,
instant_io_context_,
process_id));
}
}
void InstantService::OnMostVisitedItemsReceived(
const history::MostVisitedURLList& data) {
history::MostVisitedURLList reordered_data(data);
history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data);
std::vector<InstantMostVisitedItem> new_most_visited_items;
for (size_t i = 0; i < reordered_data.size(); i++) {
const history::MostVisitedURL& url = reordered_data[i];
InstantMostVisitedItem item;
item.url = url.url;
item.title = url.title;
new_most_visited_items.push_back(item);
}
most_visited_items_ = new_most_visited_items;
NotifyAboutMostVisitedItems();
}
void InstantService::NotifyAboutMostVisitedItems() {
FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
MostVisitedItemsChanged(most_visited_items_));
}
void InstantService::OnThemeChanged(ThemeService* theme_service) {
if (!theme_service) {
DCHECK(theme_info_.get());
FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
ThemeInfoChanged(*theme_info_));
return;
}
theme_info_.reset(new ThemeBackgroundInfo());
theme_info_->using_default_theme = theme_service->UsingDefaultTheme();
SkColor background_color =
theme_service->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
SkColor text_color =
theme_service->GetColor(ThemeProperties::COLOR_NTP_TEXT);
SkColor link_color =
theme_service->GetColor(ThemeProperties::COLOR_NTP_LINK);
SkColor text_color_light =
theme_service->GetColor(ThemeProperties::COLOR_NTP_TEXT_LIGHT);
SkColor header_color =
theme_service->GetColor(ThemeProperties::COLOR_NTP_HEADER);
SkColor section_border_color =
SkColorSetARGB(kSectionBorderAlphaTransparency,
SkColorGetR(header_color),
SkColorGetG(header_color),
SkColorGetB(header_color));
if (gfx::IsInvertedColorScheme()) {
background_color = color_utils::InvertColor(background_color);
text_color = color_utils::InvertColor(text_color);
link_color = color_utils::InvertColor(link_color);
text_color_light = color_utils::InvertColor(text_color_light);
header_color = color_utils::InvertColor(header_color);
section_border_color = color_utils::InvertColor(section_border_color);
}
theme_info_->background_color = SkColorToRGBAColor(background_color);
theme_info_->text_color = SkColorToRGBAColor(text_color);
theme_info_->link_color = SkColorToRGBAColor(link_color);
theme_info_->text_color_light = SkColorToRGBAColor(text_color_light);
theme_info_->header_color = SkColorToRGBAColor(header_color);
theme_info_->section_border_color = SkColorToRGBAColor(section_border_color);
int logo_alternate = theme_service->GetDisplayProperty(
ThemeProperties::NTP_LOGO_ALTERNATE);
theme_info_->logo_alternate = logo_alternate == 1;
if (theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
theme_info_->theme_id = theme_service->GetThemeID();
int alignment = theme_service->GetDisplayProperty(
ThemeProperties::NTP_BACKGROUND_ALIGNMENT);
if (alignment & ThemeProperties::ALIGN_LEFT)
theme_info_->image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_LEFT;
else if (alignment & ThemeProperties::ALIGN_RIGHT)
theme_info_->image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_RIGHT;
else
theme_info_->image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
if (alignment & ThemeProperties::ALIGN_TOP)
theme_info_->image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_TOP;
else if (alignment & ThemeProperties::ALIGN_BOTTOM)
theme_info_->image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_BOTTOM;
else
theme_info_->image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
int tiling = theme_service->GetDisplayProperty(
ThemeProperties::NTP_BACKGROUND_TILING);
switch (tiling) {
case ThemeProperties::NO_REPEAT:
theme_info_->image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT;
break;
case ThemeProperties::REPEAT_X:
theme_info_->image_tiling = THEME_BKGRND_IMAGE_REPEAT_X;
break;
case ThemeProperties::REPEAT_Y:
theme_info_->image_tiling = THEME_BKGRND_IMAGE_REPEAT_Y;
break;
case ThemeProperties::REPEAT:
theme_info_->image_tiling = THEME_BKGRND_IMAGE_REPEAT;
break;
}
gfx::ImageSkia* image = theme_service->GetImageSkiaNamed(
IDR_THEME_NTP_BACKGROUND);
DCHECK(image);
theme_info_->image_height = image->height();
theme_info_->has_attribution =
theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION);
}
FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
ThemeInfoChanged(*theme_info_));
}
void InstantService::OnGoogleURLUpdated(
Profile* profile,
GoogleURLTracker::UpdatedDetails* details) {
GURL last_prompted_url(
profile->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL));
if (last_prompted_url.is_empty())
return;
ResetInstantSearchPrerenderer();
if (net::StripWWWFromHost(details->first) ==
net::StripWWWFromHost(details->second))
return;
FOR_EACH_OBSERVER(InstantServiceObserver, observers_, GoogleURLUpdated());
}
void InstantService::OnDefaultSearchProviderChanged(
const std::string& pref_name) {
DCHECK_EQ(pref_name, std::string(prefs::kDefaultSearchProviderID));
const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
profile_)->GetDefaultSearchProvider();
if (!template_url) {
return;
}
ResetInstantSearchPrerenderer();
FOR_EACH_OBSERVER(
InstantServiceObserver, observers_, DefaultSearchProviderChanged());
}
void InstantService::ResetInstantSearchPrerenderer() {
if (!chrome::ShouldPrefetchSearchResults())
return;
GURL url(chrome::GetSearchResultPrefetchBaseURL(profile_));
if (url.is_valid())
instant_prerenderer_.reset(new InstantSearchPrerenderer(profile_, url));
else
instant_prerenderer_.reset();
}