summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd3
-rw-r--r--chrome/browser/extensions/api/identity/identity_api.cc17
-rw-r--r--chrome/browser/extensions/api/identity/identity_api.h2
-rw-r--r--chrome/browser/extensions/api/identity/identity_event_router.cc73
-rw-r--r--chrome/browser/extensions/api/identity/identity_event_router.h35
-rw-r--r--chrome/browser/extensions/api/identity/identity_event_router_unittest.cc291
-rw-r--r--chrome/chrome_browser_extensions.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/common/extensions/api/_api_features.json5
-rw-r--r--chrome/common/extensions/api/_permission_features.json4
-rw-r--r--chrome/common/extensions/api/identity.idl13
-rw-r--r--chrome/common/extensions/permissions/chrome_api_permissions.cc4
-rw-r--r--extensions/common/permissions/api_permission.h1
-rw-r--r--extensions/common/permissions/permission_message.h1
14 files changed, 447 insertions, 5 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 1c01d52..0a766ff 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4263,6 +4263,9 @@ Make sure you do not expose any sensitive information.
<message name="IDS_EXTENSION_PROMPT_WARNING_DOWNLOADS_OPEN" desc="Permission string for access to downloads.">
Open downloaded files
</message>
+ <message name="IDS_EXTENSION_PROMPT_WARNING_IDENTITY_EMAIL" desc="Permission string for access to profile email address.">
+ View email addresses signed in to your profile
+ </message>
<message name="IDS_EXTENSION_PROMPT_WARNING_WALLPAPER" desc="Permission string for access to wallpaper.">
Change your wallpaper
</message>
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index f60da81..491b65e 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -655,14 +655,20 @@ const base::Time& IdentityTokenCacheValue::expiration_time() const {
IdentityAPI::IdentityAPI(Profile* profile)
: profile_(profile),
- error_(GoogleServiceAuthError::NONE) {
- SigninGlobalError::GetForProfile(profile_)->AddProvider(this);
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->AddObserver(this);
+ error_(GoogleServiceAuthError::NONE),
+ initialized_(false) {
}
IdentityAPI::~IdentityAPI() {
}
+void IdentityAPI::Initialize() {
+ SigninGlobalError::GetForProfile(profile_)->AddProvider(this);
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->AddObserver(this);
+
+ initialized_ = true;
+}
+
IdentityMintRequestQueue* IdentityAPI::mint_queue() {
return &mint_queue_;
}
@@ -714,9 +720,14 @@ void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
}
void IdentityAPI::Shutdown() {
+ if (!initialized_)
+ return;
+
SigninGlobalError::GetForProfile(profile_)->RemoveProvider(this);
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
RemoveObserver(this);
+
+ initialized_ = false;
}
static base::LazyInstance<ProfileKeyedAPIFactory<IdentityAPI> >
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h
index 5b790e1..e37c603 100644
--- a/chrome/browser/extensions/api/identity/identity_api.h
+++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -255,6 +255,7 @@ class IdentityAPI : public ProfileKeyedAPI,
explicit IdentityAPI(Profile* profile);
virtual ~IdentityAPI();
+ void Initialize();
// Request serialization queue for getAuthToken.
IdentityMintRequestQueue* mint_queue();
@@ -295,6 +296,7 @@ class IdentityAPI : public ProfileKeyedAPI,
Profile* profile_;
GoogleServiceAuthError error_;
+ bool initialized_;
IdentityMintRequestQueue mint_queue_;
CachedTokens token_cache_;
};
diff --git a/chrome/browser/extensions/api/identity/identity_event_router.cc b/chrome/browser/extensions/api/identity/identity_event_router.cc
new file mode 100644
index 0000000..06a9ac8
--- /dev/null
+++ b/chrome/browser/extensions/api/identity/identity_event_router.cc
@@ -0,0 +1,73 @@
+// Copyright 2013 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/extensions/api/identity/identity_event_router.h"
+
+#include <set>
+
+#include "base/stl_util.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/event_router.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/common/extensions/api/identity.h"
+
+namespace extensions {
+
+IdentityEventRouter::IdentityEventRouter(Profile* profile)
+ : profile_(profile) {}
+
+IdentityEventRouter::~IdentityEventRouter() {}
+
+void IdentityEventRouter::DispatchSignInEvent(const std::string& id,
+ const std::string& email,
+ bool is_signed_in) {
+ const EventListenerMap::ListenerList& listeners =
+ extensions::ExtensionSystem::Get(profile_)->event_router()->listeners()
+ .GetEventListenersByName(api::identity::OnSignInChanged::kEventName);
+
+ ExtensionService* service =
+ ExtensionSystem::Get(profile_)->extension_service();
+ EventRouter* event_router = ExtensionSystem::Get(profile_)->event_router();
+
+ api::identity::AccountInfo account_info;
+ account_info.id = id;
+
+ api::identity::AccountInfo account_info_email;
+ account_info_email.id = id;
+ account_info_email.email = scoped_ptr<std::string>(new std::string(email));
+
+ std::set<std::string> already_dispatched;
+
+ for (EventListenerMap::ListenerList::const_iterator it = listeners.begin();
+ it != listeners.end();
+ ++it) {
+
+ const std::string extension_id = (*it)->extension_id;
+ const Extension* extension = service->extensions()->GetByID(extension_id);
+
+ if (ContainsKey(already_dispatched, extension_id))
+ continue;
+
+ already_dispatched.insert(extension_id);
+
+ // Add the email address to AccountInfo only for extensions that
+ // have APIPermission::kIdentityEmail.
+ scoped_ptr<base::ListValue> args;
+ if (extension->HasAPIPermission(APIPermission::kIdentityEmail)) {
+ args = api::identity::OnSignInChanged::Create(account_info_email,
+ is_signed_in);
+ } else {
+ args = api::identity::OnSignInChanged::Create(account_info,
+ is_signed_in);
+ }
+
+ scoped_ptr<Event> event(
+ new Event(api::identity::OnSignInChanged::kEventName, args.Pass()));
+ event->restrict_to_profile = profile_;
+ event_router->DispatchEventToExtension(extension_id, event.Pass());
+ }
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/identity_event_router.h b/chrome/browser/extensions/api/identity/identity_event_router.h
new file mode 100644
index 0000000..21bf2eb
--- /dev/null
+++ b/chrome/browser/extensions/api/identity/identity_event_router.h
@@ -0,0 +1,35 @@
+// Copyright 2013 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_EXTENSIONS_API_IDENTITY_IDENTITY_EVENT_ROUTER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_EVENT_ROUTER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+class Profile;
+
+namespace extensions {
+
+class IdentityEventRouter {
+ public:
+ explicit IdentityEventRouter(Profile* profile);
+ ~IdentityEventRouter();
+
+ // Dispatch identity.onSignInChanged event, including email address
+ // for extensions with the identity.email permission.
+ void DispatchSignInEvent(const std::string& id,
+ const std::string& email,
+ bool is_signed_in);
+
+ private:
+ Profile* profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdentityEventRouter);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_EVENT_ROUTER_H_
diff --git a/chrome/browser/extensions/api/identity/identity_event_router_unittest.cc b/chrome/browser/extensions/api/identity/identity_event_router_unittest.cc
new file mode 100644
index 0000000..8b65c5c
--- /dev/null
+++ b/chrome/browser/extensions/api/identity/identity_event_router_unittest.cc
@@ -0,0 +1,291 @@
+// Copyright 2013 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/extensions/api/identity/identity_event_router.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/event_router.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_system_factory.h"
+#include "chrome/browser/extensions/test_extension_service.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/extensions/api/identity.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_builder.h"
+#include "chrome/common/extensions/extension_set.h"
+#include "chrome/common/extensions/permissions/permissions_data.h"
+#include "chrome/common/extensions/value_builder.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+struct EventInfo {
+ std::string user_id;
+ std::string email;
+ bool is_signed_in;
+};
+
+class FakeEventRouter : public extensions::EventRouter {
+ public:
+ explicit FakeEventRouter(Profile* profile) : EventRouter(profile, NULL) {}
+
+ virtual void DispatchEventToExtension(
+ const std::string& extension_id,
+ scoped_ptr<extensions::Event> event) OVERRIDE {
+ EventInfo event_info;
+ base::DictionaryValue* event_object = NULL;
+ EXPECT_TRUE(event->event_args->GetDictionary(0, &event_object));
+ EXPECT_TRUE(event_object->GetString("id", &event_info.user_id));
+ event_object->GetString("email", &event_info.email);
+
+ EXPECT_TRUE(event->event_args->GetBoolean(1, &event_info.is_signed_in));
+
+ EXPECT_FALSE(ContainsKey(extension_id_to_event_, extension_id));
+ extension_id_to_event_[extension_id] = event_info;
+ }
+
+ size_t GetEventCount() {
+ return extension_id_to_event_.size();
+ }
+
+ bool ContainsExtensionId(const std::string extension_id) {
+ return ContainsKey(extension_id_to_event_, extension_id);
+ }
+
+ const EventInfo& GetEventInfo(const std::string extension_id) {
+ return extension_id_to_event_[extension_id];
+ }
+
+ private:
+ std::map<std::string, EventInfo> extension_id_to_event_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeEventRouter);
+};
+
+class FakeExtensionService : public TestExtensionService {
+ public:
+ FakeExtensionService() {}
+ virtual ~FakeExtensionService() {}
+
+ virtual const ExtensionSet* extensions() const OVERRIDE {
+ return &extensions_;
+ }
+
+ virtual void AddExtension(const extensions::Extension* extension) OVERRIDE {
+ extensions_.Insert(extension);
+ }
+
+ private:
+ ExtensionSet extensions_;
+};
+
+class FakeExtensionSystem : public extensions::TestExtensionSystem {
+ public:
+ explicit FakeExtensionSystem(Profile* profile)
+ : extensions::TestExtensionSystem(profile) {}
+
+ virtual extensions::EventRouter* event_router() OVERRIDE {
+ return fake_event_router();
+ }
+
+ virtual ExtensionService* extension_service() OVERRIDE {
+ ExtensionServiceInterface* as_interface =
+ static_cast<ExtensionServiceInterface*>(&fake_extension_service_);
+ return static_cast<ExtensionService*>(as_interface);
+ }
+
+ FakeEventRouter* fake_event_router() {
+ if (!fake_event_router_)
+ fake_event_router_.reset(new FakeEventRouter(profile_));
+ return fake_event_router_.get();
+ }
+
+ private:
+ FakeExtensionService fake_extension_service_;
+ scoped_ptr<FakeEventRouter> fake_event_router_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeExtensionSystem);
+};
+
+BrowserContextKeyedService* BuildFakeExtensionSystem(
+ content::BrowserContext* profile) {
+ return new FakeExtensionSystem(static_cast<Profile*>(profile));
+}
+
+} // namespace
+
+namespace extensions {
+
+class IdentityEventRouterTest : public testing::Test {
+ public:
+ IdentityEventRouterTest()
+ : test_profile_(new TestingProfile()),
+ identity_event_router_(test_profile_.get()),
+ extension_counter_(0) {}
+
+ virtual void SetUp() OVERRIDE {
+ fake_extension_system_ = static_cast<FakeExtensionSystem*>(
+ ExtensionSystemFactory::GetInstance()->SetTestingFactoryAndUse(
+ test_profile_.get(), &BuildFakeExtensionSystem));
+ }
+
+ FakeEventRouter* fake_event_router() {
+ return fake_extension_system_->fake_event_router();
+ }
+
+ Profile* profile() {
+ return test_profile_.get();
+ }
+
+ protected:
+ scoped_refptr<const Extension> CreateExtension(bool has_email_permission) {
+ ListBuilder permissions;
+ if (has_email_permission)
+ permissions.Append("identity.email");
+
+ std::string id = base::StringPrintf("id.%d", extension_counter_++);
+ scoped_refptr<const Extension> extension = ExtensionBuilder()
+ .SetID(id)
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "Extension with ID " + id)
+ .Set("version", "1.0")
+ .Set("manifest_version", 2)
+ .Set("permissions", permissions))
+ .Build();
+ fake_extension_system_->extension_service()->AddExtension(extension.get());
+ fake_event_router()->AddEventListener(
+ api::identity::OnSignInChanged::kEventName, NULL, extension->id());
+ return extension;
+ }
+
+ scoped_ptr<TestingProfile> test_profile_;
+ IdentityEventRouter identity_event_router_;
+ FakeExtensionSystem* fake_extension_system_;
+ content::TestBrowserThreadBundle thread_bundle_;
+ int extension_counter_;
+};
+
+TEST_F(IdentityEventRouterTest, SignInNoListeners) {
+ identity_event_router_.DispatchSignInEvent(
+ "test_user_id", "test_email", true);
+ EXPECT_EQ(0ul, fake_event_router()->GetEventCount());
+}
+
+TEST_F(IdentityEventRouterTest, SignInNoEmailListener) {
+ scoped_refptr<const Extension> ext = CreateExtension(false);
+ identity_event_router_.DispatchSignInEvent(
+ "test_user_id", "test_email", true);
+ EXPECT_EQ(1ul, fake_event_router()->GetEventCount());
+ EXPECT_TRUE(fake_event_router()->ContainsExtensionId(ext->id()));
+ EXPECT_EQ("test_user_id",
+ fake_event_router()->GetEventInfo(ext->id()).user_id);
+ EXPECT_TRUE(fake_event_router()->GetEventInfo(ext->id()).email.empty());
+ EXPECT_TRUE(fake_event_router()->GetEventInfo(ext->id()).is_signed_in);
+}
+
+TEST_F(IdentityEventRouterTest, SignInWithEmailListener) {
+ scoped_refptr<const Extension> ext = CreateExtension(true);
+ identity_event_router_.DispatchSignInEvent(
+ "test_user_id", "test_email", true);
+ EXPECT_EQ(1ul, fake_event_router()->GetEventCount());
+ EXPECT_TRUE(fake_event_router()->ContainsExtensionId(ext->id()));
+ EXPECT_EQ("test_user_id",
+ fake_event_router()->GetEventInfo(ext->id()).user_id);
+ EXPECT_EQ("test_email", fake_event_router()->GetEventInfo(ext->id()).email);
+ EXPECT_TRUE(fake_event_router()->GetEventInfo(ext->id()).is_signed_in);
+}
+
+TEST_F(IdentityEventRouterTest, SignInMultipleListeners) {
+ typedef std::vector<scoped_refptr<const Extension> > ExtensionVector;
+ ExtensionVector with_email;
+ ExtensionVector no_email;
+
+ for (int i = 0; i < 3; i++)
+ with_email.push_back(CreateExtension(true));
+
+ for (int i = 0; i < 2; i++)
+ no_email.push_back(CreateExtension(false));
+
+ identity_event_router_.DispatchSignInEvent(
+ "test_user_id", "test_email", true);
+
+ EXPECT_EQ(with_email.size() + no_email.size(),
+ fake_event_router()->GetEventCount());
+
+ for (ExtensionVector::const_iterator it = with_email.begin();
+ it != with_email.end();
+ ++it) {
+ EXPECT_TRUE(fake_event_router()->ContainsExtensionId((*it)->id()));
+ EXPECT_EQ("test_user_id",
+ fake_event_router()->GetEventInfo((*it)->id()).user_id);
+ EXPECT_EQ("test_email",
+ fake_event_router()->GetEventInfo((*it)->id()).email);
+ EXPECT_TRUE(fake_event_router()->GetEventInfo((*it)->id()).is_signed_in);
+ }
+
+ for (ExtensionVector::const_iterator it = no_email.begin();
+ it != no_email.end();
+ ++it) {
+ EXPECT_TRUE(fake_event_router()->ContainsExtensionId((*it)->id()));
+ EXPECT_EQ("test_user_id",
+ fake_event_router()->GetEventInfo((*it)->id()).user_id);
+ EXPECT_TRUE(fake_event_router()->GetEventInfo((*it)->id()).email.empty());
+ EXPECT_TRUE(fake_event_router()->GetEventInfo((*it)->id()).is_signed_in);
+ }
+}
+
+TEST_F(IdentityEventRouterTest, SignInWithTwoListenersOnOneExtension) {
+ scoped_refptr<const Extension> ext = CreateExtension(true);
+
+ scoped_ptr<content::MockRenderProcessHost> fake_render_process(
+ new content::MockRenderProcessHost(profile()));
+ fake_event_router()->AddEventListener(
+ api::identity::OnSignInChanged::kEventName,
+ fake_render_process.get(),
+ ext->id());
+
+ identity_event_router_.DispatchSignInEvent(
+ "test_user_id", "test_email", true);
+ EXPECT_EQ(1ul, fake_event_router()->GetEventCount());
+ EXPECT_TRUE(fake_event_router()->ContainsExtensionId(ext->id()));
+ EXPECT_EQ("test_user_id",
+ fake_event_router()->GetEventInfo(ext->id()).user_id);
+ EXPECT_EQ("test_email", fake_event_router()->GetEventInfo(ext->id()).email);
+ EXPECT_TRUE(fake_event_router()->GetEventInfo(ext->id()).is_signed_in);
+
+ fake_event_router()->RemoveEventListener(
+ api::identity::OnSignInChanged::kEventName,
+ fake_render_process.get(),
+ ext->id());
+}
+
+TEST_F(IdentityEventRouterTest, SignOut) {
+ scoped_refptr<const Extension> ext = CreateExtension(false);
+ identity_event_router_.DispatchSignInEvent(
+ "test_user_id", "test_email", false);
+ EXPECT_EQ(1ul, fake_event_router()->GetEventCount());
+ EXPECT_TRUE(fake_event_router()->ContainsExtensionId(ext->id()));
+ EXPECT_EQ("test_user_id",
+ fake_event_router()->GetEventInfo(ext->id()).user_id);
+ EXPECT_TRUE(fake_event_router()->GetEventInfo(ext->id()).email.empty());
+ EXPECT_FALSE(fake_event_router()->GetEventInfo(ext->id()).is_signed_in);
+}
+
+} // namespace extensions
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 9f2d058..51dbee7 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -284,6 +284,8 @@
'browser/extensions/api/identity/gaia_web_auth_flow.h',
'browser/extensions/api/identity/identity_api.cc',
'browser/extensions/api/identity/identity_api.h',
+ 'browser/extensions/api/identity/identity_event_router.cc',
+ 'browser/extensions/api/identity/identity_event_router.h',
'browser/extensions/api/identity/identity_mint_queue.cc',
'browser/extensions/api/identity/identity_mint_queue.h',
'browser/extensions/api/identity/identity_signin_flow.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index d9f91ea..083c7e4 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -809,6 +809,7 @@
'browser/extensions/api/file_system/file_system_api_unittest.cc',
'browser/extensions/api/identity/experimental_web_auth_flow_unittest.cc',
'browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc',
+ 'browser/extensions/api/identity/identity_event_router_unittest.cc',
'browser/extensions/api/identity/identity_mint_queue_unittest.cc',
'browser/extensions/api/idle/idle_api_unittest.cc',
'browser/extensions/api/log_private/syslog_parser_unittest.cc',
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index b6e72e7..9026c20 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -309,6 +309,11 @@
"dependencies": ["permission:identity"],
"contexts": ["blessed_extension"]
},
+ "identity.onSignInChanged": {
+ "channel": "dev",
+ "dependencies": ["permission:identity"],
+ "contexts": ["blessed_extension"]
+ },
"identityPrivate": {
"dependencies": ["permission:identityPrivate"],
"contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index ce62073..922176a 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -360,6 +360,10 @@
"channel": "stable",
"extension_types": ["extension", "platform_app"]
},
+ "identity.email": {
+ "channel": "dev",
+ "extension_types": ["extension", "platform_app"]
+ },
"identityPrivate": {
"channel": "stable",
"extension_types": [
diff --git a/chrome/common/extensions/api/identity.idl b/chrome/common/extensions/api/identity.idl
index cba84e4..cefd50c 100644
--- a/chrome/common/extensions/api/identity.idl
+++ b/chrome/common/extensions/api/identity.idl
@@ -39,6 +39,11 @@ namespace identity {
boolean? interactive;
};
+ dictionary AccountInfo {
+ DOMString id;
+ DOMString? email;
+ };
+
callback GetAuthTokenCallback = void (optional DOMString token);
callback InvalidateAuthTokenCallback = void ();
callback LaunchWebAuthFlowCallback = void (optional DOMString responseUrl);
@@ -85,6 +90,10 @@ namespace identity {
// |callback| : Called with the URL redirected back to your application.
static void launchWebAuthFlow(WebAuthFlowDetails details,
LaunchWebAuthFlowCallback callback);
- }
- ;
+ };
+
+ interface Events {
+ // Fired when signin state changes for an account on the user's profile.
+ static void onSignInChanged(AccountInfo account, boolean signedIn);
+ };
};
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index 28790c2..1950a9946 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -64,6 +64,10 @@ std::vector<APIPermissionInfo*> ChromeAPIPermissions::GetAllPermissions()
PermissionMessage::kDownloadsOpen },
{ APIPermission::kDownloadsShelf, "downloads.shelf" },
{ APIPermission::kIdentity, "identity" },
+ { APIPermission::kIdentityEmail, "identity.email",
+ APIPermissionInfo::kFlagNone,
+ IDS_EXTENSION_PROMPT_WARNING_IDENTITY_EMAIL,
+ PermissionMessage::kIdentityEmail },
{ APIPermission::kExperimental, "experimental",
APIPermissionInfo::kFlagCannotBeOptional },
// NOTE(kalman): this is provided by a manifest property but needs to
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index 7e09d14..7dd42c0 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -91,6 +91,7 @@ class APIPermission {
kGeolocation,
kHistory,
kIdentity,
+ kIdentityEmail,
kIdentityPrivate,
kIdltest,
kIdle,
diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h
index 19c5799..3b745b2 100644
--- a/extensions/common/permissions/permission_message.h
+++ b/extensions/common/permissions/permission_message.h
@@ -74,6 +74,7 @@ class PermissionMessage {
kSignedInDevices,
kWallpaper,
kNetworkState,
+ kIdentityEmail,
kEnumBoundary,
};
COMPILE_ASSERT(PermissionMessage::kNone > PermissionMessage::kUnknown,