push_messaging_api.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/push_messaging_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_number_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/event_names.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/event_router.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/token_service.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/push_messaging.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_set.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/permissions/api_permission.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChannelIdSeparator[] = "/";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserNotSignedIn[] = "The user is not signed in.";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTokenServiceNotAvailable[] = "Failed to get token service.";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace glue = api::push_messaging;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingEventRouter::PushMessagingEventRouter(Profile* profile)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This may be NULL; for example, for the ChromeOS guest user. In these cases,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just return without setting up anything, since it won't work anyway.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pss)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExtensionSet* extensions =
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionSystem::Get(profile_)->extension_service()->extensions();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> push_messaging_extensions;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionSet::const_iterator it = extensions->begin();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != extensions->end(); ++it) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension = *it;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension->HasAPIPermission(APIPermission::kPushMessaging)) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      push_messaging_extensions.insert(extension->id());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset(new PushMessagingInvalidationHandler(
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pss, this, push_messaging_extensions));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for extension load/unload as well, so we can update any
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // registrations as appropriate.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<Profile>(profile_->GetOriginalProfile()));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<Profile>(profile_->GetOriginalProfile()));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingEventRouter::~PushMessagingEventRouter() {}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::Shutdown() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need an explicit Shutdown() due to the dependencies among the various
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProfileKeyedServices. ProfileSyncService depends on ExtensionSystem, so
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it is destroyed before us in the destruction phase of Profile shutdown.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As a result, we need to drop any references to it in the Shutdown() phase
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::SetMapperForTest(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PushMessagingInvalidationMapper> mapper) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_ = mapper.Pass();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::TriggerMessageForTest(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int subchannel,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& payload) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnMessage(extension_id, subchannel, payload);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::OnMessage(const std::string& extension_id,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int subchannel,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& payload) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glue::Message message;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message.subchannel_id = subchannel;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message.payload = payload;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> args(glue::OnMessage::Create(message));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_id,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_names::kOnPushMessage,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args.Pass(),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::Observe(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_LOADED: {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension = content::Details<Extension>(details).ptr();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension->HasAPIPermission(APIPermission::kPushMessaging)) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handler_->RegisterExtension(extension->id());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension =
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<UnloadedExtensionInfo>(details)->extension;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension->HasAPIPermission(APIPermission::kPushMessaging)) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handler_->UnregisterExtension(extension->id());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetChannelId class functions
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingGetChannelIdFunction::PushMessagingGetChannelIdFunction()
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : interactive_(false) {}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingGetChannelIdFunction::~PushMessagingGetChannelIdFunction() {}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PushMessagingGetChannelIdFunction::RunImpl() {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fetch the function arguments.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<glue::GetChannelId::Params> params(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glue::GetChannelId::Params::Create(*args_));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params && params->interactive) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    interactive_ = *params->interactive;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balanced in ReportResult()
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsUserLoggedIn()) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (interactive_) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoginUIService* login_ui_service =
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LoginUIServiceFactory::GetForProfile(profile());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      login_ui_service->AddObserver(this);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // OnLoginUICLosed will be called when UI is closed.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      login_ui_service->ShowLoginPopup();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = kUserNotSignedIn;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportResult(std::string(), error_);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartGaiaIdFetch();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PushMessagingGetChannelIdFunction::StartGaiaIdFetch() {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the async fetch of the GAIA ID.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestContextGetter* context = profile()->GetRequestContext();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!token_service) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportResult(std::string(), std::string(kTokenServiceNotAvailable));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& refresh_token =
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token_service->GetOAuth2LoginRefreshToken();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher_.reset(new ObfuscatedGaiaIdFetcher(context, this, refresh_token));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the cache, if we already have a gaia ID, use it instead of
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fetching the ID over the network.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& gaia_id =
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token_service->GetTokenForService(GaiaConstants::kObfuscatedGaiaId);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gaia_id.empty()) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportResult(gaia_id, std::string());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher_->Start();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Will finish asynchronously.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check if the user is logged in.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PushMessagingGetChannelIdFunction::IsUserLoggedIn() const {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!token_service)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return token_service->HasOAuthLoginToken();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnLoginUIShown(
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoginUIService::LoginUI* ui) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing when login ui is shown.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the login succeeds, continue with our logic to fetch the ChannelId.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnLoginUIClosed(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoginUIService::LoginUI* ui) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoginUIService* login_ui_service =
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoginUIServiceFactory::GetForProfile(profile());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  login_ui_service->RemoveObserver(this);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!StartGaiaIdFetch()) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendResponse(false);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::ReportResult(
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& gaia_id, const std::string& error_string) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unpack the status and GaiaId parameters, and use it to build the
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel ID here.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id(gaia_id);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildAndSendResult(gaia_id, error_string);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cache the obfuscated ID locally. It never changes for this user,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and if we call the web API too often, we get errors due to rate limiting.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gaia_id.empty()) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (token_service) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token_service->AddAuthTokenManually(GaiaConstants::kObfuscatedGaiaId,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          gaia_id);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balanced in RunImpl.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::BuildAndSendResult(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& gaia_id, const std::string& error_message) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gaia_id.empty()) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id = gaia_id;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id += kChannelIdSeparator;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id += extension_id();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(petewil): It may be a good idea to further
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // obfuscate the channel ID to prevent the user's obfuscated GAIA ID
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from being readily obtained.  Security review will tell us if we need to.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a ChannelId results object and set the fields.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glue::ChannelIdResult result;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.channel_id = channel_id;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetError(error_message);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = glue::GetChannelId::Results::Create(result);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = error_message.empty() && !gaia_id.empty();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(success);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchSuccess(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& gaia_id) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportResult(gaia_id, std::string());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchFailure(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GoogleServiceAuthError& error) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error_text = error.error_message();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the error message is blank, see if we can set it from the state.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_text.empty() &&
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (0 != error.state())) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_text = base::IntToString(error.state());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportResult(std::string(), error_text);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
294