diff options
author | tim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-15 21:52:28 +0000 |
---|---|---|
committer | tim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-15 21:52:28 +0000 |
commit | d742d2f41fd7035ef040a1b76bd5bcd93ae9b0ac (patch) | |
tree | 1593105e3c5b59d87bcedbb465eb9d67500f3fdd /chrome/browser | |
parent | 53556e1b386f14de94d97351e47774b97c0ed753 (diff) | |
download | chromium_src-d742d2f41fd7035ef040a1b76bd5bcd93ae9b0ac.zip chromium_src-d742d2f41fd7035ef040a1b76bd5bcd93ae9b0ac.tar.gz chromium_src-d742d2f41fd7035ef040a1b76bd5bcd93ae9b0ac.tar.bz2 |
Facelifts to sync UI
BUG=23136,24858,21596
TEST=SyncSetupWizardTest
Review URL: http://codereview.chromium.org/270081
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29197 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
19 files changed, 352 insertions, 97 deletions
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 98d558a..05e6342 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -48,6 +48,7 @@ without changes to the corresponding grd file. ek --> <include name="IDR_GAIA_LOGIN_HTML" file="sync\resources\gaia_login.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_SYNC_SETUP_FLOW_HTML" file="sync\resources\setup_flow.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_MERGE_AND_SYNC_HTML" file="sync\resources\merge_and_sync.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_SYNC_SETUP_DONE_HTML" file="sync\resources\setup_done.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_BLACKLIST_HTML" file="resources\privacy_blacklist_block.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_BLACKLIST_IMAGE" file="resources\privacy_blacklist_block.png" type="BINDATA" /> <include name="IDR_DEFAULT_EXTENSION_ICON_128" file="resources\default_extension_icon_128.png" type="BINDATA" /> 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 0b26492..e5239a5 100644 --- a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc +++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc @@ -80,6 +80,20 @@ NewTabPageSyncHandler::~NewTabPageSyncHandler() { sync_service_->RemoveObserver(this); } +// static +NewTabPageSyncHandler::MessageType + NewTabPageSyncHandler::FromSyncStatusMessageType( + SyncStatusUIHelper::MessageType type) { + switch (type) { + case SyncStatusUIHelper::SYNC_ERROR: + return SYNC_ERROR; + case SyncStatusUIHelper::PRE_SYNCED: + case SyncStatusUIHelper::SYNCED: + default: + return HIDE; + } +} + DOMMessageHandler* NewTabPageSyncHandler::Attach(DOMUI* dom_ui) { sync_service_ = dom_ui->GetProfile()->GetProfileSyncService(); DCHECK(sync_service_); // This shouldn't get called by an incognito NTP. @@ -100,8 +114,7 @@ void NewTabPageSyncHandler::HandleGetSyncMessage(const Value* value) { } void NewTabPageSyncHandler::HideSyncStatusSection() { - SendSyncMessageToPage(SyncStatusUIHelper::PRE_SYNCED, std::string(), - std::string()); + SendSyncMessageToPage(HIDE, std::string(), std::string()); } void NewTabPageSyncHandler::BuildAndSendSyncStatus() { @@ -116,14 +129,11 @@ void NewTabPageSyncHandler::BuildAndSendSyncStatus() { // 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()) { - if (IsGoogleGAIACookieInstalled()) { - SendSyncMessageToPage(SyncStatusUIHelper::PRE_SYNCED, + if (!sync_service_->HasSyncSetupCompleted()) { + if(!sync_service_->SetupInProgress() && IsGoogleGAIACookieInstalled()) { + SendSyncMessageToPage(PROMOTION, WideToUTF8(l10n_util::GetString(IDS_SYNC_NTP_PROMOTION_MESSAGE)), WideToUTF8(l10n_util::GetString(IDS_SYNC_NTP_START_NOW_LINK_LABEL))); - } else { - HideSyncStatusSection(); } return; } @@ -131,17 +141,15 @@ void NewTabPageSyncHandler::BuildAndSendSyncStatus() { // 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 // the sync server (appropriate information appended to // message). - // "Authenticating", when credentials are in flight. - SyncStatusUIHelper::MessageType type(SyncStatusUIHelper::PRE_SYNCED); std::wstring status_msg; std::wstring link_text; - type = SyncStatusUIHelper::GetLabels(sync_service_, &status_msg, &link_text); - SendSyncMessageToPage(type, WideToUTF8(status_msg), WideToUTF8(link_text)); + SyncStatusUIHelper::MessageType type = + SyncStatusUIHelper::GetLabels(sync_service_, &status_msg, &link_text); + SendSyncMessageToPage(FromSyncStatusMessageType(type), + WideToUTF8(status_msg), WideToUTF8(link_text)); } void NewTabPageSyncHandler::HandleSyncLinkClicked(const Value* value) { @@ -165,7 +173,7 @@ void NewTabPageSyncHandler::OnStateChanged() { } void NewTabPageSyncHandler::SendSyncMessageToPage( - SyncStatusUIHelper::MessageType type, std::string msg, + MessageType type, std::string msg, std::string linktext) { DictionaryValue value; std::string msgtype; @@ -174,28 +182,24 @@ void NewTabPageSyncHandler::SendSyncMessageToPage( WideToUTF8(l10n_util::GetString(IDS_SYNC_NTP_SYNC_SECTION_TITLE)); std::string linkurl; switch (type) { - case SyncStatusUIHelper::PRE_SYNCED: + case HIDE: + case PROMOTION: msgtype = "presynced"; break; - case SyncStatusUIHelper::SYNCED: - msgtype = "synced"; - linktext = - WideToUTF8(l10n_util::GetString(IDS_SYNC_NTP_VIEW_ONLINE_LINK)); - linkurl = kSyncDefaultViewOnlineUrl; - user = UTF16ToWide(sync_service_->GetAuthenticatedUsername()); - msg = WideToUTF8(l10n_util::GetStringF(IDS_SYNC_NTP_SYNCED_TO, user)); - break; - case SyncStatusUIHelper::SYNC_ERROR: + case SYNC_ERROR: title = WideToUTF8( l10n_util::GetString(IDS_SYNC_NTP_SYNC_SECTION_ERROR_TITLE)); msgtype = "error"; break; + default: + NOTREACHED(); + break; } // If there is no message to show, we should hide the sync section // altogether. - if (msg.empty()) { + if (type == HIDE || msg.empty()) { value.SetBoolean(L"syncsectionisvisible", false); } else { value.SetBoolean(L"syncsectionisvisible", true); 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 5931684..9774640 100644 --- a/chrome/browser/dom_ui/new_tab_page_sync_handler.h +++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.h @@ -36,8 +36,13 @@ class NewTabPageSyncHandler : public DOMMessageHandler, virtual void OnStateChanged(); private: + enum MessageType { + HIDE, + PROMOTION, + SYNC_ERROR, + }; // Helper to invoke the |syncMessageChanged| JS function on the new tab page. - void SendSyncMessageToPage(SyncStatusUIHelper::MessageType type, + void SendSyncMessageToPage(MessageType type, std::string msg, std::string linktext); // Helper to query the sync service and figure out what to send to @@ -48,6 +53,10 @@ class NewTabPageSyncHandler : public DOMMessageHandler, // Helper to send a message to the NNTP which hides the sync section. void HideSyncStatusSection(); + // Helper to convert from a sync status message type to an NTP specific one. + static MessageType FromSyncStatusMessageType( + SyncStatusUIHelper::MessageType type); + // Cached pointer to ProfileSyncService. ProfileSyncService* sync_service_; diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js index a130105..7c98c21 100644 --- a/chrome/browser/resources/new_new_tab.js +++ b/chrome/browser/resources/new_new_tab.js @@ -728,6 +728,7 @@ function syncMessageChanged(newMessage) { // Hide the section if the message is emtpy. if (!newMessage.syncsectionisvisible) { + style.display = 'none'; return; } style.display = 'block'; diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 3dbf1d7..2efba68 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -212,9 +212,9 @@ void ProfileSyncService::UpdateLastSyncedTime() { void ProfileSyncService::OnUnrecoverableError() { unrecoverable_error_detected_ = true; change_processor_->Stop(); - - if (SetupInProgress()) - wizard_.Step(SyncSetupWizard::FATAL_ERROR); + + // Tell the wizard so it can inform the user only if it is already open. + wizard_.Step(SyncSetupWizard::FATAL_ERROR); FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable."; } @@ -338,17 +338,19 @@ void ProfileSyncService::OnUserSubmittedAuth( void ProfileSyncService::OnUserAcceptedMergeAndSync() { base::TimeTicks start_time = base::TimeTicks::Now(); + bool not_first_run = model_associator_->SyncModelHasUserCreatedNodes(); bool merge_success = model_associator_->AssociateModels(); UMA_HISTOGRAM_MEDIUM_TIMES("Sync.UserPerceivedBookmarkAssociation", base::TimeTicks::Now() - start_time); - - wizard_.Step(SyncSetupWizard::DONE); // TODO(timsteele): error state? if (!merge_success) { LOG(ERROR) << "Model assocation failed."; OnUnrecoverableError(); return; } + wizard_.Step(not_first_run ? SyncSetupWizard::DONE : + SyncSetupWizard::DONE_FIRST_TIME); + change_processor_->Start(profile_->GetBookmarkModel(), backend_->GetUserShareHandle()); FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); @@ -385,17 +387,19 @@ void ProfileSyncService::StartProcessingChangesIfReady() { // We're ready to merge the models. base::TimeTicks start_time = base::TimeTicks::Now(); + bool not_first_run = model_associator_->SyncModelHasUserCreatedNodes(); bool merge_success = model_associator_->AssociateModels(); UMA_HISTOGRAM_TIMES("Sync.BookmarkAssociationTime", base::TimeTicks::Now() - start_time); - - wizard_.Step(SyncSetupWizard::DONE); // TODO(timsteele): error state? if (!merge_success) { - LOG(ERROR) << "Model assocation failed."; - OnUnrecoverableError(); - return; + LOG(ERROR) << "Model assocation failed."; + OnUnrecoverableError(); + return; } + wizard_.Step(not_first_run ? SyncSetupWizard::DONE : + SyncSetupWizard::DONE_FIRST_TIME); + change_processor_->Start(profile_->GetBookmarkModel(), backend_->GetUserShareHandle()); FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); diff --git a/chrome/browser/sync/resources/gaia_login.html b/chrome/browser/sync/resources/gaia_login.html index 478dce7..7f16c7c 100644 --- a/chrome/browser/sync/resources/gaia_login.html +++ b/chrome/browser/sync/resources/gaia_login.html @@ -34,6 +34,9 @@ text-align: left; margin: 5px; } + #gaia_loginform { + margin-bottom: 0.5em; + } --></style> </head> <body bgcolor="#ffffff" vlink="#666666" @@ -190,8 +193,8 @@ </div> <form id="gaia_loginform" onsubmit="sendCredentialsAndClose(); return false;"> <div id="gaia_loginbox"> -<table class="form-noindent" cellspacing="3" cellpadding="5" width="100%" - border="0"> +<table class="form-noindent" cellspacing="3" cellpadding="5" width="75%" + border="0" align="center"> <tr> <td valign="top" style="text-align:center" nowrap="nowrap" bgcolor="#e8eefa"> @@ -313,7 +316,8 @@ <td> <input id="signIn" type="button" class="gaia le button" name="signIn" i18n-values="value:signin" - onclick="sendCredentialsAndClose();" /> + onclick="sendCredentialsAndClose();" + style="width:85" /> </td> </tr> </table> @@ -346,7 +350,8 @@ </tr> </table> <div class="endaligned"> - <input type="button" name="cancel" i18n-values="value:cancel" onclick="CloseDialog();"/> + <input type="button" name="cancel" i18n-values="value:cancel" + onclick="CloseDialog();" style="width:85" /> </div> </body> </html> diff --git a/chrome/browser/sync/resources/merge_and_sync.html b/chrome/browser/sync/resources/merge_and_sync.html index 8af2fc1..f350ae0 100644 --- a/chrome/browser/sync/resources/merge_and_sync.html +++ b/chrome/browser/sync/resources/merge_and_sync.html @@ -3,8 +3,20 @@ <title></title> <style type="text/css"> body,td,div,p,a,font,span {font-family: arial,sans-serif;} - body { bgcolor:"#ffffff" } + body { bgcolor:"#ffffff" } .gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } +.endaligned { + text-align: right; +} +html[dir='rtl'] .endaligned { + text-align: left; +} +.textaligned { + text-align: left; +} +html[dir='rtl'] .textaligned { + text-align: right; +} </style> <script> function advanceThrobber() { @@ -12,18 +24,18 @@ throbber.style.backgroundPositionX = ((parseInt(throbber.style.backgroundPositionX) - 16) % 576) + 'px'; } - + function acceptMergeAndSync() { var throbber = document.getElementById('throbber_container'); throbber.style.display = "inline"; document.getElementById("acceptMerge").disabled = true; chrome.send("SubmitMergeAndSync", [""]); } - + function Close() { chrome.send("DialogClose", [""]); } - + function showMergeAndSyncDone() { var throbber = document.getElementById('throbber_container'); throbber.style.display = "none"; @@ -33,7 +45,7 @@ document.getElementById("close").value = templateData['closelabel']; setTimeout(Close, 1600); } - + function showMergeAndSyncError() { var throbber = document.getElementById('throbber_container'); throbber.style.display = "none"; @@ -41,36 +53,37 @@ "<p><font size='-1'><b>" + templateData['setuperror'] + "</b></font></p>"; } - + </script> </head> <body onload="setInterval(advanceThrobber, 30);"> -<div id="header"> - <p><font size="-1"><b><span i18n-content="introduction"></span></b> - </font></p> -</div> -<br /> -<img src="merge_and_sync.png" i18n-values="alt:mergeandsynclabel" /> -<br /> -<p><font size="-1"><span i18n-content="mergeandsyncwarning"></span></font></p> -<br /> -<table align="right"> - <tr> - <td> +<table height="100%"> + <tr valign="top"> + <td align="center"> + <div id="header" align="left"> + <p class="textaligned"><font size="-1"><b> + <span i18n-content="introduction"></span> + </b></font></p> + </div> + <br /> + <img src="merge_and_sync.png" i18n-values="alt:mergeandsynclabel" /> + <br /> + <p class="textaligned"><font size="-1"><span i18n-content="mergeandsyncwarning"></span></font></p> + <br /> <div id="throbber_container" style="display:none"> <div id="throb" style="background-image:url(throbber.png); width:16px; height:16px; background-position:0px;"> </div> </div> </td> - <td> + </tr> + <tr class="endaligned" valign="bottom"> + <td class="endaligned"> <input id="acceptMerge" type="button" class="gaia le button" name="accept" i18n-values="value:mergeandsynclabel" onclick="acceptMergeAndSync();" /> - </td> - <td> <input id="close" type="button" i18n-values="value:abortlabel" - onclick="Close();"/> + onclick="Close();" style="width:85"/> </td> </tr> </table> diff --git a/chrome/browser/sync/resources/setup_done.html b/chrome/browser/sync/resources/setup_done.html new file mode 100644 index 0000000..897f191 --- /dev/null +++ b/chrome/browser/sync/resources/setup_done.html @@ -0,0 +1,59 @@ +<html i18n-values="dir:textdirection;"> +<head> +<title></title> +<style type="text/css"> +body,td,div,p,a,font,span { + font-family: arial,sans-serif; + } +body { + bgcolor:"#ffffff" + } +.gaia.le.button { + font-family: Arial, Helvetica, sans-serif; + font-size: smaller; +} +.endaligned { + text-align: right; + align: right; +} +html[dir='rtl'] .endaligned { + text-align: left; + align: left; +} +</style> +<script> + function setShowFirstTimeSetupSummary() { + document.getElementById("summary").innerHTML = + "<p><font size='-1'>" + templateData['firsttimesetupsummary'] + + "</font></p>"; + } + function setSyncedToUser(synced_to) { + document.getElementById('user').innerHTML = synced_to; + } +</script> +<body bgcolor="#ffffff" vlink="#666666 + i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize" + style="margin: 10px"> +<table height="100%" width="100%" margin="0" cellpadding="0"> + <tr valign="top"> + <td> + <p><font size="-1"><b><span i18n-content="success"></span></b></font></p> + <div align="center"> + <img src="success-large.png" /> + </div> + <br /> + <p><font size="-1"><span id="user"></span></font></p> + <div id="summary"> + <p><font size="-1"><span i18n-content="setupsummary"></span></font></p> + </div> + </td> + </tr> + <tr valign="bottom"> + <td class="endaligned"> + <input id="close" type="submit" i18n-values="value:okay" style="width:85" + onclick='chrome.send("DialogClose", [""])' /> + </td> + </tr> +</table> +</body> +</html> diff --git a/chrome/browser/sync/resources/setup_flow.html b/chrome/browser/sync/resources/setup_flow.html index f818787..9bec21a 100644 --- a/chrome/browser/sync/resources/setup_flow.html +++ b/chrome/browser/sync/resources/setup_flow.html @@ -8,6 +8,11 @@ document.getElementById("login").style.display = "none"; document.getElementById("merge").style.display = "block"; } + function showSetupDone() { + document.getElementById("login").style.display = "none"; + document.getElementById("merge").style.display = "none"; + document.getElementById("done").style.display = "block"; + } </script> </HEAD> <BODY style="margin:0; border:0;"> @@ -15,5 +20,7 @@ src="chrome://syncresources/gaialogin"></iframe> <iframe id="merge" frameborder="0" width="100%" scrolling="no" height="100%" src="chrome://syncresources/mergeandsync" style="display:none"></iframe> + <iframe id="done" frameborder="0" width="100%" scrolling="no" height="100%" + src="chrome://syncresources/setupdone" style="display:none"></iframe> </BODY> </HTML> diff --git a/chrome/browser/views/confirm_message_box_dialog.cc b/chrome/browser/views/confirm_message_box_dialog.cc index fe66582..6182bd8 100644 --- a/chrome/browser/views/confirm_message_box_dialog.cc +++ b/chrome/browser/views/confirm_message_box_dialog.cc @@ -25,11 +25,38 @@ void ConfirmMessageBoxDialog::Run(gfx::NativeWindow parent, window->Show(); } +// static +void ConfirmMessageBoxDialog::RunWithCustomConfiguration( + gfx::NativeWindow parent, + ConfirmMessageBoxObserver* observer, + const std::wstring& message_text, + const std::wstring& window_title, + const std::wstring& confirm_label, + const std::wstring& reject_label, + const gfx::Size& preferred_size) { + DCHECK(observer); + ConfirmMessageBoxDialog* dialog = new ConfirmMessageBoxDialog(observer, + message_text, window_title); + dialog->preferred_size_ = preferred_size; + dialog->confirm_label_ = confirm_label; + dialog->reject_label_ = reject_label; + views::Window* window = views::Window::CreateChromeWindow( + parent, gfx::Rect(), dialog); + window->Show(); +} + ConfirmMessageBoxDialog::ConfirmMessageBoxDialog( ConfirmMessageBoxObserver* observer, const std::wstring& message_text, const std::wstring& window_title) : observer_(observer), - window_title_(window_title) { + window_title_(window_title), + preferred_size_(gfx::Size(views::Window::GetLocalizedContentsSize( + IDS_CONFIRM_MESSAGE_BOX_DEFAULT_WIDTH_CHARS, + IDS_CONFIRM_MESSAGE_BOX_DEFAULT_HEIGHT_LINES))), + confirm_label_(l10n_util::GetString( + IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL)), + reject_label_(l10n_util::GetString( + IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL)) { message_label_ = new views::Label(message_text); message_label_->SetMultiLine(true); l10n_util::TextDirection direction = @@ -59,10 +86,10 @@ std::wstring ConfirmMessageBoxDialog::GetWindowTitle() const { std::wstring ConfirmMessageBoxDialog::GetDialogButtonLabel( MessageBoxFlags::DialogButton button) const { if (button == MessageBoxFlags::DIALOGBUTTON_OK) { - return l10n_util::GetString(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); + return confirm_label_; } if (button == MessageBoxFlags::DIALOGBUTTON_CANCEL) - return l10n_util::GetString(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); + return reject_label_; return DialogDelegate::GetDialogButtonLabel(button); } @@ -84,7 +111,5 @@ void ConfirmMessageBoxDialog::Layout() { } gfx::Size ConfirmMessageBoxDialog::GetPreferredSize() { - return gfx::Size(views::Window::GetLocalizedContentsSize( - IDS_CONFIRM_MESSAGE_BOX_DEFAULT_WIDTH_CHARS, - IDS_CONFIRM_MESSAGE_BOX_DEFAULT_HEIGHT_LINES)); + return preferred_size_; }
\ No newline at end of file diff --git a/chrome/browser/views/confirm_message_box_dialog.h b/chrome/browser/views/confirm_message_box_dialog.h index b2ca806..81c0213 100644 --- a/chrome/browser/views/confirm_message_box_dialog.h +++ b/chrome/browser/views/confirm_message_box_dialog.h @@ -28,18 +28,28 @@ class ConfirmMessageBoxDialog : public views::DialogDelegate, public views::View { public: // The method presents a modal confirmation dialog to the user with the title - // |window_title| and message |message_text|. |observer| will be notified - // when the user makes a decision or closes the dialog. Note that this class - // guarantees it will call one of the observer's methods, so it is the - // caller's responsibility to ensure |observer| lives until one of the - // methods is invoked; it can be deleted thereafter from this class' point - // of view. |parent| specifies where to insert the view into the hierarchy - // and effectively assumes ownership of the dialog. + // |window_title| and message |message_text|, and 'Yes' 'No' buttons. + // |observer| will be notified when the user makes a decision or closes the + // dialog. Note that this class guarantees it will call one of the observer's + // methods, so it is the caller's responsibility to ensure |observer| lives + // until one of the methods is invoked; it can be deleted thereafter from this + // class' point of view. |parent| specifies where to insert the view into the + // hierarchy and effectively assumes ownership of the dialog. static void Run(gfx::NativeWindow parent, ConfirmMessageBoxObserver* observer, const std::wstring& message_text, const std::wstring& window_title); + // A variant of the above for when the message text is longer/shorter than + // what the default size of this dialog can accommodate. + static void RunWithCustomConfiguration(gfx::NativeWindow parent, + ConfirmMessageBoxObserver* observer, + const std::wstring& message_text, + const std::wstring& window_title, + const std::wstring& confirm_label, + const std::wstring& reject_label, + const gfx::Size& preferred_size); + virtual ~ConfirmMessageBoxDialog() {} // views::DialogDelegate implementation. @@ -47,6 +57,10 @@ class ConfirmMessageBoxDialog : public views::DialogDelegate, virtual std::wstring GetWindowTitle() const; virtual std::wstring GetDialogButtonLabel( MessageBoxFlags::DialogButton button) const; + virtual int GetDefaultDialogButton() const { + return MessageBoxFlags::DIALOGBUTTON_CANCEL; + } + virtual bool Accept(); virtual bool Cancel(); @@ -69,6 +83,13 @@ class ConfirmMessageBoxDialog : public views::DialogDelegate, // This is the Title bar text. std::wstring window_title_; + // The text for the 'OK' and 'CANCEL' buttons. + std::wstring confirm_label_; + std::wstring reject_label_; + + // The preferred size of the dialog. + gfx::Size preferred_size_; + // The observer to notify of acceptance or cancellation. ConfirmMessageBoxObserver* observer_; diff --git a/chrome/browser/views/options/content_page_view.cc b/chrome/browser/views/options/content_page_view.cc index 2f8efb0..a3df28c 100644 --- a/chrome/browser/views/options/content_page_view.cc +++ b/chrome/browser/views/options/content_page_view.cc @@ -128,9 +128,19 @@ void ContentPageView::ButtonPressed( #ifdef CHROME_PERSONALIZATION } else if (sender == sync_start_stop_button_) { DCHECK(sync_service_); + if (sync_service_->HasSyncSetupCompleted()) { - sync_service_->DisableForUser(); - ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS); + ConfirmMessageBoxDialog::RunWithCustomConfiguration( + GetWindow()->GetNativeWindow(), + this, + l10n_util::GetString(IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL), + l10n_util::GetString(IDS_SYNC_STOP_SYNCING_BUTTON_LABEL), + l10n_util::GetString(IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL), + l10n_util::GetString(IDS_CANCEL), + gfx::Size(views::Window::GetLocalizedContentsSize( + IDS_CONFIRM_STOP_SYNCING_DIALOG_WIDTH_CHARS, + IDS_CONFIRM_STOP_SYNCING_DIALOG_HEIGHT_LINES))); + return; } else { sync_service_->EnableForUser(); ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS); @@ -422,6 +432,11 @@ void ContentPageView::InitBrowsingDataGroup() { L"", true); } +void ContentPageView::OnConfirmMessageAccept() { + sync_service_->DisableForUser(); + ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS); +} + #ifdef CHROME_PERSONALIZATION void ContentPageView::InitSyncGroup() { sync_status_label_ = new views::Label; diff --git a/chrome/browser/views/options/content_page_view.h b/chrome/browser/views/options/content_page_view.h index 62133c0..e3902c4 100644 --- a/chrome/browser/views/options/content_page_view.h +++ b/chrome/browser/views/options/content_page_view.h @@ -7,6 +7,7 @@ #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/views/options/options_page_view.h" +#include "chrome/browser/views/confirm_message_box_dialog.h" #include "chrome/common/pref_member.h" #include "views/controls/button/button.h" #include "views/controls/link.h" @@ -30,7 +31,8 @@ class ContentPageView : public OptionsPageView, public views::LinkController, public ProfileSyncServiceObserver, #endif - public views::ButtonListener { + public views::ButtonListener, + public ConfirmMessageBoxObserver { public: explicit ContentPageView(Profile* profile); virtual ~ContentPageView(); @@ -41,6 +43,9 @@ class ContentPageView : public OptionsPageView, // views::LinkController method. virtual void LinkActivated(views::Link* source, int event_flags); + // ConfirmMessageBoxObserver implementation. + virtual void OnConfirmMessageAccept(); + #ifdef CHROME_PERSONALIZATION // ProfileSyncServiceObserver method. virtual void OnStateChanged(); diff --git a/chrome/browser/views/sync/sync_setup_flow.cc b/chrome/browser/views/sync/sync_setup_flow.cc index 7019c39..01a5728 100644 --- a/chrome/browser/views/sync/sync_setup_flow.cc +++ b/chrome/browser/views/sync/sync_setup_flow.cc @@ -25,6 +25,7 @@ // XPath expression for finding specific iframes. static const wchar_t* kLoginIFrameXPath = L"//iframe[@id='login']"; static const wchar_t* kMergeIFrameXPath = L"//iframe[@id='merge']"; +static const wchar_t* kDoneIframeXPath = L"//iframe[@id='done']"; // Helper function to read the JSON string from the Value parameter. static std::string GetJsonResponse(const Value* content) { @@ -114,8 +115,23 @@ void FlowHandler::ShowMergeAndSync() { dom_ui_->CallJavascriptFunction(L"showMergeAndSync"); } -void FlowHandler::ShowMergeAndSyncDone() { - ExecuteJavascriptInIFrame(kMergeIFrameXPath, L"showMergeAndSyncDone();"); +void FlowHandler::ShowSetupDone(const std::wstring& user) { + StringValue synced_to_string(WideToUTF8(l10n_util::GetStringF( + IDS_SYNC_NTP_SYNCED_TO, user))); + std::string json; + JSONWriter::Write(&synced_to_string, false, &json); + std::wstring javascript = std::wstring(L"setSyncedToUser") + + L"(" + UTF8ToWide(json) + L");"; + ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript); + + if (dom_ui_) + dom_ui_->CallJavascriptFunction(L"showSetupDone", synced_to_string); +} + +void FlowHandler::ShowFirstTimeDone(const std::wstring& user) { + ExecuteJavascriptInIFrame(kDoneIframeXPath, + L"setShowFirstTimeSetupSummary();"); + ShowSetupDone(user); } void FlowHandler::ShowMergeAndSyncError() { @@ -153,7 +169,8 @@ void SyncSetupFlow::GetDialogSize(gfx::Size* size) const { void SyncSetupFlow::OnDialogClosed(const std::string& json_retval) { DCHECK(json_retval.empty()); container_->set_flow(NULL); // Sever ties from the wizard. - if (current_state_ == SyncSetupWizard::DONE) { + if (current_state_ == SyncSetupWizard::DONE || + current_state_ == SyncSetupWizard::DONE_FIRST_TIME) { service_->SetSyncSetupCompleted(); } @@ -171,6 +188,7 @@ void SyncSetupFlow::OnDialogClosed(const std::string& json_retval) { ProfileSyncService::SyncEvent( ProfileSyncService::CANCEL_DURING_SIGNON_AFTER_MERGE); break; + case SyncSetupWizard::DONE_FIRST_TIME: case SyncSetupWizard::DONE: UMA_HISTOGRAM_MEDIUM_TIMES("Sync.UserPerceivedAuthorizationTime", base::TimeTicks::Now() - login_start_time_); @@ -212,6 +230,7 @@ bool SyncSetupFlow::ShouldAdvance(SyncSetupWizard::State state) { return current_state_ == SyncSetupWizard::GAIA_SUCCESS; case SyncSetupWizard::FATAL_ERROR: return true; // You can always hit the panic button. + case SyncSetupWizard::DONE_FIRST_TIME: case SyncSetupWizard::DONE: return current_state_ == SyncSetupWizard::MERGE_AND_SYNC || current_state_ == SyncSetupWizard::GAIA_SUCCESS; @@ -244,11 +263,11 @@ void SyncSetupFlow::Advance(SyncSetupWizard::State advance_state) { if (current_state_ == SyncSetupWizard::MERGE_AND_SYNC) flow_handler_->ShowMergeAndSyncError(); break; + case SyncSetupWizard::DONE_FIRST_TIME: + flow_handler_->ShowFirstTimeDone(service_->GetAuthenticatedUsername()); + break; case SyncSetupWizard::DONE: - if (current_state_ == SyncSetupWizard::MERGE_AND_SYNC) - flow_handler_->ShowMergeAndSyncDone(); - else if (current_state_ == SyncSetupWizard::GAIA_SUCCESS) - flow_handler_->ShowGaiaSuccessAndClose(); + flow_handler_->ShowSetupDone(service_->GetAuthenticatedUsername()); break; default: NOTREACHED() << "Invalid advance state: " << advance_state; diff --git a/chrome/browser/views/sync/sync_setup_flow.h b/chrome/browser/views/sync/sync_setup_flow.h index f02b292..4bc7d60 100644 --- a/chrome/browser/views/sync/sync_setup_flow.h +++ b/chrome/browser/views/sync/sync_setup_flow.h @@ -170,8 +170,9 @@ class FlowHandler : public DOMMessageHandler { void ShowGaiaSuccessAndClose(); void ShowGaiaSuccessAndSettingUp(); void ShowMergeAndSync(); - void ShowMergeAndSyncDone(); void ShowMergeAndSyncError(); + void ShowSetupDone(const std::wstring& user); + void ShowFirstTimeDone(const std::wstring& user); void set_flow(SyncSetupFlow* flow) { flow_ = flow; diff --git a/chrome/browser/views/sync/sync_setup_wizard.cc b/chrome/browser/views/sync/sync_setup_wizard.cc index 5e46382..31afcea 100644 --- a/chrome/browser/views/sync/sync_setup_wizard.cc +++ b/chrome/browser/views/sync/sync_setup_wizard.cc @@ -80,7 +80,7 @@ void SyncResourcesSource::StartDataRequest(const std::string& path_raw, localized_strings.SetString(L"settingup", l10n_util::GetString(IDS_SYNC_LOGIN_SETTING_UP)); localized_strings.SetString(L"success", - l10n_util::GetString(IDS_SYNC_LOGIN_SUCCESS)); + l10n_util::GetString(IDS_SYNC_SUCCESS)); localized_strings.SetString(L"errorsigningin", l10n_util::GetString(IDS_SYNC_ERROR_SIGNING_IN)); static const base::StringPiece html(ResourceBundle::GetSharedInstance() @@ -98,8 +98,6 @@ void SyncResourcesSource::StartDataRequest(const std::string& path_raw, l10n_util::GetString(IDS_ABORT)); localized_strings.SetString(L"closelabel", l10n_util::GetString(IDS_CLOSE)); - localized_strings.SetString(L"alldone", - l10n_util::GetString(IDS_SYNC_MERGE_ALL_DONE)); localized_strings.SetString(L"mergeandsyncwarning", l10n_util::GetString(IDS_SYNC_MERGE_WARNING)); localized_strings.SetString(L"setuperror", @@ -110,6 +108,21 @@ void SyncResourcesSource::StartDataRequest(const std::string& path_raw, SetFontAndTextDirection(&localized_strings); response = jstemplate_builder::GetI18nTemplateHtml( html, &localized_strings); + } else if (path_raw == chrome::kSyncSetupDonePath) { + DictionaryValue localized_strings; + localized_strings.SetString(L"success", + l10n_util::GetString(IDS_SYNC_SUCCESS)); + localized_strings.SetString(L"setupsummary", + l10n_util::GetString(IDS_SYNC_SETUP_ALL_DONE)); + localized_strings.SetString(L"firsttimesetupsummary", + l10n_util::GetString(IDS_SYNC_SETUP_FIRST_TIME_ALL_DONE)); + localized_strings.SetString(L"okay", + l10n_util::GetString(IDS_SYNC_SETUP_OK_BUTTON_LABEL)); + static const base::StringPiece html(ResourceBundle::GetSharedInstance() + .GetRawDataResource(IDR_SYNC_SETUP_DONE_HTML)); + SetFontAndTextDirection(&localized_strings); + response = jstemplate_builder::GetI18nTemplateHtml( + html, &localized_strings); } else if (path_raw == chrome::kSyncSetupFlowPath) { static const base::StringPiece html(ResourceBundle::GetSharedInstance() .GetRawDataResource(IDR_SYNC_SETUP_FLOW_HTML)); @@ -146,7 +159,7 @@ void SyncSetupWizard::Step(State advance_state) { flow->Advance(advance_state); } else if (!service_->profile()->GetPrefs()->GetBoolean( prefs::kSyncHasSetupCompleted)) { - if (advance_state == DONE || advance_state == GAIA_SUCCESS) + if (IsTerminalState(advance_state)) return; // No flow is in progress, and we have never escorted the user all the // way through the wizard flow. @@ -155,13 +168,21 @@ void SyncSetupWizard::Step(State advance_state) { } else { // No flow in in progress, but we've finished the wizard flow once before. // This is just a discrete run. - if (advance_state == DONE || advance_state == GAIA_SUCCESS) + if (IsTerminalState(advance_state)) return; // Nothing to do. flow_container_->set_flow(SyncSetupFlow::Run(service_, flow_container_, advance_state, GetEndStateForDiscreteRun(advance_state))); } } +// static +bool SyncSetupWizard::IsTerminalState(State advance_state) { + return advance_state == GAIA_SUCCESS || + advance_state == DONE || + advance_state == DONE_FIRST_TIME || + advance_state == FATAL_ERROR; +} + bool SyncSetupWizard::IsVisible() const { return flow_container_->get_flow() != NULL; } diff --git a/chrome/browser/views/sync/sync_setup_wizard.h b/chrome/browser/views/sync/sync_setup_wizard.h index f51ba64..1d36f61 100644 --- a/chrome/browser/views/sync/sync_setup_wizard.h +++ b/chrome/browser/views/sync/sync_setup_wizard.h @@ -19,10 +19,23 @@ class ProfileSyncService; class SyncSetupWizard { public: enum State { + // Show the Google Account login UI. GAIA_LOGIN = 0, + // A login attempt succeeded. Depending on initial conditions, this may + // cause a transition to DONE, or to wait for an explicit transition (via + // Step) to the next state. GAIA_SUCCESS, + // The user needs to accept a merge and sync warning to proceed. MERGE_AND_SYNC, + // The panic switch. Something went terribly wrong during setup and we + // can't recover. FATAL_ERROR, + // A final state for when setup completes and it is possible it is the + // user's first time (globally speaking) as the cloud doesn't have any + // bookmarks. We show additional info in this case to explain setting up + // more computers. + DONE_FIRST_TIME, + // A catch-all done case for any setup process. DONE }; @@ -51,6 +64,9 @@ class SyncSetupWizard { // the end state to pass to Run for a given |start_state|. static State GetEndStateForDiscreteRun(State start_state); + // Helper to return whether |state| warrants starting a new flow. + static bool IsTerminalState(State state); + ProfileSyncService* service_; #if defined(OS_WIN) diff --git a/chrome/browser/views/sync/sync_setup_wizard_unittest.cc b/chrome/browser/views/sync/sync_setup_wizard_unittest.cc index 4861649..fec7ef3 100644 --- a/chrome/browser/views/sync/sync_setup_wizard_unittest.cc +++ b/chrome/browser/views/sync/sync_setup_wizard_unittest.cc @@ -254,10 +254,11 @@ TEST_F(SyncSetupWizardTest, InitialStepMergeAndSync) { EXPECT_TRUE(service_->user_accepted_merge_and_sync_); EXPECT_FALSE(service_->user_cancelled_dialog_); service_->ResetTestStats(); - wizard_->Step(SyncSetupWizard::DONE); // No merge and sync. + wizard_->Step(SyncSetupWizard::DONE_FIRST_TIME); // No merge and sync. EXPECT_TRUE(wizard_->IsVisible()); EXPECT_FALSE(test_window_->TestAndResetWasShowHTMLDialogCalled()); - EXPECT_EQ(SyncSetupWizard::DONE, test_window_->flow()->current_state_); + EXPECT_EQ(SyncSetupWizard::DONE_FIRST_TIME, + test_window_->flow()->current_state_); } TEST_F(SyncSetupWizardTest, DialogCancelled) { @@ -294,12 +295,18 @@ TEST_F(SyncSetupWizardTest, InvalidTransitions) { EXPECT_FALSE(wizard_->IsVisible()); EXPECT_FALSE(test_window_->TestAndResetWasShowHTMLDialogCalled()); + wizard_->Step(SyncSetupWizard::DONE_FIRST_TIME); + EXPECT_FALSE(wizard_->IsVisible()); + EXPECT_FALSE(test_window_->TestAndResetWasShowHTMLDialogCalled()); + wizard_->Step(SyncSetupWizard::GAIA_LOGIN); wizard_->Step(SyncSetupWizard::MERGE_AND_SYNC); EXPECT_EQ(SyncSetupWizard::GAIA_LOGIN, test_window_->flow()->current_state_); wizard_->Step(SyncSetupWizard::DONE); EXPECT_EQ(SyncSetupWizard::GAIA_LOGIN, test_window_->flow()->current_state_); + wizard_->Step(SyncSetupWizard::DONE_FIRST_TIME); + EXPECT_EQ(SyncSetupWizard::GAIA_LOGIN, test_window_->flow()->current_state_); wizard_->Step(SyncSetupWizard::GAIA_SUCCESS); wizard_->Step(SyncSetupWizard::MERGE_AND_SYNC); @@ -325,6 +332,17 @@ TEST_F(SyncSetupWizardTest, FullSuccessfulRunSetsPref) { prefs::kSyncHasSetupCompleted)); } +TEST_F(SyncSetupWizardTest, FirstFullSuccessfulRunSetsPref) { + wizard_->Step(SyncSetupWizard::GAIA_LOGIN); + wizard_->Step(SyncSetupWizard::GAIA_SUCCESS); + wizard_->Step(SyncSetupWizard::MERGE_AND_SYNC); + wizard_->Step(SyncSetupWizard::DONE_FIRST_TIME); + test_window_->CloseDialog(); + EXPECT_FALSE(wizard_->IsVisible()); + EXPECT_TRUE(service_->profile()->GetPrefs()->GetBoolean( + prefs::kSyncHasSetupCompleted)); +} + TEST_F(SyncSetupWizardTest, DiscreteRun) { DictionaryValue dialog_args; // For a discrete run, we need to have ran through setup once. diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index 4c29e28..97b0381 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -20,14 +20,15 @@ #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/character_encoding.h" #include "chrome/browser/encoding_menu_controller.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" +#include "chrome/browser/sync/sync_status_ui_helper.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/user_data_manager.h" #include "chrome/browser/views/bookmark_menu_button.h" #include "chrome/browser/views/browser_actions_container.h" @@ -1133,8 +1134,18 @@ void ToolbarView::CreateAppMenu() { app_menu_contents_->AddSeparator(); #ifdef CHROME_PERSONALIZATION if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableSync)) { - app_menu_contents_->AddItem(IDC_SYNC_BOOKMARKS, - l10n_util::GetString(IDS_SYNC_MY_BOOKMARKS_LABEL) + L"..."); + std::wstring label; + std::wstring link; + // TODO(timsteele): Need a ui helper method to just get the type without + // needing labels. + SyncStatusUIHelper::MessageType type = SyncStatusUIHelper::GetLabels( + browser_->profile()->GetProfileSyncService(), &label, &link); + label = type == SyncStatusUIHelper::SYNCED ? + l10n_util::GetString(IDS_SYNC_MENU_BOOKMARKS_SYNCED_LABEL) : + type == SyncStatusUIHelper::SYNC_ERROR ? + l10n_util::GetString(IDS_SYNC_MENU_BOOKMARK_SYNC_ERROR_LABEL) : + l10n_util::GetString(IDS_SYNC_START_SYNC_BUTTON_LABEL); + app_menu_contents_->AddItem(IDC_SYNC_BOOKMARKS, label); app_menu_contents_->AddSeparator(); } #endif |