summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoridana@chromium.org <idana@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-17 23:03:21 +0000
committeridana@chromium.org <idana@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-17 23:03:21 +0000
commit386afa320189f08ab18b453863d6cc6a758b06d1 (patch)
tree7e5ce37fdbf63daf478f2b178b2c8d2e47e150fe /chrome
parentd9810a805d4e4626bf2ec9dc805e5643a801d3d9 (diff)
downloadchromium_src-386afa320189f08ab18b453863d6cc6a758b06d1.zip
chromium_src-386afa320189f08ab18b453863d6cc6a758b06d1.tar.gz
chromium_src-386afa320189f08ab18b453863d6cc6a758b06d1.tar.bz2
Made the Sync UI work in the New New tab page.
There are no significant logic changes except the addition of a link which points to the web ui. BUG=none Review URL: http://codereview.chromium.org/172007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23591 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/dom_ui/new_tab_page_sync_handler.cc126
-rw-r--r--chrome/browser/dom_ui/new_tab_page_sync_handler.h9
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc17
-rw-r--r--chrome/browser/resources/new_new_tab.css24
-rw-r--r--chrome/browser/resources/new_new_tab.html10
-rw-r--r--chrome/browser/resources/new_new_tab.js106
-rw-r--r--chrome/browser/sync/personalization_strings.h10
7 files changed, 227 insertions, 75 deletions
diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
index 83bca5e..d903f28 100644
--- a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
+++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
@@ -20,10 +20,9 @@
#include "net/base/cookie_monster.h"
#include "net/url_request/url_request_context.h"
-// XPath expression for finding our p13n iframe.
-static const wchar_t* kP13nIframeXpath = L"//iframe[@id='p13n']";
-
-namespace Personalization {
+// TODO(idana): the following code was originally copied from
+// toolbar_importer.h/cc and it needs to be moved to a common Google Accounts
+// utility.
// A simple pair of fields that identify a set of Google cookies, used to
// filter from a larger set.
@@ -65,14 +64,13 @@ bool IsGoogleGAIACookieInstalled() {
return false;
}
-} // namespace Personalization
-
NewTabPageSyncHandler::NewTabPageSyncHandler() : sync_service_(NULL),
- waiting_for_initial_page_load_(true) {
+ waiting_for_initial_page_load_(true) {
}
NewTabPageSyncHandler::~NewTabPageSyncHandler() {
- sync_service_->RemoveObserver(this);
+ if (sync_service_)
+ sync_service_->RemoveObserver(this);
}
DOMMessageHandler* NewTabPageSyncHandler::Attach(DOMUI* dom_ui) {
@@ -87,32 +85,44 @@ void NewTabPageSyncHandler::RegisterMessages() {
NewCallback(this, &NewTabPageSyncHandler::HandleGetSyncMessage));
dom_ui_->RegisterMessageCallback("SyncLinkClicked",
NewCallback(this, &NewTabPageSyncHandler::HandleSyncLinkClicked));
- dom_ui_->RegisterMessageCallback("ResizeP13N",
- NewCallback(this, &NewTabPageSyncHandler::HandleResizeP13N));
}
-void NewTabPageSyncHandler::HandleResizeP13N(const Value* value) {
- // We just want to call back in to the new tab page on behalf of our
- // same-origin-policy crippled iframe, to tell it to resize the container.
- dom_ui_->CallJavascriptFunction(L"resizeP13N", *value);
+void NewTabPageSyncHandler::HandleGetSyncMessage(const Value* value) {
+ waiting_for_initial_page_load_ = false;
+ BuildAndSendSyncStatus();
+}
+
+void NewTabPageSyncHandler::HideSyncStatusSection() {
+ SendSyncMessageToPage(SyncStatusUIHelper::PRE_SYNCED, std::string(),
+ std::string());
}
void NewTabPageSyncHandler::BuildAndSendSyncStatus() {
DCHECK(!waiting_for_initial_page_load_);
+ // Hide the sync status section if sync is disabled entirely.
+ if (!sync_service_) {
+ HideSyncStatusSection();
+ return;
+ }
+
+ // We show the sync promotion if sync has not been enabled and the user is
+ // logged in to Google Accounts. If the user is not signed in to GA, we
+ // should hide the sync status section entirely.
if (!sync_service_->HasSyncSetupCompleted() &&
!sync_service_->SetupInProgress()) {
- // Clear the page status, without showing the promotion or sync ui.
- // TODO(timsteele): This is fine, but if the page is refreshed or another
- // NTP is opened, we could end up showing the promo again. Not sure this is
- // desired if the user already signed up once and disabled.
- FundamentalValue value(0);
- dom_ui_->CallJavascriptFunction(L"resizeP13N", value);
+ if (IsGoogleGAIACookieInstalled()) {
+ SendSyncMessageToPage(SyncStatusUIHelper::PRE_SYNCED, kSyncPromotionMsg,
+ kStartNowLinkText);
+ } else {
+ HideSyncStatusSection();
+ }
return;
}
- // There are currently three supported "sync statuses" for the NTP, from
- // the users perspective:
+ // Once sync has been enabled, the supported "sync statuses" for the NNTP
+ // from the user's perspective are:
+ //
// "Synced to foo@gmail.com", when we are successfully authenticated and
// connected to a sync server.
// "Sync error", when we can't authenticate or establish a connection with
@@ -126,29 +136,14 @@ void NewTabPageSyncHandler::BuildAndSendSyncStatus() {
SendSyncMessageToPage(type, WideToUTF8(status_msg), WideToUTF8(link_text));
}
-void NewTabPageSyncHandler::HandleGetSyncMessage(const Value* value) {
- waiting_for_initial_page_load_ = false;
-
- if (!sync_service_->HasSyncSetupCompleted() &&
- !sync_service_->SetupInProgress()) {
- if (Personalization::IsGoogleGAIACookieInstalled()) {
- // Sync has not been enabled, and the user has logged in to GAIA.
- SendSyncMessageToPage(SyncStatusUIHelper::PRE_SYNCED, kSyncPromotionMsg,
- kStartNowLinkText);
- }
- return;
- }
-
- BuildAndSendSyncStatus();
-}
-
void NewTabPageSyncHandler::HandleSyncLinkClicked(const Value* value) {
DCHECK(!waiting_for_initial_page_load_);
+ DCHECK(sync_service_);
if (sync_service_->HasSyncSetupCompleted()) {
- // User clicked 'Login again' link to re-authenticate.
+ // User clicked the 'Login again' link to re-authenticate.
sync_service_->ShowLoginDialog();
} else {
- // User clicked "Start now" link to begin syncing.
+ // User clicked the 'Start now' link to begin syncing.
ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_NTP);
sync_service_->EnableForUser();
}
@@ -163,16 +158,19 @@ void NewTabPageSyncHandler::OnStateChanged() {
void NewTabPageSyncHandler::SendSyncMessageToPage(
SyncStatusUIHelper::MessageType type, std::string msg,
- const std::string& linktext) {
+ std::string linktext) {
DictionaryValue value;
- std::string title, msgtype;
+ std::string msgtype;
+ std::string title = kSyncSectionTitle;
+ std::string linkurl;
switch (type) {
case SyncStatusUIHelper::PRE_SYNCED:
- title = kSyncSectionTitle;
msgtype = "presynced";
break;
case SyncStatusUIHelper::SYNCED:
msgtype = "synced";
+ linktext = kSyncViewOnlineLinkLabel;
+ linkurl = kSyncViewOnlineLinkUrl;
msg = msg.substr(0, msg.find(WideToUTF8(kLastSyncedLabel)));
break;
case SyncStatusUIHelper::SYNC_ERROR:
@@ -181,20 +179,34 @@ void NewTabPageSyncHandler::SendSyncMessageToPage(
break;
}
- value.SetString(L"title", title);
- value.SetString(L"msg", msg);
- value.SetString(L"msgtype", msgtype);
- if (!linktext.empty())
- value.SetString(L"linktext", linktext);
- else
- value.SetBoolean(L"linktext", false);
-
- std::string json;
- JSONWriter::Write(&value, false, &json);
- std::wstring javascript = std::wstring(L"renderSyncMessage") +
- L"(" + UTF8ToWide(json) + L");";
- RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
- rvh->ExecuteJavascriptInWebFrame(kP13nIframeXpath, javascript);
+ // If there is no message to show, we should hide the sync section
+ // altogether.
+ if (msg.empty()) {
+ value.SetBoolean(L"syncsectionisvisible", false);
+ } else {
+ value.SetBoolean(L"syncsectionisvisible", true);
+ value.SetString(L"msg", msg);
+ value.SetString(L"title", title);
+ value.SetString(L"msgtype", msgtype);
+ if (linktext.empty()) {
+ value.SetBoolean(L"linkisvisible", false);
+ } else {
+ value.SetBoolean(L"linkisvisible", true);
+ value.SetString(L"linktext", linktext);
+
+ // The only time we set the URL is when the user is synced and we need to
+ // show a link to a web interface (e.g. http://docs.google.com). When we
+ // set that URL, HandleSyncLinkClicked won't be called when the user
+ // clicks on the link.
+ if (linkurl.empty()) {
+ value.SetBoolean(L"linkurlisset", false);
+ } else {
+ value.SetBoolean(L"linkurlisset", true);
+ value.SetString(L"linkurl", linkurl);
+ }
+ }
+ }
+ dom_ui_->CallJavascriptFunction(L"syncMessageChanged", value);
}
#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.h b/chrome/browser/dom_ui/new_tab_page_sync_handler.h
index 2f50a2a..5931684 100644
--- a/chrome/browser/dom_ui/new_tab_page_sync_handler.h
+++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.h
@@ -31,22 +31,23 @@ class NewTabPageSyncHandler : public DOMMessageHandler,
void HandleGetSyncMessage(const Value* value);
// Callback for "SyncLinkClicked".
void HandleSyncLinkClicked(const Value* value);
- // Callback for "ResizeP13N"
- void HandleResizeP13N(const Value* value);
// ProfileSyncServiceObserver
virtual void OnStateChanged();
private:
- // Helper to invoke |renderSyncMessage| JS function on the new tab page.
+ // Helper to invoke the |syncMessageChanged| JS function on the new tab page.
void SendSyncMessageToPage(SyncStatusUIHelper::MessageType type,
- std::string msg, const std::string& linktext);
+ std::string msg, std::string linktext);
// Helper to query the sync service and figure out what to send to
// the page, and send it via SendSyncMessageToPage.
// NOTE: precondition: sync must be enabled.
void BuildAndSendSyncStatus();
+ // Helper to send a message to the NNTP which hides the sync section.
+ void HideSyncStatusSection();
+
// Cached pointer to ProfileSyncService.
ProfileSyncService* sync_service_;
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index b3e246e..0504352 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/dom_ui/dom_ui_theme_source.h"
#include "chrome/browser/dom_ui/downloads_dom_handler.h"
#include "chrome/browser/dom_ui/history_ui.h"
+#include "chrome/browser/dom_ui/new_tab_page_sync_handler.h"
#include "chrome/browser/dom_ui/shown_sections_handler.h"
#include "chrome/browser/dom_ui/tips_handler.h"
#include "chrome/browser/history/page_usage_data.h"
@@ -36,9 +37,6 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/sessions/tab_restore_service.h"
-#ifdef CHROME_PERSONALIZATION
-#include "chrome/browser/sync/personalization.h"
-#endif
#include "chrome/browser/user_data_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/jstemplate_builder.h"
@@ -344,6 +342,13 @@ void NewTabHTMLSource::StartDataRequest(const std::string& path,
localized_strings.SetString(L"closefirstrunnotification",
l10n_util::GetString(IDS_NEW_TAB_CLOSE_FIRST_RUN_NOTIFICATION));
+ // Don't initiate the sync related message passing with the page if the sync
+ // code is not present.
+ if (profile_->GetProfileSyncService())
+ localized_strings.SetString(L"syncispresent", "true");
+ else
+ localized_strings.SetString(L"syncispresent", "false");
+
SetFontAndTextDirection(&localized_strings);
// Let the tab know whether it's the first tab being viewed.
@@ -356,10 +361,6 @@ void NewTabHTMLSource::StartDataRequest(const std::string& path,
Animation::ShouldRenderRichAnimation() ? L"true" : L"false";
localized_strings.SetString(L"anim", anim);
-#ifdef CHROME_PERSONALIZATION
- localized_strings.SetString(L"p13nsrc", Personalization::GetNewTabSource());
-#endif
-
// In case we have the new new tab page enabled we first try to read the file
// provided on the command line. If that fails we just get the resource from
// the resource bundle.
@@ -1552,7 +1553,7 @@ NewTabUI::NewTabUI(TabContents* contents)
#ifdef CHROME_PERSONALIZATION
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableSync)) {
- AddMessageHandler(Personalization::CreateNewTabPageHandler(this));
+ AddMessageHandler((new NewTabPageSyncHandler())->Attach(this));
}
#endif
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css
index 1f52452..1c4fefe 100644
--- a/chrome/browser/resources/new_new_tab.css
+++ b/chrome/browser/resources/new_new_tab.css
@@ -460,7 +460,7 @@ html[dir='rtl'] .item {
background-color: hsla(213, 60%, 92%, .4);
border: 1px solid hsl(213, 60%, 92%);
-webkit-border-radius: 5px;
- padding: 5px 0px;;
+ padding: 5px 0px;
white-space: nowrap;
overflow-x: hidden;
}
@@ -490,6 +490,28 @@ html[dir='rtl'] .item {
-webkit-padding-start: 2px;
}
+#sync-status {
+ -webkit-transition: height .15s, opacity .15s;
+ background-color: hsla(213, 60%, 92%, .4);
+ border: 1px solid hsl(213, 60%, 92%);
+ -webkit-border-radius: 6px;
+ padding: 5px 0;
+ margin: 10px 0;
+ white-space: nowrap;
+ opacity: 0;
+ overflow-x: hidden;
+}
+
+#sync-status > * {
+ display: inline-block;
+ max-width: none;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-size: 100%;
+ margin: 0 10px;
+}
+
#view-toolbar {
-webkit-user-select: none;
text-align: right;
diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html
index 6012544..e6ae26a 100644
--- a/chrome/browser/resources/new_new_tab.html
+++ b/chrome/browser/resources/new_new_tab.html
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<html i18n-values="dir:textdirection;firstview:firstview;bookmarkbarattached:bookmarkbarattached;hasattribution:hasattribution;anim:anim">
+<html i18n-values="dir:textdirection;firstview:firstview;bookmarkbarattached:bookmarkbarattached;hasattribution:hasattribution;anim:anim;syncispresent:syncispresent">
<meta charset="utf-8">
<title i18n-content="title"></title>
@@ -39,6 +39,8 @@ chrome.send('getRecentlyClosedTabs');
registerCallback('onShownSections');
registerCallback('mostVisitedPages');
registerCallback('recentlyClosedTabs');
+registerCallback('syncMessageChanged');
+
// TODO(arv): The backend calls this function. Remove the call on the backend.
function downloadsList() {}
@@ -226,6 +228,12 @@ document.write('<link id="themecss" rel="stylesheet" ' +
</span>
</div>
+ <div id="sync-status">
+ <h2>&nbsp;</h2>
+ <span>&nbsp;</span>
+ <span><a href="">&nbsp;</a></span>
+ </div>
+
</div> <!-- main -->
<div>
diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js
index 7ce28bd..dcd7c20 100644
--- a/chrome/browser/resources/new_new_tab.js
+++ b/chrome/browser/resources/new_new_tab.js
@@ -102,7 +102,6 @@ function recentlyClosedTabs(data) {
}
var recentItems = [];
-var recentItemKeys = {};
function renderRecentlyClosed() {
// We remove all items but the header and the nav
@@ -646,8 +645,6 @@ var mostVisited = {
function layoutRecentlyClosed() {
var recentElement = $('recently-closed');
-
- var rtl = document.documentElement.dir == 'rtl';
var recentShown = shownSections & Section.RECENT;
var style = recentElement.style;
@@ -685,6 +682,90 @@ function layoutRecentlyClosed() {
}
/**
+ * This function is called by the backend whenever the sync status section
+ * needs to be updated to reflect recent sync state changes. The backend passes
+ * the new status information in the newMessage parameter. The state includes
+ * the following:
+ *
+ * syncsectionisvisible: true if the sync section needs to show up on the new
+ * tab page and false otherwise.
+ * msgtype: represents the states - "error", "presynced" or "synced".
+ * title: the header for the sync status section.
+ * msg: the actual message (e.g. "Synced to foo@gmail.com").
+ * linkisvisible: true if the link element should be visible within the sync
+ * section and false otherwise.
+ * linktext: the text to display as the link in the sync status (only used if
+ * linkisvisible is true).
+ * linkurlisset: true if an URL should be set as the href for the link and false
+ * otherwise. If this field is false, then clicking on the link
+ * will result in sending a message to the backend (see
+ * 'SyncLinkClicked').
+ * linkurl: the URL to use as the element's href (only used if linkurlisset is
+ * true).
+ */
+function syncMessageChanged(newMessage) {
+ var syncStatusElement = $('sync-status');
+ var style = syncStatusElement.style;
+
+ // Hide the section if the message is emtpy.
+ if (!newMessage.syncsectionisvisible) {
+ style.opacity = style.height = 0;
+ return;
+ }
+ style.height = '';
+ style.opacity = 1;
+
+ // Set the sync section background color based on the state.
+ if (newMessage.msgtype == "error") {
+ style.backgroundColor = "tomato";
+ } else if (newMessage.msgtype == "presynced") {
+ style.backgroundColor = "greenyellow";
+ } else {
+ style.backgroundColor = "#CAFF70";
+ }
+
+ // Set the text for the header and sync message.
+ var titleElement = syncStatusElement.firstElementChild;
+ titleElement.textContent = newMessage.title;
+ var messageElement = titleElement.nextElementSibling;
+ messageElement.textContent = newMessage.msg;
+
+ // Set up the link if we should show one or hide it otherwise.
+ var linkContainer = messageElement.nextElementSibling;
+ var containerStyle = linkContainer.style;
+ var linkElement = linkContainer.firstElementChild;
+ linkElement.removeEventListener('click', syncSectionLinkClicked);
+
+ // TODO(idana): when we don't have an URL to set, using an href is not a good
+ // idea because the user will still be able to right click on the link and
+ // open the empty href in a new tab/window.
+ //
+ // See http://code.google.com/p/chromium/issues/detail?id=19538 for more info
+ // about how to fix this.
+ linkElement.href = '';
+ containerStyle.display = 'none';
+ if (newMessage.linkisvisible) {
+ containerStyle.display = '';
+ linkElement.textContent = newMessage.linktext;
+ // We don't listen to click events if the backend specified a target URL
+ // for the link.
+ if (newMessage.linkurlisset) {
+ linkElement.href = newMessage.linkurl;
+ } else {
+ linkElement.addEventListener('click', syncSectionLinkClicked);
+ }
+ }
+}
+
+/**
+ * Invoked when the link in the sync status section is clicked.
+ */
+function syncSectionLinkClicked(e) {
+ chrome.send('SyncLinkClicked');
+ e.preventDefault();
+}
+
+/**
* Returns the text used for a recently closed window.
* @param {number} numTabs Number of tabs in the window.
* @return {string} The text to use.
@@ -1206,6 +1287,25 @@ window.addEventListener('resize', handleWindowResize);
document.addEventListener('DOMContentLoaded', bind(logEvent, global,
'domcontentloaded fired'));
+// Whether or not we should send the initial 'GetSyncMessage' to the backend
+// depends on the value of the attribue 'syncispresent' which the backend sets
+// to indicate if there is code in the backend which is capable of processing
+// this message. This attribute is loaded by the JSTemplate and therefore we
+// must make sure we check the attribute after the DOM is loaded.
+document.addEventListener('DOMContentLoaded',
+ callGetSyncMessageIfSyncIsPresent);
+
+/**
+ * The sync code is not yet built by default on all platforms so we have to
+ * make sure we don't send the initial sync message to the backend unless the
+ * backend told us that the sync code is present.
+ */
+function callGetSyncMessageIfSyncIsPresent() {
+ if (document.documentElement.getAttribute("syncispresent") == "true") {
+ chrome.send('GetSyncMessage');
+ }
+}
+
function hideAllMenus() {
optionMenu.hide();
}
diff --git a/chrome/browser/sync/personalization_strings.h b/chrome/browser/sync/personalization_strings.h
index 2dd67aa..08204a0 100644
--- a/chrome/browser/sync/personalization_strings.h
+++ b/chrome/browser/sync/personalization_strings.h
@@ -47,9 +47,17 @@ static const char kSyncPromotionMsg[] =
static const wchar_t kSyncServerUnavailableMsg[] =
L"Google Chrome could not sync your bookmarks because it could not connect "
L"to the sync server. Retrying...";
-static const char kStartNowLinkText[] = "Start now.";
+static const char kStartNowLinkText[] = "Start now";
static const char kSettingUpText[] = "Setup in progress...";
+// TODO(idana): when we get rid of this file and move all the strings into
+// generated_resources.grd, we should probably move these into a pref of some
+// sort to allow third party sync providers to control which URL to use for the
+// sync web UI. We should also make it possible for the sync provider to hide
+// the link altogether if they don't provide web UI for their users.
+static const char kSyncViewOnlineLinkUrl[] = "http://docs.google.com";
+static const char kSyncViewOnlineLinkLabel[] = "View in Google Docs";
+
// Sync menu item strings.
static const wchar_t kMenuLabelStartSync[] = L"Sync my bookmarks...";