1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/extensions/extension_gcm_app_handler.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <vector>
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/bind.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/bind_helpers.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/command_line.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/files/file_path.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/files/scoped_temp_dir.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/location.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/logging.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/ref_counted.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/message_loop/message_loop.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/path_service.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_service.h"
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/run_loop.h"
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/values.h"
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h"
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/extensions/api/gcm/gcm_api.h"
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/extensions/extension_service.h"
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/test_extension_service.h"
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/test_extension_system.h"
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/profiles/profile.h"
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/services/gcm/fake_signin_manager.h"
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/services/gcm/gcm_profile_service.h"
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/signin/signin_manager_factory.h"
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/common/pref_names.h"
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/test/base/testing_profile.h"
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/fake_gcm_app_handler.h"
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/fake_gcm_client.h"
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/fake_gcm_client_factory.h"
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/gcm_client_factory.h"
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/gcm_driver.h"
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/keyed_service/core/keyed_service.h"
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_context.h"
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/browser_thread.h"
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/test/test_browser_thread_bundle.h"
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/test/test_utils.h"
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/browser/extension_system.h"
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h"
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension.h"
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/manifest.h"
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_constants.h"
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/permissions/api_permission.h"
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_CHROMEOS)
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/chromeos/settings/cros_settings.h"
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/chromeos/settings/device_settings_service.h"
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/dbus/dbus_thread_manager.h"
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace extensions {
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kTestExtensionName[] = "FooBar";
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kTestingUsername[] = "user1@example.com";
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Helper class for asynchronous waiting.
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass Waiter {
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Waiter() {}
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ~Waiter() {}
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Waits until the asynchronous operation finishes.
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void WaitUntilCompleted() {
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    run_loop_.reset(new base::RunLoop);
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    run_loop_->Run();
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Signals that the asynchronous operation finishes.
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void SignalCompleted() {
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (run_loop_ && run_loop_->running())
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      run_loop_->Quit();
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Runs until UI loop becomes idle.
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void PumpUILoop() {
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::MessageLoop::current()->RunUntilIdle();
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Runs until IO loop becomes idle.
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void PumpIOLoop() {
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    content::BrowserThread::PostTask(
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        content::BrowserThread::IO,
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::Bind(&Waiter::OnIOLoopPump, base::Unretained(this)));
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WaitUntilCompleted();
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void PumpIOLoopCompleted() {
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SignalCompleted();
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void OnIOLoopPump() {
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    content::BrowserThread::PostTask(
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        content::BrowserThread::IO,
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::Bind(&Waiter::OnIOLoopPumpCompleted, base::Unretained(this)));
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void OnIOLoopPumpCompleted() {
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    content::BrowserThread::PostTask(
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        content::BrowserThread::UI,
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::Bind(&Waiter::PumpIOLoopCompleted, base::Unretained(this)));
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::RunLoop> run_loop_;
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DISALLOW_COPY_AND_ASSIGN(Waiter);
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler {
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter)
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : ExtensionGCMAppHandler(profile),
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        waiter_(waiter),
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR),
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        app_handler_count_drop_to_zero_(false) {
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual ~FakeExtensionGCMAppHandler() {
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnMessage(
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const std::string& app_id,
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const gcm::GCMClient::IncomingMessage& message) OVERRIDE {
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE {
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnSendError(
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const std::string& app_id,
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE {
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnUnregisterCompleted(const std::string& app_id,
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     gcm::GCMClient::Result result) OVERRIDE {
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    unregistration_result_ = result;
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiter_->SignalCompleted();
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void RemoveAppHandler(const std::string& app_id) OVERRIDE{
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ExtensionGCMAppHandler::RemoveAppHandler(app_id);
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!GetGCMDriver()->app_handlers().size())
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      app_handler_count_drop_to_zero_ = true;
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gcm::GCMClient::Result unregistration_result() const {
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return unregistration_result_;
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool app_handler_count_drop_to_zero() const {
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return app_handler_count_drop_to_zero_;
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Waiter* waiter_;
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gcm::GCMClient::Result unregistration_result_;
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool app_handler_count_drop_to_zero_;
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler);
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass ExtensionGCMAppHandlerTest : public testing::Test {
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static KeyedService* BuildGCMProfileService(
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      content::BrowserContext* context) {
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return new gcm::GCMProfileService(
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Profile::FromBrowserContext(context),
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        scoped_ptr<gcm::GCMClientFactory>(new gcm::FakeGCMClientFactory(
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            gcm::FakeGCMClient::NO_DELAY_START,
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            content::BrowserThread::GetMessageLoopProxyForThread(
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                content::BrowserThread::UI),
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            content::BrowserThread::GetMessageLoopProxyForThread(
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                content::BrowserThread::IO))));
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ExtensionGCMAppHandlerTest()
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : extension_service_(NULL),
2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) {
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual ~ExtensionGCMAppHandlerTest() {
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Overridden from test::Test:
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void SetUp() OVERRIDE {
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Make BrowserThread work in unittest.
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    thread_bundle_.reset(new content::TestBrowserThreadBundle(
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        content::TestBrowserThreadBundle::REAL_IO_THREAD));
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Allow extension update to unpack crx in process.
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    in_process_utility_thread_helper_.reset(
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        new content::InProcessUtilityThreadHelper);
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // This is needed to create extension service under CrOS.
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_CHROMEOS)
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    test_user_manager_.reset(new chromeos::ScopedTestUserManager());
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Creating a DBus thread manager setter has the side effect of
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // creating a DBusThreadManager, which is needed for testing.
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // We don't actually need the setter so we ignore the return value.
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    chromeos::DBusThreadManager::GetSetterForTesting();
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Create a new profile.
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestingProfile::Builder builder;
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              gcm::FakeSigninManager::Build);
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    profile_ = builder.Build();
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    signin_manager_ = static_cast<gcm::FakeSigninManager*>(
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        SigninManagerFactory::GetInstance()->GetForProfile(profile_.get()));
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Create extension service in order to uninstall the extension.
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestExtensionSystem* extension_system(
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile())));
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::FilePath extensions_install_dir =
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        temp_dir_.path().Append(FILE_PATH_LITERAL("Extensions"));
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    extension_system->CreateExtensionService(
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        CommandLine::ForCurrentProcess(), extensions_install_dir, false);
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    extension_service_ = extension_system->Get(profile())->extension_service();
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    extension_service_->set_extensions_enabled(true);
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    extension_service_->set_show_extensions_prompts(false);
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    extension_service_->set_install_updates_when_idle_for_test(false);
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Enable GCM such that tests could be run on all channels.
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Create GCMProfileService that talks with fake GCMClient.
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse(
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        profile(), &ExtensionGCMAppHandlerTest::BuildGCMProfileService);
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Create a fake version of ExtensionGCMAppHandler.
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_));
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void TearDown() OVERRIDE {
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_CHROMEOS)
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    test_user_manager_.reset();
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiter_.PumpUILoop();
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Returns a barebones test extension.
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<Extension> CreateExtension() {
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::DictionaryValue manifest;
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    manifest.SetString(manifest_keys::kVersion, "1.0.0.0");
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    manifest.SetString(manifest_keys::kName, kTestExtensionName);
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::ListValue* permission_list = new base::ListValue;
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    permission_list->Append(new base::StringValue("gcm"));
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    manifest.Set(manifest_keys::kPermissions, permission_list);
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    std::string error;
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    scoped_refptr<Extension> extension = Extension::Create(
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        temp_dir_.path(),
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        Manifest::UNPACKED,
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        manifest,
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        Extension::NO_FLAGS,
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        "ldnnhddmnhbkjipkidpdiheffobcpfmf",
285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        &error);
286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    EXPECT_TRUE(extension.get()) << error;
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EXPECT_TRUE(
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        extension->permissions_data()->HasAPIPermission(APIPermission::kGcm));
289c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
290c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return extension;
291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void LoadExtension(const Extension* extension) {
294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    extension_service_->AddExtension(extension);
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  static bool IsCrxInstallerDone(extensions::CrxInstaller** installer,
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 const content::NotificationSource& source,
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 const content::NotificationDetails& details) {
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return content::Source<extensions::CrxInstaller>(source).ptr() ==
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           *installer;
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void UpdateExtension(const Extension* extension,
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       const std::string& update_crx) {
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::FilePath data_dir;
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!PathService::Get(chrome::DIR_TEST_DATA, &data_dir)) {
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ADD_FAILURE();
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    data_dir = data_dir.AppendASCII("extensions");
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    data_dir = data_dir.AppendASCII(update_crx);
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::FilePath path = temp_dir_.path();
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    path = path.Append(data_dir.BaseName());
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ASSERT_TRUE(base::CopyFile(data_dir, path));
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    extensions::CrxInstaller* installer = NULL;
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    content::WindowedNotificationObserver observer(
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extensions::NOTIFICATION_CRX_INSTALLER_DONE,
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        base::Bind(&IsCrxInstallerDone, &installer));
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    extension_service_->UpdateExtension(
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        extension->id(), path, true, &installer);
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (installer)
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      observer.Wait();
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
329c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void DisableExtension(const Extension* extension) {
330c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    extension_service_->DisableExtension(
331c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        extension->id(), Extension::DISABLE_USER_ACTION);
332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
334c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void EnableExtension(const Extension* extension) {
335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    extension_service_->EnableExtension(extension->id());
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void UninstallExtension(const Extension* extension) {
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    extension_service_->UninstallExtension(
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extension->id(),
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extensions::UNINSTALL_REASON_FOR_TESTING,
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&base::DoNothing),
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NULL);
344c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
345c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
346c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void SignIn(const std::string& username) {
347c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    signin_manager_->SignIn(username);
348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiter_.PumpIOLoop();
349c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
351c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void SignOut() {
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    signin_manager_->SignOut(signin_metrics::SIGNOUT_TEST);
353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiter_.PumpIOLoop();
354c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
356c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void Register(const std::string& app_id,
357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                const std::vector<std::string>& sender_ids) {
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GetGCMDriver()->Register(
359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        app_id,
360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        sender_ids,
361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        base::Bind(&ExtensionGCMAppHandlerTest::RegisterCompleted,
362c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   base::Unretained(this)));
363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void RegisterCompleted(const std::string& registration_id,
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         gcm::GCMClient::Result result) {
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    registration_result_ = result;
368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    waiter_.SignalCompleted();
369c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
370c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gcm::GCMDriver* GetGCMDriver() const {
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return gcm::GCMProfileServiceFactory::GetForProfile(profile())->driver();
373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool HasAppHandlers(const std::string& app_id) const {
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return GetGCMDriver()->app_handlers().count(app_id);
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Profile* profile() const { return profile_.get(); }
380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Waiter* waiter() { return &waiter_; }
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FakeExtensionGCMAppHandler* gcm_app_handler() const {
382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return gcm_app_handler_.get();
383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gcm::GCMClient::Result registration_result() const {
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return registration_result_;
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gcm::GCMClient::Result unregistration_result() const {
388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return unregistration_result_;
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<content::InProcessUtilityThreadHelper>
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      in_process_utility_thread_helper_;
395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<TestingProfile> profile_;
396c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ExtensionService* extension_service_;  // Not owned.
397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gcm::FakeSigninManager* signin_manager_;  // Not owned.
398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::ScopedTempDir temp_dir_;
399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // This is needed to create extension service under CrOS.
401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_CHROMEOS)
402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  chromeos::ScopedTestCrosSettings test_cros_settings_;
404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Waiter waiter_;
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_;
4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gcm::GCMClient::Result registration_result_;
4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gcm::GCMClient::Result unregistration_result_;
411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ExtensionGCMAppHandlerTest);
413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
414c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
415c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(ExtensionGCMAppHandlerTest, AddAndRemoveAppHandler) {
416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<Extension> extension(CreateExtension());
417c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
418c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // App handler is added when extension is loaded.
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LoadExtension(extension.get());
420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  waiter()->PumpUILoop();
421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_TRUE(HasAppHandlers(extension->id()));
422c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // App handler is removed when extension is unloaded.
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DisableExtension(extension.get());
425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  waiter()->PumpUILoop();
426c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(HasAppHandlers(extension->id()));
427c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
428c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // App handler is added when extension is reloaded.
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EnableExtension(extension.get());
430c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  waiter()->PumpUILoop();
431c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_TRUE(HasAppHandlers(extension->id()));
432c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
433c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // App handler is removed when extension is uninstalled.
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UninstallExtension(extension.get());
435c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  waiter()->PumpUILoop();
436c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(HasAppHandlers(extension->id()));
437c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(ExtensionGCMAppHandlerTest, UnregisterOnExtensionUninstall) {
440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<Extension> extension(CreateExtension());
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LoadExtension(extension.get());
442c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Sign-in is needed for registration.
444c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SignIn(kTestingUsername);
445c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
446c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Kick off registration.
447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::vector<std::string> sender_ids;
448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  sender_ids.push_back("sender1");
449c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Register(extension->id(), sender_ids);
450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  waiter()->WaitUntilCompleted();
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(gcm::GCMClient::SUCCESS, registration_result());
452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Add another app handler in order to prevent the GCM service from being
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // stopped when the extension is uninstalled. This is needed because otherwise
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we are not able to receive the unregistration result.
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetGCMDriver()->AddAppHandler("Foo", gcm_app_handler());
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Unregistration should be triggered when the extension is uninstalled.
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UninstallExtension(extension.get());
460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  waiter()->WaitUntilCompleted();
4615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(gcm::GCMClient::SUCCESS,
4625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            gcm_app_handler()->unregistration_result());
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Clean up.
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetGCMDriver()->RemoveAppHandler("Foo");
466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(ExtensionGCMAppHandlerTest, UpdateExtensionWithGcmPermissionKept) {
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension());
470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // App handler is added when the extension is loaded.
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LoadExtension(extension.get());
473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  waiter()->PumpUILoop();
474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(HasAppHandlers(extension->id()));
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // App handler count should not drop to zero when the extension is updated.
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UpdateExtension(extension.get(), "gcm2.crx");
478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  waiter()->PumpUILoop();
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(gcm_app_handler()->app_handler_count_drop_to_zero());
480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(HasAppHandlers(extension->id()));
481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(ExtensionGCMAppHandlerTest, UpdateExtensionWithGcmPermissionRemoved) {
484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension());
485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // App handler is added when the extension is loaded.
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LoadExtension(extension.get());
488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  waiter()->PumpUILoop();
489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(HasAppHandlers(extension->id()));
490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // App handler is removed when the extension is updated to the version that
492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // has GCM permission removed.
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UpdateExtension(extension.get(), "good2.crx");
494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  waiter()->PumpUILoop();
495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(gcm_app_handler()->app_handler_count_drop_to_zero());
496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(HasAppHandlers(extension->id()));
497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace extensions
500