summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/DEPS3
-rw-r--r--chrome/browser/extensions/app_background_page_apitest.cc118
-rw-r--r--chrome/chrome_tests.gypi3
-rw-r--r--components/nacl/browser/nacl_process_host.cc6
-rw-r--r--extensions/browser/process_manager.cc18
-rw-r--r--extensions/browser/process_manager.h11
-rw-r--r--ppapi/proxy/plugin_main_nacl.cc17
-rw-r--r--ppapi/shared_impl/ppapi_switches.cc3
-rw-r--r--ppapi/shared_impl/ppapi_switches.h1
-rw-r--r--ppapi/tests/extensions/background_keepalive/background.cc63
-rw-r--r--ppapi/tests/extensions/background_keepalive/background.js41
-rw-r--r--ppapi/tests/extensions/background_keepalive/manifest.json11
-rw-r--r--ppapi/tests/extensions/extensions.gyp19
13 files changed, 311 insertions, 3 deletions
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS
index 3cc3516..e2e659d 100644
--- a/chrome/browser/extensions/DEPS
+++ b/chrome/browser/extensions/DEPS
@@ -12,4 +12,7 @@ include_rules = [
# DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
"!chrome/browser/ui/views/extensions/extension_view_views.h",
# DO NOT ADD ANY MORE ITEMS TO THE ABOVE LIST!
+
+ # For access to testing command line switches.
+ "+ppapi/shared_impl",
]
diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc
index aa14346..7fc1d53 100644
--- a/chrome/browser/extensions/app_background_page_apitest.cc
+++ b/chrome/browser/extensions/app_background_page_apitest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/background/background_contents_service.h"
@@ -11,10 +12,13 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/extensions/application_launch.h"
+#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_notification_tracker.h"
@@ -23,6 +27,7 @@
#include "extensions/common/switches.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "ppapi/shared_impl/ppapi_switches.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
@@ -108,6 +113,88 @@ class AppBackgroundPageApiTest : public ExtensionApiTest {
base::ScopedTempDir app_dir_;
};
+namespace {
+
+// Fixture to assist in testing v2 app background pages containing
+// Native Client embeds.
+class AppBackgroundPageNaClTest : public AppBackgroundPageApiTest {
+ public:
+ AppBackgroundPageNaClTest()
+ : extension_(NULL) {
+ PathService::Get(chrome::DIR_GEN_TEST_DATA, &app_dir_);
+ app_dir_ = app_dir_.AppendASCII(
+ "ppapi/tests/extensions/background_keepalive/newlib");
+ }
+ virtual ~AppBackgroundPageNaClTest() {
+ }
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ AppBackgroundPageApiTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(
+ switches::kPpapiKeepAliveThrottle, "50");
+ command_line->AppendSwitchASCII(
+ extensions::switches::kEventPageIdleTime, "1000");
+ command_line->AppendSwitchASCII(
+ extensions::switches::kEventPageSuspendingTime, "1000");
+ }
+
+ const Extension* extension() { return extension_; }
+
+ protected:
+ void LaunchTestingApp() {
+ extension_ = LoadExtension(app_dir_);
+ ASSERT_TRUE(extension_);
+ }
+
+ private:
+ base::FilePath app_dir_;
+ const Extension* extension_;
+};
+
+// Produces an extensions::ProcessManager::ImpulseCallbackForTesting callback
+// that will match a specified goal and can be waited on.
+class ImpulseCallbackCounter {
+ public:
+ explicit ImpulseCallbackCounter(const std::string& extension_id)
+ : observed_(0),
+ goal_(0),
+ extension_id_(extension_id) {
+ }
+
+ extensions::ProcessManager::ImpulseCallbackForTesting
+ SetGoalAndGetCallback(int goal) {
+ observed_ = 0;
+ goal_ = goal;
+ message_loop_runner_ = new content::MessageLoopRunner();
+ return base::Bind(&ImpulseCallbackCounter::ImpulseCallback,
+ base::Unretained(this),
+ message_loop_runner_->QuitClosure(),
+ extension_id_);
+ }
+
+ void Wait() {
+ message_loop_runner_->Run();
+ }
+ private:
+ void ImpulseCallback(
+ const base::Closure& quit_callback,
+ const std::string& extension_id_from_test,
+ const std::string& extension_id_from_manager) {
+ if (extension_id_from_test == extension_id_from_manager) {
+ if (++observed_ >= goal_) {
+ quit_callback.Run();
+ }
+ }
+ }
+
+ int observed_;
+ int goal_;
+ const std::string extension_id_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+};
+
+} // namespace
+
// Disable on Mac only. http://crbug.com/95139
#if defined(OS_MACOSX)
#define MAYBE_Basic DISABLED_Basic
@@ -502,3 +589,34 @@ IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, UnloadExtensionWhileHidden) {
content::RunAllPendingInMessageLoop();
ASSERT_TRUE(WaitForBackgroundMode(false));
}
+
+// Verify active NaCl embeds cause many keepalive impulses to be sent.
+IN_PROC_BROWSER_TEST_F(AppBackgroundPageNaClTest, BackgroundKeepaliveActive) {
+ ExtensionTestMessageListener nacl_modules_loaded("nacl_modules_loaded", true);
+ LaunchTestingApp();
+ extensions::ProcessManager* manager =
+ extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
+ ImpulseCallbackCounter active_impulse_counter(extension()->id());
+ EXPECT_TRUE(nacl_modules_loaded.WaitUntilSatisfied());
+
+ // Target .5 seconds: .5 seconds / 50ms throttle * 2 embeds == 20 impulses.
+ manager->SetKeepaliveImpulseCallbackForTesting(
+ active_impulse_counter.SetGoalAndGetCallback(20));
+ active_impulse_counter.Wait();
+}
+
+// Verify that nacl modules that go idle will not send keepalive impulses.
+IN_PROC_BROWSER_TEST_F(AppBackgroundPageNaClTest, BackgroundKeepaliveIdle) {
+ ExtensionTestMessageListener nacl_modules_loaded("nacl_modules_loaded", true);
+ LaunchTestingApp();
+ extensions::ProcessManager* manager =
+ extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
+ ImpulseCallbackCounter idle_impulse_counter(extension()->id());
+ EXPECT_TRUE(nacl_modules_loaded.WaitUntilSatisfied());
+
+ manager->SetKeepaliveImpulseDecrementCallbackForTesting(
+ idle_impulse_counter.SetGoalAndGetCallback(1));
+ nacl_modules_loaded.Reply("be idle");
+ idle_impulse_counter.Wait();
+}
+
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index aae7ddf..fe6836b 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1684,7 +1684,8 @@
'test/data/nacl/nacl_test_data.gyp:*',
'../ppapi/native_client/native_client.gyp:nacl_irt',
'../ppapi/ppapi_untrusted.gyp:ppapi_nacl_tests',
- '../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_socket',
+ '../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_background_keepalive',
+ '../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_socket'
],
'conditions': [
['OS=="linux"', {
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 6bd813d..6ad6f21 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -810,7 +810,11 @@ void NaClProcessHost::OnPpapiChannelCreated(
args.permissions = permissions_;
CommandLine* cmdline = CommandLine::ForCurrentProcess();
DCHECK(cmdline);
- std::string flag_whitelist[] = {switches::kV, switches::kVModule};
+ std::string flag_whitelist[] = {
+ switches::kPpapiKeepAliveThrottle,
+ switches::kV,
+ switches::kVModule,
+ };
for (size_t i = 0; i < arraysize(flag_whitelist); ++i) {
std::string value = cmdline->GetSwitchValueASCII(flag_whitelist[i]);
if (!value.empty()) {
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index e49d990..1eb2903 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -421,6 +421,9 @@ void ProcessManager::KeepaliveImpulse(const Extension* extension) {
IncrementLazyKeepaliveCount(extension);
}
}
+
+ if (!keepalive_impulse_callback_for_testing_.is_null())
+ keepalive_impulse_callback_for_testing_.Run(extension->id());
}
// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse
@@ -433,8 +436,11 @@ void ProcessManager::OnKeepaliveImpulseCheck() {
for (BackgroundPageDataMap::iterator i = background_page_data_.begin();
i != background_page_data_.end();
++i) {
- if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse)
+ if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) {
DecrementLazyKeepaliveCount(i->first);
+ if (!keepalive_impulse_decrement_callback_for_testing_.is_null())
+ keepalive_impulse_decrement_callback_for_testing_.Run(i->first);
+ }
i->second.previous_keepalive_impulse = i->second.keepalive_impulse;
i->second.keepalive_impulse = false;
@@ -553,6 +559,16 @@ content::BrowserContext* ProcessManager::GetBrowserContext() const {
return site_instance_->GetBrowserContext();
}
+void ProcessManager::SetKeepaliveImpulseCallbackForTesting(
+ const ImpulseCallbackForTesting& callback) {
+ keepalive_impulse_callback_for_testing_ = callback;
+}
+
+void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting(
+ const ImpulseCallbackForTesting& callback) {
+ keepalive_impulse_decrement_callback_for_testing_ = callback;
+}
+
void ProcessManager::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h
index fa5f2b6..4aa5141 100644
--- a/extensions/browser/process_manager.h
+++ b/extensions/browser/process_manager.h
@@ -120,6 +120,14 @@ class ProcessManager : public content::NotificationObserver {
// related SiteInstances.
content::BrowserContext* GetBrowserContext() const;
+ // Sets callbacks for testing keepalive impulse behavior.
+ typedef base::Callback<void(const std::string& extension_id)>
+ ImpulseCallbackForTesting;
+ void SetKeepaliveImpulseCallbackForTesting(
+ const ImpulseCallbackForTesting& callback);
+ void SetKeepaliveImpulseDecrementCallbackForTesting(
+ const ImpulseCallbackForTesting& callback);
+
protected:
// If |context| is incognito pass the master context as |original_context|.
// Otherwise pass the same context for both.
@@ -215,6 +223,9 @@ class ProcessManager : public content::NotificationObserver {
base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_;
+ ImpulseCallbackForTesting keepalive_impulse_callback_for_testing_;
+ ImpulseCallbackForTesting keepalive_impulse_decrement_callback_for_testing_;
+
base::WeakPtrFactory<ProcessManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ProcessManager);
diff --git a/ppapi/proxy/plugin_main_nacl.cc b/ppapi/proxy/plugin_main_nacl.cc
index bced108..6690f20 100644
--- a/ppapi/proxy/plugin_main_nacl.cc
+++ b/ppapi/proxy/plugin_main_nacl.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "components/tracing/child_trace_message_filter.h"
@@ -29,6 +30,7 @@
#include "ppapi/proxy/plugin_message_filter.h"
#include "ppapi/proxy/plugin_proxy_delegate.h"
#include "ppapi/proxy/resource_reply_thread_registrar.h"
+#include "ppapi/shared_impl/ppapi_switches.h"
#include "ppapi/shared_impl/ppb_audio_shared.h"
#if defined(IPC_MESSAGE_LOG_ENABLED)
@@ -95,6 +97,8 @@ class PpapiDispatcher : public ProxyChannel,
SerializedHandle handle);
void OnPluginDispatcherMessageReceived(const IPC::Message& msg);
+ void SetPpapiKeepAliveThrottleFromCommandLine();
+
std::set<PP_Instance> instances_;
std::map<uint32, PluginDispatcher*> plugin_dispatchers_;
uint32 next_plugin_dispatcher_id_;
@@ -208,6 +212,7 @@ void PpapiDispatcher::OnMsgCreateNaClChannel(
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
logging::InitLogging(settings);
+ SetPpapiKeepAliveThrottleFromCommandLine();
command_line_and_logging_initialized = true;
}
// Tell the process-global GetInterface which interfaces it can return to the
@@ -250,6 +255,18 @@ void PpapiDispatcher::OnPluginDispatcherMessageReceived(
dispatcher->second->OnMessageReceived(msg);
}
+void PpapiDispatcher::SetPpapiKeepAliveThrottleFromCommandLine() {
+ unsigned keepalive_throttle_interval_milliseconds = 0;
+ if (base::StringToUint(
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kPpapiKeepAliveThrottle),
+ &keepalive_throttle_interval_milliseconds)) {
+ ppapi::proxy::PluginGlobals::Get()->
+ set_keepalive_throttle_interval_milliseconds(
+ keepalive_throttle_interval_milliseconds);
+ }
+}
+
} // namespace
void PpapiPluginRegisterThreadCreator(
diff --git a/ppapi/shared_impl/ppapi_switches.cc b/ppapi/shared_impl/ppapi_switches.cc
index 84ba250..2a3f1c28 100644
--- a/ppapi/shared_impl/ppapi_switches.cc
+++ b/ppapi/shared_impl/ppapi_switches.cc
@@ -9,4 +9,7 @@ namespace switches {
// Enables the testing interface for PPAPI.
const char kEnablePepperTesting[] = "enable-pepper-testing";
+// Specifies throttling time in milliseconds for PpapiHostMsg_Keepalive IPCs.
+const char kPpapiKeepAliveThrottle[] = "ppapi-keep-alive-throttle";
+
} // namespace switches
diff --git a/ppapi/shared_impl/ppapi_switches.h b/ppapi/shared_impl/ppapi_switches.h
index a5c8e9d..4fb9c3481 100644
--- a/ppapi/shared_impl/ppapi_switches.h
+++ b/ppapi/shared_impl/ppapi_switches.h
@@ -10,6 +10,7 @@
namespace switches {
PPAPI_SHARED_EXPORT extern const char kEnablePepperTesting[];
+PPAPI_SHARED_EXPORT extern const char kPpapiKeepAliveThrottle[];
} // namespace switches
diff --git a/ppapi/tests/extensions/background_keepalive/background.cc b/ppapi/tests/extensions/background_keepalive/background.cc
new file mode 100644
index 0000000..53f166b
--- /dev/null
+++ b/ppapi/tests/extensions/background_keepalive/background.cc
@@ -0,0 +1,63 @@
+// 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 <cstdio>
+#include <string>
+
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/message_loop.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+class Instance : public pp::Instance {
+ public:
+ explicit Instance(PP_Instance instance) :
+ pp::Instance(instance),
+ callback_factory_(this),
+ delay_milliseconds_(10),
+ active_(true) {
+ DoSomething(PP_OK);
+ }
+ virtual ~Instance() {}
+
+ virtual void HandleMessage(const pp::Var& message_var) {
+ std::string message_string = message_var.AsString();
+ if (message_string == "be idle") {
+ active_ = false;
+ } else {
+ PostMessage("Unhandled control message.");
+ }
+ }
+
+ void DoSomething(int32_t result) {
+ if (active_) {
+ pp::MessageLoop loop = pp::MessageLoop::GetCurrent();
+ pp::CompletionCallback c = callback_factory_.NewCallback(
+ &Instance::DoSomething);
+ loop.PostWork(c, delay_milliseconds_);
+ }
+ }
+
+ pp::CompletionCallbackFactory<Instance> callback_factory_;
+ int delay_milliseconds_;
+ bool active_;
+};
+
+class Module : public pp::Module {
+ public:
+ Module() : pp::Module() {}
+ virtual ~Module() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new Instance(instance);
+ }
+};
+
+namespace pp {
+Module* CreateModule() {
+ return new ::Module();
+}
+} // namespace pp
+
diff --git a/ppapi/tests/extensions/background_keepalive/background.js b/ppapi/tests/extensions/background_keepalive/background.js
new file mode 100644
index 0000000..90e4864
--- /dev/null
+++ b/ppapi/tests/extensions/background_keepalive/background.js
@@ -0,0 +1,41 @@
+// 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.
+
+var NaClModulesExpected = 0;
+var NaClModulesLoaded = 0;
+
+// Indicate load success.
+function moduleDidLoad() {
+ NaClModulesLoaded++;
+ if (NaClModulesLoaded == NaClModulesExpected)
+ chrome.test.sendMessage("nacl_modules_loaded", handleChromeTestMessage);
+}
+
+var handleChromeTestMessage = function (message) {
+ NaClModules = document.querySelectorAll('embed');
+ for (var i = 0; i < NaClModules.length; i++) {
+ NaClModules[i].postMessage(message);
+ }
+}
+
+function handleNaclMessage(message_event) {
+ console.log("handleNaclMessage: " + message_event.data);
+}
+
+function createNaClEmbed() {
+ NaClModulesExpected++;
+
+ var listener = document.createElement("div");
+ listener.addEventListener("load", moduleDidLoad, true);
+ listener.addEventListener("message", handleNaclMessage, true);
+ listener.innerHTML = '<embed' +
+ ' src="ppapi_tests_extensions_background_keepalive.nmf"' +
+ ' type="application/x-nacl" />';
+ document.body.appendChild(listener);
+}
+
+// Create 2 embeds to verify that we can handle more than one.
+createNaClEmbed();
+createNaClEmbed();
+
diff --git a/ppapi/tests/extensions/background_keepalive/manifest.json b/ppapi/tests/extensions/background_keepalive/manifest.json
new file mode 100644
index 0000000..28fb912
--- /dev/null
+++ b/ppapi/tests/extensions/background_keepalive/manifest.json
@@ -0,0 +1,11 @@
+{
+ "manifest_version": 2,
+ "name": "background_nacl",
+ "version": "0",
+ "description": "Tests keeping background page with NaCl alive when active.",
+ "app": {
+ "background": {
+ "scripts": ["background.js"]
+ }
+ }
+}
diff --git a/ppapi/tests/extensions/extensions.gyp b/ppapi/tests/extensions/extensions.gyp
index d063b83f4..70af268 100644
--- a/ppapi/tests/extensions/extensions.gyp
+++ b/ppapi/tests/extensions/extensions.gyp
@@ -29,5 +29,24 @@
],
},
},
+ {
+ 'target_name': 'ppapi_tests_extensions_background_keepalive',
+ 'type': 'none',
+ 'variables': {
+ 'nexe_target': 'ppapi_tests_extensions_background_keepalive',
+ # Only newlib build is used in tests, no need to build others.
+ 'build_newlib': 1,
+ 'build_glibc': 0,
+ 'build_pnacl_newlib': 0,
+ 'nexe_destination_dir': 'test_data/ppapi/tests/extensions/background_keepalive',
+ 'sources': [
+ 'background_keepalive/background.cc',
+ ],
+ 'test_files': [
+ 'background_keepalive/background.js',
+ 'background_keepalive/manifest.json',
+ ],
+ },
+ },
],
}