diff options
author | idana@chromium.org <idana@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-17 23:03:21 +0000 |
---|---|---|
committer | idana@chromium.org <idana@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-17 23:03:21 +0000 |
commit | 386afa320189f08ab18b453863d6cc6a758b06d1 (patch) | |
tree | 7e5ce37fdbf63daf478f2b178b2c8d2e47e150fe /chrome | |
parent | d9810a805d4e4626bf2ec9dc805e5643a801d3d9 (diff) | |
download | chromium_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.cc | 126 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_page_sync_handler.h | 9 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.cc | 17 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.css | 24 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.html | 10 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 106 | ||||
-rw-r--r-- | chrome/browser/sync/personalization_strings.h | 10 |
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> </h2> + <span> </span> + <span><a href=""> </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..."; |