summaryrefslogtreecommitdiffstats
path: root/chrome/browser/background
diff options
context:
space:
mode:
authordimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-28 21:58:53 +0000
committerdimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-28 21:58:53 +0000
commit0d784792f432a058824d332d3cd7f4f2617f2092 (patch)
tree0af48586dfa3bf9eeccb8baac06b6d53722bb4f5 /chrome/browser/background
parent0f79893bfd2a3c5bcc20bd32ad9b509f0e157115 (diff)
downloadchromium_src-0d784792f432a058824d332d3cd7f4f2617f2092.zip
chromium_src-0d784792f432a058824d332d3cd7f4f2617f2092.tar.gz
chromium_src-0d784792f432a058824d332d3cd7f4f2617f2092.tar.bz2
Enable apps that use Push Messaging to not request background mode.
The use case: the app is using Push Messaging for not real-time event that happens rarely. There is no great reason to keep Chrome running just for that. Implemented as a whitelist for now since we believe this is a temporary solution. A better solution, which would allow push to work all the time but not keep Chrome running can take longer time. See bug for more info. BUG=311268 Review URL: https://codereview.chromium.org/45863002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231419 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/background')
-rw-r--r--chrome/browser/background/background_application_list_model.cc26
-rw-r--r--chrome/browser/background/background_application_list_model.h7
-rw-r--r--chrome/browser/background/background_application_list_model_unittest.cc139
3 files changed, 158 insertions, 14 deletions
diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc
index 1661b39..11c4406 100644
--- a/chrome/browser/background/background_application_list_model.cc
+++ b/chrome/browser/background/background_application_list_model.cc
@@ -7,7 +7,9 @@
#include <algorithm>
#include <set>
+#include "base/sha1.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/background/background_contents_service.h"
@@ -267,6 +269,28 @@ int BackgroundApplicationListModel::GetPosition(
}
// static
+bool BackgroundApplicationListModel::RequiresBackgroundModeForPushMessaging(
+ const Extension& extension) {
+ // No PushMessaging permission - does not require the background mode.
+ if (!extension.HasAPIPermission(APIPermission::kPushMessaging))
+ return false;
+
+ // If in the whitelist, then does not require background mode even if
+ // uses push messaging.
+ // TODO(dimich): remove this whitelist once we have a better way to keep
+ // listening for GCM. http://crbug.com/311268
+ std::string id_hash = base::SHA1HashString(extension.id());
+ std::string hexencoded_id_hash = base::HexEncode(id_hash.c_str(),
+ id_hash.length());
+ // The id starting from "9A04..." is a one from unit test.
+ if (hexencoded_id_hash == "C41AD9DCD670210295614257EF8C9945AD68D86E" ||
+ hexencoded_id_hash == "9A0417016F345C934A1A88F55CA17C05014EEEBA")
+ return false;
+
+ return true;
+ }
+
+// static
bool BackgroundApplicationListModel::IsBackgroundApp(
const Extension& extension, Profile* profile) {
// An extension is a "background app" if it has the "background API"
@@ -278,7 +302,7 @@ bool BackgroundApplicationListModel::IsBackgroundApp(
// Not a background app if we don't have the background permission or
// the push messaging permission
if (!extension.HasAPIPermission(APIPermission::kBackground) &&
- !extension.HasAPIPermission(APIPermission::kPushMessaging) )
+ !RequiresBackgroundModeForPushMessaging(extension))
return false;
// Extensions and packaged apps with background permission are always treated
diff --git a/chrome/browser/background/background_application_list_model.h b/chrome/browser/background/background_application_list_model.h
index e9be88a..1bc7d2d 100644
--- a/chrome/browser/background/background_application_list_model.h
+++ b/chrome/browser/background/background_application_list_model.h
@@ -139,6 +139,13 @@ class BackgroundApplicationListModel : public content::NotificationObserver {
// Refresh the list of background applications and generate notifications.
void Update();
+ // Determines if the given extension has to be considered a "background app"
+ // due to its use of PushMessaging. Normally every extension that expectes
+ // push messages is classified as "background app", however there are some
+ // rare exceptions, so this function implements a whitelist.
+ static bool RequiresBackgroundModeForPushMessaging(
+ const extensions::Extension& extension);
+
ApplicationMap applications_;
extensions::ExtensionList extensions_;
ObserverList<Observer> observers_;
diff --git a/chrome/browser/background/background_application_list_model_unittest.cc b/chrome/browser/background/background_application_list_model_unittest.cc
index 0c35c59..62aa6c2 100644
--- a/chrome/browser/background/background_application_list_model_unittest.cc
+++ b/chrome/browser/background/background_application_list_model_unittest.cc
@@ -35,8 +35,9 @@ using extensions::APIPermission;
using extensions::Extension;
// For ExtensionService interface when it requires a path that is not used.
-base::FilePath bogus_file_path() {
- return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent"));
+base::FilePath bogus_file_pathname(const std::string& name) {
+ return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent"))
+ .AppendASCII(name);
}
class BackgroundApplicationListModelTest : public ExtensionServiceTestBase {
@@ -56,32 +57,69 @@ class BackgroundApplicationListModelTest : public ExtensionServiceTestBase {
}
};
+enum PushMessagingOption {
+ NO_PUSH_MESSAGING,
+ PUSH_MESSAGING_PERMISSION,
+ PUSH_MESSAGING_BUT_NOT_BACKGROUND
+};
+
// Returns a barebones test Extension object with the specified |name|. The
// returned extension will include background permission iff
-// |background_permission| is true.
-static scoped_refptr<Extension> CreateExtension(const std::string& name,
- bool background_permission) {
+// |background_permission| is true and pushMessaging permission if requested
+// by |push_messaging| value. Also the extension may have a specific id set
+// to test the case when it has a pushMessaging permission but is not
+// considered a background app based on a whitelist.
+static scoped_refptr<Extension> CreateExtensionBase(
+ const std::string& name,
+ bool background_permission,
+ PushMessagingOption push_messaging) {
DictionaryValue manifest;
manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
manifest.SetString(extensions::manifest_keys::kName, name);
+ ListValue* permissions = new ListValue();
+ manifest.Set(extensions::manifest_keys::kPermissions, permissions);
if (background_permission) {
- ListValue* permissions = new ListValue();
- manifest.Set(extensions::manifest_keys::kPermissions, permissions);
permissions->Append(Value::CreateStringValue("background"));
}
+ if (push_messaging == PUSH_MESSAGING_PERMISSION ||
+ push_messaging == PUSH_MESSAGING_BUT_NOT_BACKGROUND) {
+ permissions->Append(Value::CreateStringValue("pushMessaging"));
+ }
+
std::string error;
- scoped_refptr<Extension> extension = Extension::Create(
- bogus_file_path().AppendASCII(name),
- extensions::Manifest::INVALID_LOCATION,
- manifest,
- Extension::NO_FLAGS,
- &error);
+ scoped_refptr<Extension> extension;
+
+ // There is a whitelist for extensions that have pushMessaging permission but
+ // are not considered a background app. Create a test extension with a known
+ // test id if needed.
+ if (push_messaging == PUSH_MESSAGING_BUT_NOT_BACKGROUND) {
+ extension = Extension::Create(
+ bogus_file_pathname(name),
+ extensions::Manifest::INVALID_LOCATION,
+ manifest,
+ Extension::NO_FLAGS,
+ "aaaabbbbccccddddeeeeffffgggghhhh",
+ &error);
+ } else {
+ extension = Extension::Create(
+ bogus_file_pathname(name),
+ extensions::Manifest::INVALID_LOCATION,
+ manifest,
+ Extension::NO_FLAGS,
+ &error);
+ }
+
// Cannot ASSERT_* here because that attempts an illegitimate return.
// Cannot EXPECT_NE here because that assumes non-pointers unlike EXPECT_EQ
EXPECT_TRUE(extension.get() != NULL) << error;
return extension;
}
+static scoped_refptr<Extension> CreateExtension(const std::string& name,
+ bool background_permission) {
+ return CreateExtensionBase(name, background_permission, NO_PUSH_MESSAGING);
+}
+
namespace {
std::string GenerateUniqueExtensionName() {
static int uniqueness = 0;
@@ -192,6 +230,81 @@ TEST_F(BackgroundApplicationListModelTest, MAYBE_ExplicitTest) {
ASSERT_EQ(0U, model->size());
}
+// Verifies that pushMessaging also triggers background detection, except
+// when extension is in a whitelist.
+TEST_F(BackgroundApplicationListModelTest, PushMessagingTest) {
+ InitializeAndLoadEmptyExtensionService();
+ ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())->
+ extension_service();
+ ASSERT_TRUE(service);
+ ASSERT_TRUE(service->is_ready());
+ ASSERT_TRUE(service->extensions());
+ ASSERT_TRUE(service->extensions()->is_empty());
+ scoped_ptr<BackgroundApplicationListModel> model(
+ new BackgroundApplicationListModel(profile_.get()));
+ ASSERT_EQ(0U, model->size());
+
+ scoped_refptr<Extension> ext1 = CreateExtension("alpha", false);
+ scoped_refptr<Extension> ext2 =
+ CreateExtensionBase("charlie", false, PUSH_MESSAGING_BUT_NOT_BACKGROUND);
+ scoped_refptr<Extension> bgapp1 =
+ CreateExtensionBase("bravo", false, PUSH_MESSAGING_PERMISSION);
+ scoped_refptr<Extension> bgapp2 =
+ CreateExtensionBase("delta", true, PUSH_MESSAGING_PERMISSION);
+ scoped_refptr<Extension> bgapp3 =
+ CreateExtensionBase("echo", true, PUSH_MESSAGING_BUT_NOT_BACKGROUND);
+ ASSERT_TRUE(service->extensions() != NULL);
+ ASSERT_EQ(0U, service->extensions()->size());
+ ASSERT_EQ(0U, model->size());
+
+ // Add alternating Extensions and Background Apps
+ ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
+ service->AddExtension(ext1.get());
+ ASSERT_EQ(1U, service->extensions()->size());
+ ASSERT_EQ(0U, model->size());
+ ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
+ service->AddExtension(bgapp1.get());
+ ASSERT_EQ(2U, service->extensions()->size());
+ ASSERT_EQ(1U, model->size());
+ ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
+ service->AddExtension(ext2.get());
+ ASSERT_EQ(3U, service->extensions()->size());
+ ASSERT_EQ(1U, model->size());
+ ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
+ service->AddExtension(bgapp2.get());
+ ASSERT_EQ(4U, service->extensions()->size());
+ ASSERT_EQ(2U, model->size());
+ // Need to remove ext2 because it uses same id as bgapp3.
+ ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
+ service->UninstallExtension(ext2->id(), false, NULL);
+ ASSERT_EQ(3U, service->extensions()->size());
+ ASSERT_EQ(2U, model->size());
+ ASSERT_TRUE(IsBackgroundApp(*bgapp3.get()));
+ service->AddExtension(bgapp3.get());
+ ASSERT_EQ(4U, service->extensions()->size());
+ ASSERT_EQ(3U, model->size());
+
+ // Remove in FIFO order.
+ ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
+ service->UninstallExtension(ext1->id(), false, NULL);
+ ASSERT_EQ(3U, service->extensions()->size());
+ ASSERT_EQ(3U, model->size());
+ ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
+ service->UninstallExtension(bgapp1->id(), false, NULL);
+ ASSERT_EQ(2U, service->extensions()->size());
+ ASSERT_EQ(2U, model->size());
+ ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
+ service->UninstallExtension(bgapp2->id(), false, NULL);
+ ASSERT_EQ(1U, service->extensions()->size());
+ ASSERT_EQ(1U, model->size());
+ ASSERT_TRUE(IsBackgroundApp(*bgapp3.get()));
+ service->UninstallExtension(bgapp3->id(), false, NULL);
+ ASSERT_EQ(0U, service->extensions()->size());
+ ASSERT_EQ(0U, model->size());
+}
+
+
+
// With minimal test logic, verifies behavior with dynamic permissions.
TEST_F(BackgroundApplicationListModelTest, AddRemovePermissionsTest) {
InitializeAndLoadEmptyExtensionService();