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