Commit 3ecb2b58 authored by jianli@chromium.org's avatar jianli@chromium.org

Start and stop the GCM service on demand

The GCM service will now be started when there is a consumer. It will be
automatically stopped when all consumers are gone. This does not change
the existing behavior that the GCM is always started for the signed-in
profile since invalidation consumes it.

BUG=356716
TEST=tests updated and new tests added
TBR=kalman@chromium.org

Review URL: https://codereview.chromium.org/296053011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272380 0039d316-1c4b-4281-b951-d872f2087c98
parent f916f7c8
......@@ -20,6 +20,7 @@
#include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/services/gcm/fake_gcm_app_handler.h"
#include "chrome/browser/services/gcm/fake_gcm_client.h"
#include "chrome/browser/services/gcm/fake_gcm_client_factory.h"
#include "chrome/browser/services/gcm/fake_signin_manager.h"
......@@ -381,11 +382,19 @@ TEST_F(ExtensionGCMAppHandlerTest, UnregisterOnExtensionUninstall) {
waiter()->WaitUntilCompleted();
EXPECT_EQ(gcm::GCMClient::SUCCESS, registration_result());
// Add another app handler in order to prevent the GCM service from being
// stopped when the extension is uninstalled. This is needed because otherwise
// we are not able to receive the unregistration result.
GetGCMDriver()->AddAppHandler("Foo", gcm_app_handler());
// Unregistration should be triggered when the extension is uninstalled.
UninstallExtension(extension);
waiter()->WaitUntilCompleted();
EXPECT_EQ(gcm::GCMClient::SUCCESS,
gcm_app_handler()->unregistration_result());
// Clean up.
GetGCMDriver()->RemoveAppHandler("Foo");
}
} // namespace extensions
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/services/gcm/fake_gcm_app_handler.h"
#include "base/run_loop.h"
namespace gcm {
FakeGCMAppHandler::FakeGCMAppHandler() : received_event_(NO_EVENT) {
}
FakeGCMAppHandler::~FakeGCMAppHandler() {
}
void FakeGCMAppHandler::WaitForNotification() {
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
run_loop_.reset();
}
void FakeGCMAppHandler::ShutdownHandler() {
}
void FakeGCMAppHandler::OnMessage(const std::string& app_id,
const GCMClient::IncomingMessage& message) {
ClearResults();
received_event_ = MESSAGE_EVENT;
app_id_ = app_id;
message_ = message;
if (run_loop_)
run_loop_->Quit();
}
void FakeGCMAppHandler::OnMessagesDeleted(const std::string& app_id) {
ClearResults();
received_event_ = MESSAGES_DELETED_EVENT;
app_id_ = app_id;
if (run_loop_)
run_loop_->Quit();
}
void FakeGCMAppHandler::OnSendError(
const std::string& app_id,
const GCMClient::SendErrorDetails& send_error_details) {
ClearResults();
received_event_ = SEND_ERROR_EVENT;
app_id_ = app_id;
send_error_details_ = send_error_details;
if (run_loop_)
run_loop_->Quit();
}
void FakeGCMAppHandler::ClearResults() {
received_event_ = NO_EVENT;
app_id_.clear();
message_ = GCMClient::IncomingMessage();
send_error_details_ = GCMClient::SendErrorDetails();
}
} // namespace gcm
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SERVICES_GCM_FAKE_GCM_APP_HANDLER_H_
#define CHROME_BROWSER_SERVICES_GCM_FAKE_GCM_APP_HANDLER_H_
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "components/gcm_driver/gcm_app_handler.h"
namespace base {
class RunLoop;
}
namespace gcm {
class FakeGCMAppHandler : public GCMAppHandler {
public:
enum Event {
NO_EVENT,
MESSAGE_EVENT,
MESSAGES_DELETED_EVENT,
SEND_ERROR_EVENT
};
FakeGCMAppHandler();
virtual ~FakeGCMAppHandler();
const Event& received_event() const { return received_event_; }
const std::string& app_id() const { return app_id_; }
const GCMClient::IncomingMessage& message() const { return message_; }
const GCMClient::SendErrorDetails& send_error_details() const {
return send_error_details_;
}
void WaitForNotification();
// GCMAppHandler:
virtual void ShutdownHandler() OVERRIDE;
virtual void OnMessage(const std::string& app_id,
const GCMClient::IncomingMessage& message) OVERRIDE;
virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
virtual void OnSendError(
const std::string& app_id,
const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
private:
void ClearResults();
scoped_ptr<base::RunLoop> run_loop_;
Event received_event_;
std::string app_id_;
GCMClient::IncomingMessage message_;
GCMClient::SendErrorDetails send_error_details_;
DISALLOW_COPY_AND_ASSIGN(FakeGCMAppHandler);
};
} // namespace gcm
#endif // CHROME_BROWSER_SERVICES_GCM_FAKE_GCM_APP_HANDLER_H_
......@@ -475,6 +475,10 @@ void GCMDriver::RemoveAppHandler(const std::string& app_id) {
DCHECK(!app_id.empty());
app_handlers_.erase(app_id);
// Stops the GCM service when no app intends to consume it.
if (app_handlers_.empty())
Stop();
}
void GCMDriver::Register(const std::string& app_id,
......@@ -681,6 +685,10 @@ GCMClient::Result GCMDriver::EnsureStarted() {
if (!gcm_enabled_)
return GCMClient::GCM_DISABLED;
// Have any app requested the service?
if (app_handlers_.empty())
return GCMClient::UNKNOWN_ERROR;
// Is the user signed in?
const std::string account_id = identity_provider_->GetActiveAccountId();
if (account_id.empty())
......
......@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "chrome/browser/services/gcm/fake_gcm_app_handler.h"
#include "chrome/browser/services/gcm/fake_gcm_client.h"
#include "chrome/browser/services/gcm/fake_gcm_client_factory.h"
#include "chrome/browser/services/gcm/fake_signin_manager.h"
......@@ -54,6 +55,7 @@ class GCMProfileServiceTest : public testing::Test {
// testing::Test:
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
FakeGCMClient* GetGCMClient() const;
......@@ -83,6 +85,7 @@ class GCMProfileServiceTest : public testing::Test {
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestingProfile> profile_;
GCMProfileService* gcm_profile_service_;
scoped_ptr<FakeGCMAppHandler> gcm_app_handler_;
std::string registration_id_;
GCMClient::Result registration_result_;
......@@ -95,6 +98,7 @@ class GCMProfileServiceTest : public testing::Test {
GCMProfileServiceTest::GCMProfileServiceTest()
: gcm_profile_service_(NULL),
gcm_app_handler_(new FakeGCMAppHandler),
registration_result_(GCMClient::UNKNOWN_ERROR),
send_result_(GCMClient::UNKNOWN_ERROR) {
}
......@@ -117,6 +121,8 @@ void GCMProfileServiceTest::SetUp() {
GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile_.get(),
&BuildGCMProfileService));
gcm_profile_service_->driver()->AddAppHandler(
kTestAppID, gcm_app_handler_.get());
FakeSigninManager* signin_manager = static_cast<FakeSigninManager*>(
SigninManagerFactory::GetInstance()->GetForProfile(profile_.get()));
......@@ -124,6 +130,10 @@ void GCMProfileServiceTest::SetUp() {
base::RunLoop().RunUntilIdle();
}
void GCMProfileServiceTest::TearDown() {
gcm_profile_service_->driver()->RemoveAppHandler(kTestAppID);
}
void GCMProfileServiceTest::RegisterAndWaitForCompletion(
const std::vector<std::string>& sender_ids) {
base::RunLoop run_loop;
......
......@@ -1266,6 +1266,8 @@
'browser/search_engines/template_url_prepopulate_data_unittest.cc',
'browser/search_engines/template_url_scraper_unittest.cc',
'browser/search_engines/template_url_unittest.cc',
'browser/services/gcm/fake_gcm_app_handler.cc',
'browser/services/gcm/fake_gcm_app_handler.h',
'browser/services/gcm/fake_gcm_client_factory.cc',
'browser/services/gcm/fake_gcm_client_factory.h',
'browser/services/gcm/fake_signin_manager.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment