• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/new_tab_page_sync_handler.h"
6 
7 #include <vector>
8 
9 #include "base/callback.h"
10 #include "base/string_split.h"
11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/net/chrome_url_request_context.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "content/browser/renderer_host/render_view_host.h"
17 #include "grit/generated_resources.h"
18 #include "net/base/cookie_monster.h"
19 #include "net/url_request/url_request_context.h"
20 #include "ui/base/l10n/l10n_util.h"
21 
22 // Default URL for the sync web interface.
23 //
24 // TODO(idana): when we figure out how we are going to allow third parties to
25 // plug in their own sync engine, we should allow this value to be
26 // configurable.
27 static const char kSyncDefaultViewOnlineUrl[] = "http://docs.google.com";
28 
29 // TODO(idana): the following code was originally copied from
30 // toolbar_importer.h/cc and it needs to be moved to a common Google Accounts
31 // utility.
32 
33 // A simple pair of fields that identify a set of Google cookies, used to
34 // filter from a larger set.
35 struct GoogleCookieFilter {
36   // The generalized, fully qualified URL of pages where
37   // cookies with id |cookie_id| are obtained / accessed.
38   const char* url;
39   // The id of the cookie this filter is selecting,
40   // with name/value delimiter (i.e '=').
41   const char* cookie_id;
42 };
43 
44 // Filters to select Google GAIA cookies.
45 static const GoogleCookieFilter kGAIACookieFilters[] = {
46   { "http://.google.com/",       "SID=" },     // Gmail.
47   // Add filters here for other interesting cookies that should result in
48   // showing the promotions (e.g ASIDAS for dasher accounts).
49 };
50 
IsGoogleGAIACookieInstalled()51 bool IsGoogleGAIACookieInstalled() {
52   for (size_t i = 0; i < arraysize(kGAIACookieFilters); ++i) {
53     // Since we are running on the UI thread don't call GetURLRequestContext().
54     net::CookieStore* store =
55         Profile::GetDefaultRequestContext()->DONTUSEME_GetCookieStore();
56     GURL url(kGAIACookieFilters[i].url);
57     net::CookieOptions options;
58     options.set_include_httponly();  // The SID cookie might be httponly.
59     std::string cookies = store->GetCookiesWithOptions(url, options);
60     std::vector<std::string> cookie_list;
61     base::SplitString(cookies, ';', &cookie_list);
62     for (std::vector<std::string>::iterator current = cookie_list.begin();
63          current != cookie_list.end();
64          ++current) {
65       size_t position =
66           current->find(kGAIACookieFilters[i].cookie_id);
67       if (0 == position)
68         return true;
69     }
70   }
71   return false;
72 }
73 
NewTabPageSyncHandler()74 NewTabPageSyncHandler::NewTabPageSyncHandler() : sync_service_(NULL),
75   waiting_for_initial_page_load_(true) {
76 }
77 
~NewTabPageSyncHandler()78 NewTabPageSyncHandler::~NewTabPageSyncHandler() {
79   if (sync_service_)
80     sync_service_->RemoveObserver(this);
81 }
82 
83 // static
84 NewTabPageSyncHandler::MessageType
FromSyncStatusMessageType(sync_ui_util::MessageType type)85     NewTabPageSyncHandler::FromSyncStatusMessageType(
86         sync_ui_util::MessageType type) {
87   switch (type) {
88     case sync_ui_util::SYNC_ERROR:
89       return SYNC_ERROR;
90     case sync_ui_util::SYNC_PROMO:
91       return SYNC_PROMO;
92     case sync_ui_util::PRE_SYNCED:
93     case sync_ui_util::SYNCED:
94     default:
95       return HIDE;
96   }
97 }
98 
Attach(WebUI * web_ui)99 WebUIMessageHandler* NewTabPageSyncHandler::Attach(WebUI* web_ui) {
100   sync_service_ = web_ui->GetProfile()->GetProfileSyncService();
101   DCHECK(sync_service_);  // This shouldn't get called by an incognito NTP.
102   DCHECK(!sync_service_->IsManaged());  // And neither if sync is managed.
103   sync_service_->AddObserver(this);
104   return WebUIMessageHandler::Attach(web_ui);
105 }
106 
RegisterMessages()107 void NewTabPageSyncHandler::RegisterMessages() {
108   web_ui_->RegisterMessageCallback("GetSyncMessage",
109       NewCallback(this, &NewTabPageSyncHandler::HandleGetSyncMessage));
110   web_ui_->RegisterMessageCallback("SyncLinkClicked",
111       NewCallback(this, &NewTabPageSyncHandler::HandleSyncLinkClicked));
112 }
113 
HandleGetSyncMessage(const ListValue * args)114 void NewTabPageSyncHandler::HandleGetSyncMessage(const ListValue* args) {
115   waiting_for_initial_page_load_ = false;
116   BuildAndSendSyncStatus();
117 }
118 
HideSyncStatusSection()119 void NewTabPageSyncHandler::HideSyncStatusSection() {
120   SendSyncMessageToPage(HIDE, std::string(), std::string());
121 }
122 
BuildAndSendSyncStatus()123 void NewTabPageSyncHandler::BuildAndSendSyncStatus() {
124   DCHECK(!waiting_for_initial_page_load_);
125 
126   // Hide the sync status section if sync is managed or disabled entirely.
127   if (!sync_service_ || sync_service_->IsManaged()) {
128     HideSyncStatusSection();
129     return;
130   }
131 
132   // Don't show sync status if setup is not complete.
133   if (!sync_service_->HasSyncSetupCompleted()) {
134     return;
135   }
136 
137   // Once sync has been enabled, the supported "sync statuses" for the NNTP
138   // from the user's perspective are:
139   //
140   // "Sync error", when we can't authenticate or establish a connection with
141   //               the sync server (appropriate information appended to
142   //               message).
143   string16 status_msg;
144   string16 link_text;
145   sync_ui_util::MessageType type =
146       sync_ui_util::GetStatusLabelsForNewTabPage(sync_service_,
147                                                  &status_msg,
148                                                  &link_text);
149   SendSyncMessageToPage(FromSyncStatusMessageType(type),
150                         UTF16ToUTF8(status_msg), UTF16ToUTF8(link_text));
151 }
152 
HandleSyncLinkClicked(const ListValue * args)153 void NewTabPageSyncHandler::HandleSyncLinkClicked(const ListValue* args) {
154   DCHECK(!waiting_for_initial_page_load_);
155   DCHECK(sync_service_);
156   if (!sync_service_->IsSyncEnabled())
157     return;
158   if (sync_service_->HasSyncSetupCompleted()) {
159     sync_service_->ShowErrorUI(NULL);
160     DictionaryValue value;
161     value.SetString("syncEnabledMessage",
162                     l10n_util::GetStringFUTF16(IDS_SYNC_NTP_SYNCED_TO,
163                         sync_service_->GetAuthenticatedUsername()));
164     web_ui_->CallJavascriptFunction("syncAlreadyEnabled", value);
165   } else {
166     // User clicked the 'Start now' link to begin syncing.
167     ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_NTP);
168     sync_service_->ShowLoginDialog(NULL);
169   }
170 }
171 
OnStateChanged()172 void NewTabPageSyncHandler::OnStateChanged() {
173   // Don't do anything if the page has not yet loaded.
174   if (waiting_for_initial_page_load_)
175     return;
176   BuildAndSendSyncStatus();
177 }
178 
SendSyncMessageToPage(MessageType type,std::string msg,std::string linktext)179 void NewTabPageSyncHandler::SendSyncMessageToPage(
180     MessageType type, std::string msg,
181     std::string linktext) {
182   DictionaryValue value;
183   std::string user;
184   std::string title;
185   std::string linkurl;
186 
187   // If there is nothing to show, we should hide the sync section altogether.
188   if (type == HIDE || (msg.empty() && linktext.empty())) {
189     value.SetBoolean("syncsectionisvisible", false);
190   } else {
191     if (type == SYNC_ERROR)
192       title = l10n_util::GetStringUTF8(IDS_SYNC_NTP_SYNC_SECTION_ERROR_TITLE);
193     else if (type == SYNC_PROMO)
194       title = l10n_util::GetStringUTF8(IDS_SYNC_NTP_SYNC_SECTION_PROMO_TITLE);
195     else
196       NOTREACHED();
197 
198     value.SetBoolean("syncsectionisvisible", true);
199     value.SetString("msg", msg);
200     value.SetString("title", title);
201     if (linktext.empty()) {
202       value.SetBoolean("linkisvisible", false);
203     } else {
204       value.SetBoolean("linkisvisible", true);
205       value.SetString("linktext", linktext);
206 
207       // The only time we set the URL is when the user is synced and we need to
208       // show a link to a web interface (e.g. http://docs.google.com). When we
209       // set that URL, HandleSyncLinkClicked won't be called when the user
210       // clicks on the link.
211       if (linkurl.empty()) {
212         value.SetBoolean("linkurlisset", false);
213       } else {
214         value.SetBoolean("linkurlisset", true);
215         value.SetString("linkurl", linkurl);
216       }
217     }
218   }
219   web_ui_->CallJavascriptFunction("syncMessageChanged", value);
220 }
221