1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/ntp/new_tab_page_sync_handler.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/strings/string_split.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/values.h" 16 #include "chrome/browser/net/chrome_url_request_context.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/signin/signin_manager_factory.h" 19 #include "chrome/browser/signin/signin_promo.h" 20 #include "chrome/browser/sync/profile_sync_service.h" 21 #include "chrome/browser/sync/profile_sync_service_factory.h" 22 #include "chrome/browser/ui/browser.h" 23 #include "chrome/browser/ui/browser_finder.h" 24 #include "chrome/browser/ui/chrome_pages.h" 25 #include "chrome/browser/ui/webui/signin/login_ui_service.h" 26 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" 27 #include "chrome/common/pref_names.h" 28 #include "components/signin/core/browser/signin_manager.h" 29 #include "content/public/browser/render_view_host.h" 30 #include "content/public/browser/web_ui.h" 31 #include "grit/generated_resources.h" 32 #include "net/cookies/cookie_monster.h" 33 #include "net/url_request/url_request_context.h" 34 #include "ui/base/l10n/l10n_util.h" 35 36 NewTabPageSyncHandler::NewTabPageSyncHandler() : sync_service_(NULL), 37 waiting_for_initial_page_load_(true) { 38 } 39 40 NewTabPageSyncHandler::~NewTabPageSyncHandler() { 41 if (sync_service_) 42 sync_service_->RemoveObserver(this); 43 } 44 45 // static 46 NewTabPageSyncHandler::MessageType 47 NewTabPageSyncHandler::FromSyncStatusMessageType( 48 sync_ui_util::MessageType type) { 49 switch (type) { 50 case sync_ui_util::SYNC_ERROR: 51 return SYNC_ERROR; 52 case sync_ui_util::SYNC_PROMO: 53 return SYNC_PROMO; 54 case sync_ui_util::PRE_SYNCED: 55 case sync_ui_util::SYNCED: 56 default: 57 return HIDE; 58 } 59 } 60 61 void NewTabPageSyncHandler::RegisterMessages() { 62 sync_service_ = ProfileSyncServiceFactory::GetInstance()->GetForProfile( 63 Profile::FromWebUI(web_ui())); 64 if (sync_service_) 65 sync_service_->AddObserver(this); 66 profile_pref_registrar_.Init(Profile::FromWebUI(web_ui())->GetPrefs()); 67 profile_pref_registrar_.Add( 68 prefs::kSigninAllowed, 69 base::Bind(&NewTabPageSyncHandler::OnSigninAllowedPrefChange, 70 base::Unretained(this))); 71 72 web_ui()->RegisterMessageCallback("GetSyncMessage", 73 base::Bind(&NewTabPageSyncHandler::HandleGetSyncMessage, 74 base::Unretained(this))); 75 web_ui()->RegisterMessageCallback("SyncLinkClicked", 76 base::Bind(&NewTabPageSyncHandler::HandleSyncLinkClicked, 77 base::Unretained(this))); 78 } 79 80 void NewTabPageSyncHandler::HandleGetSyncMessage(const base::ListValue* args) { 81 waiting_for_initial_page_load_ = false; 82 BuildAndSendSyncStatus(); 83 } 84 85 void NewTabPageSyncHandler::HideSyncStatusSection() { 86 SendSyncMessageToPage(HIDE, std::string(), std::string()); 87 } 88 89 void NewTabPageSyncHandler::BuildAndSendSyncStatus() { 90 DCHECK(!waiting_for_initial_page_load_); 91 SigninManagerBase* signin = SigninManagerFactory::GetForProfile( 92 Profile::FromWebUI(web_ui())); 93 94 // Hide the sync status section if sync is managed or disabled entirely. 95 if (!sync_service_ || 96 sync_service_->IsManaged() || 97 !signin || 98 !signin->IsSigninAllowed()) { 99 HideSyncStatusSection(); 100 return; 101 } 102 103 // Don't show sync status if setup is not complete. 104 if (!sync_service_->HasSyncSetupCompleted()) { 105 return; 106 } 107 108 // Once sync has been enabled, the supported "sync statuses" for the NNTP 109 // from the user's perspective are: 110 // 111 // "Sync error", when we can't authenticate or establish a connection with 112 // the sync server (appropriate information appended to 113 // message). 114 base::string16 status_msg; 115 base::string16 link_text; 116 117 sync_ui_util::MessageType type = 118 sync_ui_util::GetStatusLabelsForNewTabPage(sync_service_, 119 *signin, 120 &status_msg, 121 &link_text); 122 SendSyncMessageToPage(FromSyncStatusMessageType(type), 123 base::UTF16ToUTF8(status_msg), 124 base::UTF16ToUTF8(link_text)); 125 } 126 127 void NewTabPageSyncHandler::HandleSyncLinkClicked(const base::ListValue* args) { 128 DCHECK(!waiting_for_initial_page_load_); 129 if (!sync_service_ || !sync_service_->IsSyncEnabled()) 130 return; 131 Browser* browser = 132 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()); 133 if (!browser || browser->IsAttemptingToCloseBrowser()) 134 return; 135 chrome::ShowBrowserSignin(browser, signin::SOURCE_NTP_LINK); 136 137 if (sync_service_->HasSyncSetupCompleted()) { 138 base::string16 user = base::UTF8ToUTF16(SigninManagerFactory::GetForProfile( 139 Profile::FromWebUI(web_ui()))->GetAuthenticatedUsername()); 140 base::DictionaryValue value; 141 value.SetString("syncEnabledMessage", 142 l10n_util::GetStringFUTF16(IDS_SYNC_NTP_SYNCED_TO, 143 user)); 144 web_ui()->CallJavascriptFunction("ntp.syncAlreadyEnabled", value); 145 } else { 146 ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_NTP); 147 } 148 } 149 150 void NewTabPageSyncHandler::OnStateChanged() { 151 // Don't do anything if the page has not yet loaded. 152 if (waiting_for_initial_page_load_) 153 return; 154 BuildAndSendSyncStatus(); 155 } 156 157 void NewTabPageSyncHandler::OnSigninAllowedPrefChange() { 158 // Don't do anything if the page has not yet loaded. 159 if (waiting_for_initial_page_load_) 160 return; 161 BuildAndSendSyncStatus(); 162 } 163 164 void NewTabPageSyncHandler::SendSyncMessageToPage( 165 MessageType type, std::string msg, 166 std::string linktext) { 167 base::DictionaryValue value; 168 std::string user; 169 std::string title; 170 std::string linkurl; 171 172 // If there is nothing to show, we should hide the sync section altogether. 173 if (type == HIDE || (msg.empty() && linktext.empty())) { 174 value.SetBoolean("syncsectionisvisible", false); 175 } else { 176 if (type == SYNC_ERROR) 177 title = l10n_util::GetStringUTF8(IDS_SYNC_NTP_SYNC_SECTION_ERROR_TITLE); 178 else if (type == SYNC_PROMO) 179 title = l10n_util::GetStringUTF8(IDS_SYNC_NTP_SYNC_SECTION_PROMO_TITLE); 180 else 181 NOTREACHED(); 182 183 value.SetBoolean("syncsectionisvisible", true); 184 value.SetString("msg", msg); 185 value.SetString("title", title); 186 if (linktext.empty()) { 187 value.SetBoolean("linkisvisible", false); 188 } else { 189 value.SetBoolean("linkisvisible", true); 190 value.SetString("linktext", linktext); 191 192 // The only time we set the URL is when the user is synced and we need to 193 // show a link to a web interface (e.g. http://docs.google.com). When we 194 // set that URL, HandleSyncLinkClicked won't be called when the user 195 // clicks on the link. 196 if (linkurl.empty()) { 197 value.SetBoolean("linkurlisset", false); 198 } else { 199 value.SetBoolean("linkurlisset", true); 200 value.SetString("linkurl", linkurl); 201 } 202 } 203 } 204 web_ui()->CallJavascriptFunction("ntp.syncMessageChanged", value); 205 } 206