summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/gcm/gcm_api.cc78
-rw-r--r--chrome/browser/extensions/api/gcm/gcm_api.h24
-rw-r--r--chrome/browser/extensions/api/gcm/gcm_apitest.cc73
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_message.html1
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_message.js17
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.html1
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.js13
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_send_error.html1
-rw-r--r--chrome/test/data/extensions/api_test/gcm/events/on_send_error.js35
10 files changed, 249 insertions, 1 deletions
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.cc b/chrome/browser/extensions/api/gcm/gcm_api.cc
index 620aa46..9aa6889 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -10,9 +10,13 @@
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/services/gcm/gcm_profile_service.h"
#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
+#include "chrome/common/extensions/api/gcm.h"
+#include "extensions/browser/event_router.h"
#include "extensions/common/extension.h"
namespace {
@@ -23,13 +27,43 @@ const size_t kGoogDotPrefixLength = arraysize(kGoogDotRestrictedPrefix) - 1;
const char kGoogleRestrictedPrefix[] = "google";
const size_t kGooglePrefixLength = arraysize(kGoogleRestrictedPrefix) - 1;
+// Error messages.
+const char kInvalidParameter[] =
+ "Function was called with invalid parameters.";
+const char kAsyncOperationPending[] =
+ "Asynchronous operation is pending.";
+const char kNetworkError[] = "Network error occured.";
+const char kServerError[] = "Server error occured.";
+const char kTtlExceeded[] = "Time-to-live exceeded.";
+const char kUnknownError[] = "Unknown error occured.";
+
std::string SHA1HashHexString(const std::string& str) {
std::string hash = base::SHA1HashString(str);
return base::HexEncode(hash.data(), hash.size());
}
const char* GcmResultToError(gcm::GCMClient::Result result) {
- // TODO(fgorski): Add proper error translation with the onSendError event.
+ switch (result) {
+ case gcm::GCMClient::SUCCESS:
+ return "";
+ case gcm::GCMClient::INVALID_PARAMETER:
+ return kInvalidParameter;
+ case gcm::GCMClient::ASYNC_OPERATION_PENDING:
+ return kAsyncOperationPending;
+ case gcm::GCMClient::NETWORK_ERROR:
+ return kNetworkError;
+ case gcm::GCMClient::SERVER_ERROR:
+ return kServerError;
+ case gcm::GCMClient::TTL_EXCEEDED:
+ return kTtlExceeded;
+ case gcm::GCMClient::UNKNOWN_ERROR:
+ return kUnknownError;
+ default:
+ NOTREACHED() << "Unexpected value of result cannot be converted: "
+ << result;
+ }
+
+ // Never reached, but prevents missing return statement warning.
return "";
}
@@ -142,4 +176,46 @@ bool GcmSendFunction::ValidateMessageData(
return total_size != 0;
}
+GcmJsEventRouter::GcmJsEventRouter(Profile* profile) : profile_(profile) {}
+
+GcmJsEventRouter::~GcmJsEventRouter() {}
+
+void GcmJsEventRouter::OnMessage(
+ const std::string& app_id,
+ const gcm::GCMClient::IncomingMessage& message) {
+ api::gcm::OnMessage::Message message_arg;
+ message_arg.data.additional_properties = message.data;
+
+ scoped_ptr<Event> event(new Event(
+ api::gcm::OnMessage::kEventName,
+ api::gcm::OnMessage::Create(message_arg).Pass(),
+ profile_));
+ ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
+ app_id, event.Pass());
+}
+
+void GcmJsEventRouter::OnMessagesDeleted(const std::string& app_id) {
+ scoped_ptr<Event> event(new Event(
+ api::gcm::OnMessagesDeleted::kEventName,
+ api::gcm::OnMessagesDeleted::Create().Pass(),
+ profile_));
+ ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
+ app_id, event.Pass());
+}
+
+void GcmJsEventRouter::OnSendError(const std::string& app_id,
+ const std::string& message_id,
+ gcm::GCMClient::Result result) {
+ api::gcm::OnSendError::Error error;
+ error.message_id.reset(new std::string(message_id));
+ error.error_message = GcmResultToError(result);
+
+ scoped_ptr<Event> event(new Event(
+ api::gcm::OnSendError::kEventName,
+ api::gcm::OnSendError::Create(error).Pass(),
+ profile_));
+ ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
+ app_id, event.Pass());
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.h b/chrome/browser/extensions/api/gcm/gcm_api.h
index 254a23e..dbed949 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.h
+++ b/chrome/browser/extensions/api/gcm/gcm_api.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_GCM_GCM_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_GCM_GCM_API_H_
+#include "chrome/browser/services/gcm/gcm_event_router.h"
#include "chrome/common/extensions/api/gcm.h"
#include "extensions/browser/extension_function.h"
#include "google_apis/gcm/gcm_client.h"
@@ -13,6 +14,8 @@ namespace gcm {
class GCMProfileService;
} // namespace gcm
+class Profile;
+
namespace extensions {
class GcmApiFunction : public AsyncExtensionFunction {
@@ -78,6 +81,27 @@ class GcmSendFunction : public GcmApiFunction {
gcm::GCMClient::OutgoingMessage outgoing_message_;
};
+class GcmJsEventRouter : public gcm::GCMEventRouter {
+ public:
+ explicit GcmJsEventRouter(Profile* profile);
+
+ virtual ~GcmJsEventRouter();
+
+ // GCMEventRouter:
+ virtual void OnMessage(
+ const std::string& app_id,
+ const gcm::GCMClient::IncomingMessage& message) OVERRIDE;
+ virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
+ virtual void OnSendError(const std::string& app_id,
+ const std::string& message_id,
+ gcm::GCMClient::Result result) OVERRIDE;
+
+ private:
+ // The application we route the event to is running in context of the
+ // |profile_| and the latter outlives the event router.
+ Profile* profile_;
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_GCM_GCM_API_H_
diff --git a/chrome/browser/extensions/api/gcm/gcm_apitest.cc b/chrome/browser/extensions/api/gcm/gcm_apitest.cc
index af37fa0..9435133 100644
--- a/chrome/browser/extensions/api/gcm/gcm_apitest.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_apitest.cc
@@ -13,6 +13,7 @@
namespace {
const char kFunctionsTestExtension[] = "gcm/functions";
+const char kEventsExtension[] = "gcm/events";
} // namespace
@@ -141,4 +142,76 @@ IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_SendMessageData) {
EXPECT_EQ("value2", iter->second);
}
+// http://crbug.com/177163 and http://crbug/324982
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_OnMessagesDeleted DISABLED_OnMessagesDeleted
+#else
+#define MAYBE_OnMessagesDeleted OnMessagesDeleted
+#endif
+IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_OnMessagesDeleted) {
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(profile());
+
+ const extensions::Extension* extension =
+ LoadTestExtension(kEventsExtension, "on_messages_deleted.html");
+ ASSERT_TRUE(extension);
+
+ GcmJsEventRouter router(profile());
+ router.OnMessagesDeleted(extension->id());
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+// http://crbug.com/177163 and http://crbug/324982
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_OnMessage DISABLED_OnMessage
+#else
+#define MAYBE_OnMessage OnMessage
+#endif
+IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_OnMessage) {
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(profile());
+
+ const extensions::Extension* extension =
+ LoadTestExtension(kEventsExtension, "on_message.html");
+ ASSERT_TRUE(extension);
+
+ GcmJsEventRouter router(profile());
+
+ gcm::GCMClient::IncomingMessage message;
+ message.data["property1"] = "value1";
+ message.data["property2"] = "value2";
+ router.OnMessage(extension->id(), message);
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+// http://crbug.com/177163 and http://crbug/324982
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_OnSendError DISABLED_OnSendError
+#else
+#define MAYBE_OnSendError OnSendError
+#endif
+IN_PROC_BROWSER_TEST_F(GcmApiTest, MAYBE_OnSendError) {
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(profile());
+
+ const extensions::Extension* extension =
+ LoadTestExtension(kEventsExtension, "on_send_error.html");
+ ASSERT_TRUE(extension);
+
+ GcmJsEventRouter router(profile());
+ router.OnSendError(extension->id(), "error_message_1",
+ gcm::GCMClient::ASYNC_OPERATION_PENDING);
+ router.OnSendError(extension->id(), "error_message_2",
+ gcm::GCMClient::SERVER_ERROR);
+ router.OnSendError(extension->id(), "error_message_3",
+ gcm::GCMClient::NETWORK_ERROR);
+ router.OnSendError(extension->id(), "error_message_4",
+ gcm::GCMClient::UNKNOWN_ERROR);
+ router.OnSendError(extension->id(), "error_message_5",
+ gcm::GCMClient::TTL_EXCEEDED);
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
} // namespace extensions
diff --git a/chrome/test/data/extensions/api_test/gcm/events/manifest.json b/chrome/test/data/extensions/api_test/gcm/events/manifest.json
new file mode 100644
index 0000000..e7968681
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/manifest.json
@@ -0,0 +1,7 @@
+{
+ "manifest_version": 2,
+ "name": "Test GCM App",
+ "version": "1.0",
+ "description": "Tests GCM API",
+ "permissions": ["gcm"]
+}
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_message.html b/chrome/test/data/extensions/api_test/gcm/events/on_message.html
new file mode 100644
index 0000000..48207fa
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_message.html
@@ -0,0 +1 @@
+<script src="on_message.js"></script>
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_message.js b/chrome/test/data/extensions/api_test/gcm/events/on_message.js
new file mode 100644
index 0000000..7fbfdf2
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_message.js
@@ -0,0 +1,17 @@
+// 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.
+
+onload = function() {
+ chrome.test.runTests([
+ function onMessage() {
+ chrome.test.listenOnce(chrome.gcm.onMessage, function(message) {
+ chrome.test.assertEq(2, Object.keys(message.data).length);
+ chrome.test.assertTrue(message.data.hasOwnProperty('property1'));
+ chrome.test.assertTrue(message.data.hasOwnProperty('property2'));
+ chrome.test.assertEq('value1', message.data.property1);
+ chrome.test.assertEq('value2', message.data.property2);
+ });
+ }
+ ]);
+};
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.html b/chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.html
new file mode 100644
index 0000000..fa2dfc8
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.html
@@ -0,0 +1 @@
+<script src="on_messages_deleted.js"></script>
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.js b/chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.js
new file mode 100644
index 0000000..440042b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_messages_deleted.js
@@ -0,0 +1,13 @@
+// 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.
+
+onload = function() {
+ chrome.test.runTests([
+ function messagesDeleted() {
+ chrome.test.listenOnce(chrome.gcm.onMessagesDeleted, function() {
+ chrome.test.assertTrue(true);
+ });
+ }
+ ]);
+};
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_send_error.html b/chrome/test/data/extensions/api_test/gcm/events/on_send_error.html
new file mode 100644
index 0000000..6a2ff0c
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_send_error.html
@@ -0,0 +1 @@
+<script src="on_send_error.js"></script>
diff --git a/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js b/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js
new file mode 100644
index 0000000..6200fbd
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/gcm/events/on_send_error.js
@@ -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.
+
+onload = function() {
+ chrome.test.runTests([
+ function onSendError() {
+ var errorMessages = [
+ 'Asynchronous operation is pending.',
+ 'Server error occured.',
+ 'Network error occured.',
+ 'Unknown error occured.',
+ 'Time-to-live exceeded.'
+ ];
+ var messageIds = [
+ 'error_message_1',
+ 'error_message_2',
+ 'error_message_3',
+ 'error_message_4',
+ 'error_message_5'
+ ];
+ var currentError = 0;
+ var eventHandler = function(error) {
+ chrome.test.assertEq(errorMessages[currentError], error.errorMessage);
+ chrome.test.assertEq(messageIds[currentError], error.messageId);
+ currentError += 1;
+ if (currentError == messageIds.length) {
+ chrome.gcm.onSendError.removeListener(eventHandler);
+ chrome.test.succeed();
+ }
+ };
+ chrome.gcm.onSendError.addListener(eventHandler);
+ }
+ ]);
+};