new_tab_ui.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
14ee2ad04344446e610172a0e73949212923014dfSebastian Redl// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use of this source code is governed by a BSD-style license that can be
32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// found in the LICENSE file.
42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <set>
82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/i18n/rtl.h"
10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl#include "base/lazy_instance.h"
112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/memory/scoped_ptr.h"
122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/metrics/histogram.h"
132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/prefs/pref_service.h"
147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include "base/strings/utf_string_conversions.h"
150eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis#include "chrome/browser/chrome_notification_types.h"
16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "chrome/browser/profiles/profile.h"
17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "chrome/browser/ui/webui/metrics_handler.h"
182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/ui/webui/ntp/favicon_webui_handler.h"
192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/ui/webui/ntp/foreign_session_handler.h"
202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/ui/webui/ntp/most_visited_handler.h"
212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall#include "chrome/browser/ui/webui/ntp/ntp_resource_cache.h"
2289eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis#include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h"
230b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor#include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
247a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall#include "chrome/browser/ui/webui/ntp/recently_closed_tabs_handler.h"
252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/common/pref_names.h"
26a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall#include "chrome/common/url_constants.h"
276ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl#include "components/user_prefs/pref_registry_syncable.h"
28bbf38319edd4eddc55ec273934e990d7e84991deDouglas Gregor#include "content/public/browser/browser_thread.h"
297c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner#include "content/public/browser/notification_service.h"
306a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor#include "content/public/browser/render_process_host.h"
317c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner#include "content/public/browser/render_view_host.h"
32a71a7d8a1ce4474e7bdb680658fb58b6caf391d3Douglas Gregor#include "content/public/browser/url_data_source.h"
3383d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff#include "content/public/browser/web_contents.h"
3414f79002e58556798e86168c63e48d533287eda5Douglas Gregor#include "content/public/browser/web_ui.h"
3510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "grit/browser_resources.h"
363251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor#include "grit/generated_resources.h"
3714f79002e58556798e86168c63e48d533287eda5Douglas Gregor#include "ui/base/l10n/l10n_util.h"
38bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor
392bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor#if !defined(OS_ANDROID)
4057016dda61498294120b1a881d9e6606337b29d9Douglas Gregor#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
41ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
420a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor#include "chrome/browser/ui/webui/ntp/new_tab_page_handler.h"
4317fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor#include "chrome/browser/ui/webui/ntp/new_tab_page_sync_handler.h"
4417fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor#include "chrome/browser/ui/webui/ntp/ntp_login_handler.h"
452596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar#include "chrome/browser/ui/webui/ntp/suggestions_page_handler.h"
462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#else
47fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer#include "chrome/browser/ui/webui/ntp/android/bookmarks_handler.h"
4814f79002e58556798e86168c63e48d533287eda5Douglas Gregor#include "chrome/browser/ui/webui/ntp/android/context_menu_handler.h"
4903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "chrome/browser/ui/webui/ntp/android/navigation_handler.h"
50f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor#include "chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.h"
513c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner#include "chrome/browser/ui/webui/ntp/android/promo_handler.h"
52cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor#endif
53f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor
542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#if defined(ENABLE_THEMES)
558538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#include "chrome/browser/ui/webui/theme_handler.h"
562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
57ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl
585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner#if defined(USE_ASH)
595f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner#include "chrome/browser/ui/host_desktop.h"
605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner#endif
616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer
62ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redlusing content::BrowserThread;
636e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramerusing content::RenderViewHost;
646e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramerusing content::WebUIController;
655f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner
665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnernamespace {
676e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer
68ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl// The amount of time there must be no painting for us to consider painting
69ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl// finished.  Observed times are in the ~1200ms range on Windows.
702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorconst int kTimeoutMs = 2000;
712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Strings sent to the page via jstemplates used to set the direction of the
7312b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner// HTML document based on locale.
742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorconst char kRTLHtmlTextDirection[] = "rtl";
753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlconst char kLTRHtmlTextDirection[] = "ltr";
76a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl
7789eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidisstatic base::LazyInstance<std::set<const WebUIController*> > g_live_new_tabs;
782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}  // namespace
802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
818538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl///////////////////////////////////////////////////////////////////////////////
822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// NewTabUI
8389eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis
848538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian RedlNewTabUI::NewTabUI(content::WebUI* web_ui)
852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    : WebUIController(web_ui),
862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      showing_sync_bubble_(false) {
872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  g_live_new_tabs.Pointer()->insert(this);
882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui->OverrideTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  content::WebContents* web_contents = web_ui->GetWebContents();
912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  NTPUserDataLogger::CreateForWebContents(web_contents);
922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  NTPUserDataLogger::FromWebContents(web_contents)->set_ntp_url(
932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      GURL(chrome::kChromeUINewTabURL));
942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  registrar_.Add(
963397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      this,
97b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      content::Source<content::WebContents>(web_contents));
992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1003397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // We count all link clicks as AUTO_BOOKMARK, so that site can be ranked more
1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // highly. Note this means we're including clicks on not only most visited
1028538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // thumbnails, but also clicks on recently bookmarked.
1032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui->SetLinkTransitionType(content::PAGE_TRANSITION_AUTO_BOOKMARK);
1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1053397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  if (!GetProfile()->IsOffTheRecord()) {
1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    web_ui->AddMessageHandler(new browser_sync::ForeignSessionHandler());
1078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    web_ui->AddMessageHandler(new MostVisitedHandler());
1082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    web_ui->AddMessageHandler(new RecentlyClosedTabsHandler());
1092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#if !defined(OS_ANDROID)
1103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    web_ui->AddMessageHandler(new FaviconWebUIHandler());
1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    web_ui->AddMessageHandler(new MetricsHandler());
1128538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    web_ui->AddMessageHandler(new NewTabPageHandler());
1132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    web_ui->AddMessageHandler(new CoreAppLauncherHandler());
1142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    if (NewTabUI::IsDiscoveryInNTPEnabled())
1153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      web_ui->AddMessageHandler(new SuggestionsHandler());
116df1550fc59b51681d37225934fe4e3acac321621Richard Smith    // Android doesn't have a sync promo/username on NTP.
117df1550fc59b51681d37225934fe4e3acac321621Richard Smith    web_ui->AddMessageHandler(new NewTabPageSyncHandler());
1188538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
1192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    if (ShouldShowApps()) {
1202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      ExtensionService* service = GetProfile()->GetExtensionService();
1213397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      // We might not have an ExtensionService (on ChromeOS when not logged in
122df1550fc59b51681d37225934fe4e3acac321621Richard Smith      // for example).
1238538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl      if (service)
1242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        web_ui->AddMessageHandler(new AppLauncherHandler(service));
1252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    }
1263397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#endif
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
1281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#if defined(OS_ANDROID)
1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // These handlers are specific to the Android NTP page.
1312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui->AddMessageHandler(new BookmarksHandler());
1323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  web_ui->AddMessageHandler(new ContextMenuHandler());
1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui->AddMessageHandler(new FaviconWebUIHandler());
1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui->AddMessageHandler(new NavigationHandler());
1350953e767ff7817f97b3ab20896b229891eeff45bJohn McCall  web_ui->AddMessageHandler(new NewTabPageReadyHandler());
1362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (!GetProfile()->IsOffTheRecord())
1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    web_ui->AddMessageHandler(new PromoHandler());
1383397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#else
1392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Android uses native UI for sync setup.
1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (NTPLoginHandler::ShouldShow(GetProfile()))
1418538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    web_ui->AddMessageHandler(new NTPLoginHandler());
1422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1443397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#if defined(ENABLE_THEMES)
1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // The theme handler can require some CPU, so do it after hooking up the most
1468538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // visited handler. This allows the DB query for the new tab thumbs to happen
1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // earlier.
1482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui->AddMessageHandler(new ThemeHandler());
1493397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#endif
1502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1517e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor  scoped_ptr<NewTabHTMLSource> html_source(new NewTabHTMLSource(
1527e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor      GetProfile()->GetOriginalProfile()));
153c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor
1548538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // These two resources should be loaded only if suggestions NTP is enabled.
1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  html_source->AddResource("suggestions_page.css", "text/css",
1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      NewTabUI::IsDiscoveryInNTPEnabled() ? IDR_SUGGESTIONS_PAGE_CSS : 0);
1573397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  if (NewTabUI::IsDiscoveryInNTPEnabled()) {
1582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    html_source->AddResource("suggestions_page.js", "application/javascript",
1592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        IDR_SUGGESTIONS_PAGE_JS);
160e86d78cf4754a6aef2cf9a33d847aa15338e276fBob Wilson  }
1618538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // content::URLDataSource assumes the ownership of the html_source.
1622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  content::URLDataSource::Add(GetProfile(), html_source.release());
1632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1643397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  pref_change_registrar_.Init(GetProfile()->GetPrefs());
1652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  pref_change_registrar_.Add(prefs::kShowBookmarkBar,
1668538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl                             base::Bind(&NewTabUI::OnShowBookmarkBarChanged,
1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                                        base::Unretained(this)));
1682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1693397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorNewTabUI::~NewTabUI() {
171264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola  g_live_new_tabs.Pointer()->erase(this);
172264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola}
173a49218e17bcbb1acde0245773173e2c0c42f4f19Eli Friedman
174425ef72306d4ff6b3698b744353e5f0e56b4b884Rafael Espindola// The timer callback.  If enough time has elapsed since the last paint
175ab8bbf4ebd3e3e6eab913cb044772a62b7581941Douglas Gregor// message, we say we're done painting; otherwise, we keep waiting.
176264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindolavoid NewTabUI::PaintTimeout() {
177f85e193739c953358c865005855253af4f68a497John McCall  // The amount of time there must be no painting for us to consider painting
1782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // finished.  Observed times are in the ~1200ms range on Windows.
1792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  base::TimeTicks now = base::TimeTicks::Now();
1803397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  if ((now - last_paint_) >= base::TimeDelta::FromMilliseconds(kTimeoutMs)) {
1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // Painting has quieted down.  Log this as the full time to run.
1828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    base::TimeDelta load_time = last_paint_ - start_;
1832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    int load_time_ms = static_cast<int>(load_time.InMilliseconds());
1842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    content::NotificationService::current()->Notify(
1853397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl        chrome::NOTIFICATION_INITIAL_NEW_TAB_UI_LOAD,
1862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        content::Source<Profile>(GetProfile()),
1872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        content::Details<int>(&load_time_ms));
1882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    UMA_HISTOGRAM_TIMES("NewTabUI load", load_time);
1892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  } else {
1902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // Not enough quiet time has elapsed.
191eefb3d5b49c844347f212073a7e975b8118fe8e9Richard Smith    // Some more paints must've occurred since we set the timeout.
1922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // Wait some more.
193c938c1668b4fd12af154e965dd935a89e4801a70Douglas Gregor    timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimeoutMs), this,
19460618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl                 &NewTabUI::PaintTimeout);
19560618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  }
19660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl}
19760618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl
19860618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redlvoid NewTabUI::StartTimingPaint(RenderViewHost* render_view_host) {
19960618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  start_ = base::TimeTicks::Now();
20060618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  last_paint_ = start_;
2017bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith
2027bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith  content::NotificationSource source =
2037bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith      content::Source<content::RenderWidgetHost>(render_view_host);
204b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith  if (!registrar_.IsRegistered(this,
205b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith          content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
20660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl          source)) {
2078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    registrar_.Add(
2082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        this,
2092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
2103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl        source);
211ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
2128538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
213ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimeoutMs), this,
214ed97649e9574b9d854fa4d6109c9333ae0993554John McCall               &NewTabUI::PaintTimeout);
2153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl}
2162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2179763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidisvoid NewTabUI::RenderViewCreated(RenderViewHost* render_view_host) {
2189763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  StartTimingPaint(render_view_host);
2198538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}
2202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid NewTabUI::RenderViewReused(RenderViewHost* render_view_host) {
2223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  StartTimingPaint(render_view_host);
223c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor}
2248538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
2252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid NewTabUI::Observe(int type,
2262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                       const content::NotificationSource& source,
2273397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl                       const content::NotificationDetails& details) {
2282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  switch (type) {
2298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: {
2302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      last_paint_ = base::TimeTicks::Now();
2312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      break;
2323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    }
233f8af98286022f72157d84951b48fde5fb369ab29Douglas Gregor    case content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
234395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson      if (!*content::Details<bool>(details).ptr()) {
2358538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl        EmitMouseoverCount(
236395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson            content::Source<content::WebContents>(source).ptr());
237395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson      }
238ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt      break;
239ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    }
240ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    default:
241ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt      CHECK(false) << "Unexpected notification: " << type;
242ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt  }
243ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt}
244ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt
24534b41d939a1328f484511c6002ba2456db879a29Richard Smithvoid NewTabUI::EmitMouseoverCount(content::WebContents* web_contents) {
24634b41d939a1328f484511c6002ba2456db879a29Richard Smith  NTPUserDataLogger* data = NTPUserDataLogger::FromWebContents(web_contents);
24734b41d939a1328f484511c6002ba2456db879a29Richard Smith  if (data->ntp_url() == GURL(chrome::kChromeUINewTabURL))
24834b41d939a1328f484511c6002ba2456db879a29Richard Smith    data->EmitMouseoverCount();
24934b41d939a1328f484511c6002ba2456db879a29Richard Smith}
2503397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
251be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidisvoid NewTabUI::OnShowBookmarkBarChanged() {
25256ca8a9c0fabd65418e9b2fd85140f4ed7d3c187Douglas Gregor  StringValue attached(
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      GetProfile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar) ?
2542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor          "true" : "false");
2552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  web_ui()->CallJavascriptFunction("ntp.setBookmarkBarAttached", attached);
2562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
2573397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
2582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// static
2598538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid NewTabUI::RegisterProfilePrefs(
2602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    user_prefs::PrefRegistrySyncable* registry) {
2612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#if !defined(OS_ANDROID)
2623397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  AppLauncherHandler::RegisterProfilePrefs(registry);
2632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  NewTabPageHandler::RegisterProfilePrefs(registry);
2648538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  if (NewTabUI::IsDiscoveryInNTPEnabled())
2652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    SuggestionsHandler::RegisterProfilePrefs(registry);
2662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
2679d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  MostVisitedHandler::RegisterProfilePrefs(registry);
2689d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry);
2699d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall}
2709d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall
2719d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall// static
2729d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCallbool NewTabUI::ShouldShowApps() {
2739d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall// Ash shows apps in app list thus should not show apps page in NTP4.
2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// Android does not have apps.
2753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#if defined(OS_ANDROID)
27649a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  return false;
27749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall#elif defined(USE_ASH)
27849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  return chrome::GetActiveDesktop() != chrome::HOST_DESKTOP_TYPE_ASH;
2798538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#else
28049a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  return true;
28149a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall#endif
28249a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall}
283c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor
284c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor// static
285c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregorbool NewTabUI::IsDiscoveryInNTPEnabled() {
286c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  // TODO(beaudoin): The flag was removed during a clean-up pass. We leave that
287c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  // here to easily enable it back when we will explore this option again.
288c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  return false;
289c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor}
290c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor
2913397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl// static
2922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid NewTabUI::SetUrlTitleAndDirection(DictionaryValue* dictionary,
293be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis                                       const string16& title,
29490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis                                       const GURL& gurl) {
29590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  dictionary->SetString("url", gurl.spec());
29690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
29790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  bool using_url_as_the_title = false;
29890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  string16 title_to_set(title);
2993e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith  if (title_to_set.empty()) {
3003e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith    using_url_as_the_title = true;
3019763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis    title_to_set = UTF8ToUTF16(gurl.spec());
3029763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  }
3038538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
30490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // We set the "dir" attribute of the title, so that in RTL locales, a LTR
30590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // title is rendered left-to-right and truncated from the right. For example,
30690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // the title of http://msdn.microsoft.com/en-us/default.aspx is "MSDN:
3073397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // Microsoft developer network". In RTL locales, in the [New Tab] page, if
308ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis  // the "dir" of this title is not specified, it takes Chrome UI's
309ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis  // directionality. So the title will be truncated as "soft developer
310ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis  // network". Setting the "dir" attribute as "ltr" renders the truncated title
3118538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // as "MSDN: Microsoft D...". As another example, the title of
31290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // http://yahoo.com is "Yahoo!". In RTL locales, in the [New Tab] page, the
31390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // title will be rendered as "!Yahoo" if its "dir" attribute is not set to
31490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // "ltr".
3153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  std::string direction;
31690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  if (!using_url_as_the_title &&
31790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      base::i18n::IsRTL() &&
318b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      base::i18n::StringContainsStrongRTLChars(title)) {
31990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    direction = kRTLHtmlTextDirection;
32090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  } else {
32190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    direction = kLTRHtmlTextDirection;
3223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  }
32390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  dictionary->SetString("title", title_to_set);
32490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  dictionary->SetString("direction", direction);
32590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis}
3264fb86f8c4585e53c21c847ad3de9e3b2de123cd9Chandler Carruth
3278538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl// static
32890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios KyrtzidisNewTabUI* NewTabUI::FromWebUIController(WebUIController* ui) {
32990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  if (!g_live_new_tabs.Pointer()->count(ui))
33090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    return NULL;
3313397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  return static_cast<NewTabUI*>(ui);
3328dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis}
3338dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis
3348dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios KyrtzidisProfile* NewTabUI::GetProfile() const {
335f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis  return Profile::FromWebUI(web_ui());
336f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis}
337f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis
3388538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl///////////////////////////////////////////////////////////////////////////////
33990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis// NewTabHTMLSource
34090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
34190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios KyrtzidisNewTabUI::NewTabHTMLSource::NewTabHTMLSource(Profile* profile)
3423397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    : profile_(profile) {
34390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis}
3443acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis
3453acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidisstd::string NewTabUI::NewTabHTMLSource::GetSource() const {
3463acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis  return chrome::kChromeUINewTabHost;
3473acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis}
3483acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis
3493acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidisvoid NewTabUI::NewTabHTMLSource::StartDataRequest(
3503acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis    const std::string& path,
3518538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    int render_process_id,
3522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    int render_view_id,
3532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const content::URLDataSource::GotDataCallback& callback) {
3547536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3557536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor
356cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor  std::map<std::string, std::pair<std::string, int> >::iterator it =
357cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor    resource_map_.find(path);
358cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor  if (it != resource_map_.end()) {
359cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor    scoped_refptr<base::RefCountedStaticMemory> resource_bytes(
3607536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor        it->second.second ?
3617536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor            ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
3627536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor                it->second.second) :
363075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara            new base::RefCountedStaticMemory);
364075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara    callback.Run(resource_bytes.get());
365075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara    return;
366075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara  }
367075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara
3683397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  if (!path.empty() && path[0] != '#') {
369465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara    // A path under new-tab was requested; it's likely a bad relative
3703acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis    // URL from the new tab page, but in any case it's an error.
3713acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis
3728538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    // TODO(dtrainor): Can remove this #if check once we update the
3732cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // accessibility script to no longer try to access urls like
3742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // '?2314124523523'.
3753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    // See http://crbug.com/150252.
376a8e0b978d63c52e39c002fbf014ce553374fedcfDouglas Gregor#if !defined(OS_ANDROID)
37731f17ecbef57b5679c017c375db330546b7b5145John McCall    NOTREACHED() << path << " should not have been requested on the NTP";
3788538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif
3793cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall    callback.Run(NULL);
3803cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall    return;
3813397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  }
38256ca8a9c0fabd65418e9b2fd85140f4ed7d3c187Douglas Gregor
3838538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  content::RenderProcessHost* render_host =
384c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall      content::RenderProcessHost::FromID(render_process_id);
385c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  bool is_incognito = render_host->GetBrowserContext()->IsOffTheRecord();
3863397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  scoped_refptr<base::RefCountedMemory> html_bytes(
387c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall      NTPResourceCacheFactory::GetForProfile(profile_)->
3882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      GetNewTabHTML(is_incognito));
389c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall
390446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff  callback.Run(html_bytes.get());
391446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff}
3928538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
3932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstd::string NewTabUI::NewTabHTMLSource::GetMimeType(const std::string& resource)
3942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const {
395d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff  std::map<std::string, std::pair<std::string, int> >::const_iterator it =
3963397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      resource_map_.find(resource);
3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (it != resource_map_.end())
3988538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    return it->second.first;
3992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  return "text/html";
4002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
401b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman
402b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedmanbool NewTabUI::NewTabHTMLSource::ShouldReplaceExistingSource() const {
403b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman  return false;
404b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman}
405b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman
406b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedmanbool NewTabUI::NewTabHTMLSource::ShouldAddContentSecurityPolicy() const {
407a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  return false;
408a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall}
409a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall
410a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redlvoid NewTabUI::NewTabHTMLSource::AddResource(const char* resource,
41189eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis                                             const char* mime_type,
412a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall                                             int resource_id) {
413a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  DCHECK(resource);
41489eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis  DCHECK(mime_type);
415a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  resource_map_[std::string(resource)] =
416a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall      std::make_pair(std::string(mime_type), resource_id);
41751bd803fbdade51d674598ed45da3d54190a656cJohn McCall}
418a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall
41951bd803fbdade51d674598ed45da3d54190a656cJohn McCallNewTabUI::NewTabHTMLSource::~NewTabHTMLSource() {}
420a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall