Index: chrome/browser/instant/instant_service.cc |
diff --git a/chrome/browser/instant/instant_service.cc b/chrome/browser/instant/instant_service.cc |
index 3c8a6b2ba2c9c93b4ca5f714d27175e4ffca84e8..af2ed8b73655b37b8212ea709b223126eeecb488 100644 |
--- a/chrome/browser/instant/instant_service.cc |
+++ b/chrome/browser/instant/instant_service.cc |
@@ -4,81 +4,282 @@ |
#include "chrome/browser/instant/instant_service.h" |
+#include "base/utf_string_conversions.h" |
+#include "chrome/browser/history/top_sites.h" |
#include "chrome/browser/instant/instant_io_context.h" |
+#include "chrome/browser/instant/instant_preloader.h" |
+#include "chrome/browser/instant/search.h" |
#include "chrome/browser/profiles/profile.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/ntp/thumbnail_source.h" |
#include "chrome/common/chrome_notification_types.h" |
+#include "chrome/common/pref_names.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/notification_service.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 "ui/base/resource/resource_bundle.h" |
+#include "ui/gfx/image/image_skia.h" |
+#include "ui/gfx/sys_color_change_listener.h" |
-using content::BrowserThread; |
+namespace { |
+ |
+const size_t kMaxDebugEvents = 2000; |
+ |
+} // namespace |
InstantService::InstantService(Profile* profile) |
- : profile_(profile) { |
+ : profile_(profile), |
+ omnibox_font_size_(0), |
+ omnibox_start_margin_(0), |
+ instant_pref_enabled_(false), |
+ instant_enabled_(false) { |
// Stub for unit tests. |
samarth
2013/03/11 19:03:24
Makes me slightly nervous. How about wrapping this
|
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) |
+ if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) |
return; |
- registrar_.Add(this, |
- content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
- content::NotificationService::AllSources()); |
+ notification_registrar_.Add(this, |
+ content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
+ content::NotificationService::AllSources()); |
- instant_io_context_ = new InstantIOContext(); |
+ io_context_ = new InstantIOContext(); |
- if (profile_ && profile_->GetResourceContext()) { |
- BrowserThread::PostTask( |
- BrowserThread::IO, FROM_HERE, |
+ if (profile && profile->GetResourceContext()) { |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
base::Bind(&InstantIOContext::SetUserDataOnIO, |
- profile->GetResourceContext(), instant_io_context_)); |
+ profile->GetResourceContext(), io_context_)); |
} |
content::URLDataSource::Add(profile, new ThumbnailSource(profile)); |
+ |
+ // In one mode of the InstantExtended experiments, the kInstantExtendedEnabled |
+ // preference's default value is set to the existing value of kInstantEnabled. |
+ // Because this requires reading the value of the kInstantEnabled value, we |
+ // reset the default for kInstantExtendedEnabled here. |
+ chrome::search::SetInstantExtendedPrefDefault(profile); |
+ |
+ pref_change_registrar_.Init(profile->GetPrefs()); |
+ pref_change_registrar_.Add( |
+ prefs::kInstantEnabled, |
+ base::Bind(&InstantService::PrefChanged, base::Unretained(this))); |
+ pref_change_registrar_.Add( |
+ prefs::kInstantExtendedEnabled, |
+ base::Bind(&InstantService::PrefChanged, base::Unretained(this))); |
+ pref_change_registrar_.Add( |
+ prefs::kSearchSuggestEnabled, |
+ base::Bind(&InstantService::PrefChanged, base::Unretained(this))); |
+ PrefChanged(std::string()); |
+ |
+ ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile); |
+ notification_registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
+ content::Source<ThemeService>(theme_service)); |
+ ParseTheme(theme_service); |
+ |
+ history::TopSites* top_sites = profile->GetTopSites(); |
+ notification_registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED, |
+ content::Source<history::TopSites>(top_sites)); |
+ RequestMostVisitedItems(top_sites); |
+ |
+// TODO(sail): Remove this once the Mac omnibox font size is updated. |
+#if defined(OS_MACOSX) |
+ ui::ResourceBundle::FontStyle font_style = ui::ResourceBundle::BaseFont; |
+#else |
+ ui::ResourceBundle::FontStyle font_style = ui::ResourceBundle::MediumFont; |
+#endif // defined(OS_MACOSX) |
+ const gfx::Font& omnibox_font = |
+ ui::ResourceBundle::GetSharedInstance().GetFont(font_style); |
+ omnibox_font_name_ = UTF8ToUTF16(omnibox_font.GetFontName()); |
+ omnibox_font_size_ = omnibox_font.GetFontSize(); |
} |
InstantService::~InstantService() { |
} |
-void InstantService::AddInstantProcess(int process_id) { |
- process_ids_.insert(process_id); |
+void InstantService::LogDebugEvent(const std::string& message) { |
+ DVLOG(1) << message; |
+ debug_events_.push_front(std::make_pair(base::Time::Now().ToInternalValue(), |
+ message)); |
+ if (debug_events_.size() > kMaxDebugEvents) |
+ debug_events_.pop_back(); |
+} |
- if (instant_io_context_) { |
- BrowserThread::PostTask( |
- BrowserThread::IO, FROM_HERE, |
- base::Bind(&InstantIOContext::AddInstantProcessOnIO, |
- instant_io_context_, process_id)); |
- } |
+void InstantService::ClearDebugEvents() { |
+ debug_events_.clear(); |
+} |
+ |
+void InstantService::AddObserver(InstantServiceObserver* observer) { |
+ observers_.AddObserver(observer); |
+ |
+ // If we just added our first observer, we have our first browser window. |
samarth
2013/03/11 19:03:24
This seems too subtle and easy to go wrong. I'd pr
|
+ // Create the InstantPreloader (which will also register as an observer). |
+ if (observers_.size() == 1) |
+ preloader_.reset(new InstantPreloader(this)); |
+} |
+ |
+void InstantService::RemoveObserver(InstantServiceObserver* observer) { |
+ observers_.RemoveObserver(observer); |
+ |
+ // If there's only one observer left, it must be the InstantPreloader. All |
samarth
2013/03/11 19:03:24
Again, I'd prefer a more explicit signal if possib
|
+ // browser windows have closed, so kill the preloader, to work around |
+ // http://crbug.com/180810. |
+ if (observers_.size() == 1) |
+ preloader_.reset(); |
} |
bool InstantService::IsInstantProcess(int process_id) const { |
return process_ids_.find(process_id) != process_ids_.end(); |
} |
-void InstantService::Shutdown() { |
- process_ids_.clear(); |
+void InstantService::AddInstantProcess(int process_id) { |
+ process_ids_.insert(process_id); |
+ |
+ if (io_context_) { |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&InstantIOContext::AddInstantProcessOnIO, |
+ io_context_, process_id)); |
+ } |
+} |
+ |
+void InstantService::RemoveInstantProcess(int process_id) { |
+ process_ids_.erase(process_id); |
- if (instant_io_context_) { |
- BrowserThread::PostTask( |
- BrowserThread::IO, FROM_HERE, |
- base::Bind(&InstantIOContext::ClearInstantProcessesOnIO, |
- instant_io_context_)); |
+ if (io_context_) { |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&InstantIOContext::RemoveInstantProcessOnIO, |
+ io_context_, process_id)); |
} |
- instant_io_context_ = NULL; |
+} |
+ |
+void InstantService::InstantSupportDetermined() { |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED, |
+ content::NotificationService::AllSources(), |
+ content::NotificationService::NoDetails()); |
} |
void InstantService::Observe(int type, |
const content::NotificationSource& source, |
const content::NotificationDetails& details) { |
- DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); |
- int process_id = content::Source<content::RenderProcessHost>(source)->GetID(); |
- process_ids_.erase(process_id); |
+ switch (type) { |
+ case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
+ RemoveInstantProcess( |
+ content::Source<content::RenderProcessHost>(source)->GetID()); |
+ break; |
- if (instant_io_context_) { |
- BrowserThread::PostTask( |
- BrowserThread::IO, FROM_HERE, |
- base::Bind(&InstantIOContext::RemoveInstantProcessOnIO, |
- instant_io_context_, process_id)); |
+ case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: |
+ ParseTheme(content::Source<ThemeService>(source).ptr()); |
+ break; |
+ |
+ case chrome::NOTIFICATION_TOP_SITES_CHANGED: |
+ RequestMostVisitedItems(content::Source<history::TopSites>(source).ptr()); |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+void InstantService::PrefChanged(const std::string& pref_name) { |
+ if (pref_name == prefs::kInstantEnabled) |
samarth
2013/03/11 19:03:24
I'm a little confused why you reset some of the pr
|
+ chrome::search::SetInstantExtendedPrefDefault(profile_); |
+ |
+ bool instant_pref_enabled = chrome::search::IsInstantPrefEnabled(profile_); |
+ bool instant_enabled = chrome::search::IsInstantEnabled(profile_); |
+ if (instant_pref_enabled_ == instant_pref_enabled && |
+ instant_enabled_ == instant_enabled) |
+ return; |
+ |
+ instant_pref_enabled_ = instant_pref_enabled; |
+ instant_enabled_ = instant_enabled; |
+ FOR_EACH_OBSERVER(InstantServiceObserver, observers_, InstantStatusChanged()); |
+} |
+ |
+void InstantService::ParseTheme(ThemeService* theme_service) { |
+ theme_info_ = ThemeBackgroundInfo(); |
+ |
+ // Set theme background color. |
+ SkColor background_color = |
+ theme_service->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND); |
+ if (gfx::IsInvertedColorScheme()) |
+ background_color = color_utils::InvertColor(background_color); |
+ theme_info_.color_r = SkColorGetR(background_color); |
+ theme_info_.color_g = SkColorGetG(background_color); |
+ theme_info_.color_b = SkColorGetB(background_color); |
+ theme_info_.color_a = SkColorGetA(background_color); |
+ |
+ if (!theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) |
+ return; |
+ |
+ // Set theme id for theme background image url. |
+ theme_info_.theme_id = UTF8ToUTF16(theme_service->GetThemeID()); |
+ |
+ // Set theme background image horizontal alignment. |
+ int alignment = 0; |
+ theme_service->GetDisplayProperty(ThemeProperties::NTP_BACKGROUND_ALIGNMENT, |
+ &alignment); |
+ if (alignment & ThemeProperties::ALIGN_LEFT) { |
samarth
2013/03/11 19:03:24
nit: no braces? (not sure if Chromium makes an ex
|
+ 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 { // ALIGN_CENTER |
+ theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER; |
+ } |
+ |
+ // Set theme background image vertical alignment. |
+ 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 { // ALIGN_CENTER |
+ theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER; |
+ } |
+ |
+ // Set theme background image tiling. |
+ int tiling = 0; |
+ theme_service->GetDisplayProperty(ThemeProperties::NTP_BACKGROUND_TILING, |
+ &tiling); |
+ switch (tiling) { |
+ case ThemeProperties::NO_REPEAT: |
+ theme_info_.image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT; |
samarth
2013/03/11 19:03:24
Indent looks wrong
|
+ 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; |
} |
+ |
+ // Set theme background image height. |
+ gfx::ImageSkia* image = theme_service->GetImageSkiaNamed( |
+ IDR_THEME_NTP_BACKGROUND); |
+ DCHECK(image); |
+ theme_info_.image_height = image->height(); |
+ |
+ FOR_EACH_OBSERVER(InstantServiceObserver, observers_, ThemeInfoChanged()); |
+} |
+ |
+void InstantService::RequestMostVisitedItems(history::TopSites* top_sites) { |
+ top_sites->GetMostVisitedURLs( |
+ base::Bind(&InstantService::MostVisitedItemsReceived, |
+ base::Unretained(this))); |
+} |
+ |
+void InstantService::MostVisitedItemsReceived( |
+ const history::MostVisitedURLList& data) { |
+ most_visited_items_.clear(); |
+ for (size_t i = 0; i < data.size(); ++i) |
+ most_visited_items_.push_back(MostVisitedItem(data[i].url, data[i].title)); |
+ |
+ FOR_EACH_OBSERVER(InstantServiceObserver, observers_, |
+ MostVisitedItemsChanged()); |
} |