172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/new_tab_page_sync_handler.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <vector>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/chrome_url_request_context.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/cookie_monster.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Default URL for the sync web interface.
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(idana): when we figure out how we are going to allow third parties to
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// plug in their own sync engine, we should allow this value to be
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// configurable.
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kSyncDefaultViewOnlineUrl[] = "http://docs.google.com";
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(idana): the following code was originally copied from
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// toolbar_importer.h/cc and it needs to be moved to a common Google Accounts
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// utility.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A simple pair of fields that identify a set of Google cookies, used to
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// filter from a larger set.
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct GoogleCookieFilter {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The generalized, fully qualified URL of pages where
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // cookies with id |cookie_id| are obtained / accessed.
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* url;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The id of the cookie this filter is selecting,
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // with name/value delimiter (i.e '=').
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* cookie_id;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Filters to select Google GAIA cookies.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const GoogleCookieFilter kGAIACookieFilters[] = {
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { "http://.google.com/",       "SID=" },     // Gmail.
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add filters here for other interesting cookies that should result in
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // showing the promotions (e.g ASIDAS for dasher accounts).
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsGoogleGAIACookieInstalled() {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < arraysize(kGAIACookieFilters); ++i) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Since we are running on the UI thread don't call GetURLRequestContext().
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::CookieStore* store =
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        Profile::GetDefaultRequestContext()->DONTUSEME_GetCookieStore();
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url(kGAIACookieFilters[i].url);
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::CookieOptions options;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    options.set_include_httponly();  // The SID cookie might be httponly.
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string cookies = store->GetCookiesWithOptions(url, options);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<std::string> cookie_list;
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    base::SplitString(cookies, ';', &cookie_list);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::vector<std::string>::iterator current = cookie_list.begin();
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         current != cookie_list.end();
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         ++current) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_t position =
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          current->find(kGAIACookieFilters[i].cookie_id);
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (0 == position)
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return true;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNewTabPageSyncHandler::NewTabPageSyncHandler() : sync_service_(NULL),
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  waiting_for_initial_page_load_(true) {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNewTabPageSyncHandler::~NewTabPageSyncHandler() {
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_service_)
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sync_service_->RemoveObserver(this);
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNewTabPageSyncHandler::MessageType
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NewTabPageSyncHandler::FromSyncStatusMessageType(
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        sync_ui_util::MessageType type) {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case sync_ui_util::SYNC_ERROR:
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return SYNC_ERROR;
903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    case sync_ui_util::SYNC_PROMO:
913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      return SYNC_PROMO;
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case sync_ui_util::PRE_SYNCED:
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case sync_ui_util::SYNCED:
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return HIDE;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenWebUIMessageHandler* NewTabPageSyncHandler::Attach(WebUI* web_ui) {
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_service_ = web_ui->GetProfile()->GetProfileSyncService();
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(sync_service_);  // This shouldn't get called by an incognito NTP.
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!sync_service_->IsManaged());  // And neither if sync is managed.
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sync_service_->AddObserver(this);
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return WebUIMessageHandler::Attach(web_ui);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NewTabPageSyncHandler::RegisterMessages() {
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("GetSyncMessage",
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &NewTabPageSyncHandler::HandleGetSyncMessage));
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("SyncLinkClicked",
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &NewTabPageSyncHandler::HandleSyncLinkClicked));
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid NewTabPageSyncHandler::HandleGetSyncMessage(const ListValue* args) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  waiting_for_initial_page_load_ = false;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BuildAndSendSyncStatus();
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NewTabPageSyncHandler::HideSyncStatusSection() {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendSyncMessageToPage(HIDE, std::string(), std::string());
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NewTabPageSyncHandler::BuildAndSendSyncStatus() {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_for_initial_page_load_);
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Hide the sync status section if sync is managed or disabled entirely.
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!sync_service_ || sync_service_->IsManaged()) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HideSyncStatusSection();
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't show sync status if setup is not complete.
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!sync_service_->HasSyncSetupCompleted()) {
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Once sync has been enabled, the supported "sync statuses" for the NNTP
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // from the user's perspective are:
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // "Sync error", when we can't authenticate or establish a connection with
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //               the sync server (appropriate information appended to
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //               message).
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 status_msg;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 link_text;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sync_ui_util::MessageType type =
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      sync_ui_util::GetStatusLabelsForNewTabPage(sync_service_,
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                 &status_msg,
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                 &link_text);
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendSyncMessageToPage(FromSyncStatusMessageType(type),
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        UTF16ToUTF8(status_msg), UTF16ToUTF8(link_text));
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid NewTabPageSyncHandler::HandleSyncLinkClicked(const ListValue* args) {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_for_initial_page_load_);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(sync_service_);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!sync_service_->IsSyncEnabled())
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_service_->HasSyncSetupCompleted()) {
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sync_service_->ShowErrorUI(NULL);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue value;
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    value.SetString("syncEnabledMessage",
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    l10n_util::GetStringFUTF16(IDS_SYNC_NTP_SYNCED_TO,
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        sync_service_->GetAuthenticatedUsername()));
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    web_ui_->CallJavascriptFunction("syncAlreadyEnabled", value);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // User clicked the 'Start now' link to begin syncing.
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_NTP);
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    sync_service_->ShowLoginDialog(NULL);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NewTabPageSyncHandler::OnStateChanged() {
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't do anything if the page has not yet loaded.
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (waiting_for_initial_page_load_)
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BuildAndSendSyncStatus();
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NewTabPageSyncHandler::SendSyncMessageToPage(
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageType type, std::string msg,
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string linktext) {
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue value;
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string user;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string title;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string linkurl;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // If there is nothing to show, we should hide the sync section altogether.
1883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (type == HIDE || (msg.empty() && linktext.empty())) {
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    value.SetBoolean("syncsectionisvisible", false);
1903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  } else {
1913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    if (type == SYNC_ERROR)
1923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      title = l10n_util::GetStringUTF8(IDS_SYNC_NTP_SYNC_SECTION_ERROR_TITLE);
1933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    else if (type == SYNC_PROMO)
1943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      title = l10n_util::GetStringUTF8(IDS_SYNC_NTP_SYNC_SECTION_PROMO_TITLE);
1953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    else
1963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      NOTREACHED();
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    value.SetBoolean("syncsectionisvisible", true);
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    value.SetString("msg", msg);
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    value.SetString("title", title);
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (linktext.empty()) {
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      value.SetBoolean("linkisvisible", false);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      value.SetBoolean("linkisvisible", true);
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      value.SetString("linktext", linktext);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The only time we set the URL is when the user is synced and we need to
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // show a link to a web interface (e.g. http://docs.google.com). When we
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // set that URL, HandleSyncLinkClicked won't be called when the user
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // clicks on the link.
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (linkurl.empty()) {
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        value.SetBoolean("linkurlisset", false);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        value.SetBoolean("linkurlisset", true);
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        value.SetString("linkurl", linkurl);
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction("syncMessageChanged", value);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
221