summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormiket@chromium.org <miket@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-09 00:40:20 +0000
committermiket@chromium.org <miket@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-09 00:40:20 +0000
commita1755bd1f3ae0ca4c05adf4d2979c3d09eb6278f (patch)
treed64e645ddbb3279e259a817310381406d7940e1a /chrome/browser
parent3a3cf4d1334d48a2668f544c8160736c323e430a (diff)
downloadchromium_src-a1755bd1f3ae0ca4c05adf4d2979c3d09eb6278f.zip
chromium_src-a1755bd1f3ae0ca4c05adf4d2979c3d09eb6278f.tar.gz
chromium_src-a1755bd1f3ae0ca4c05adf4d2979c3d09eb6278f.tar.bz2
Delete UDPClientSocket on same thread as creation. Also refactor.
I investigated deriving from IOThreadExtensionFunction, but we need access to Profile in the midst of our work. Deriving from UIThreadExtensionFunction appears to be the right way to do that. It's possible that we'll want to address performance issues caused by jumping back and forth between threads, but for now this seems to work well enough. See http://code.google.com/p/chromium/issues/detail?id=106802 for future plans to deal with lifetime more elegantly. Also reapply http://codereview.chromium.org/8819029/, which is what led to this bug/fix. BUG=106656 TEST=no new ones; just refactoring. Review URL: http://codereview.chromium.org/8857004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113710 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/api/socket/socket_api.cc172
-rw-r--r--chrome/browser/extensions/api/socket/socket_api.h83
-rw-r--r--chrome/browser/extensions/api/socket/socket_api_controller.cc21
-rw-r--r--chrome/browser/extensions/api/socket/socket_api_controller.h22
-rw-r--r--chrome/browser/extensions/api/socket/socket_api_controller_unittest.cc13
-rw-r--r--chrome/browser/extensions/extension_service.cc12
-rw-r--r--chrome/browser/extensions/extension_service.h9
7 files changed, 133 insertions, 199 deletions
diff --git a/chrome/browser/extensions/api/socket/socket_api.cc b/chrome/browser/extensions/api/socket/socket_api.cc
index 4d18ff9..f2cf86c 100644
--- a/chrome/browser/extensions/api/socket/socket_api.cc
+++ b/chrome/browser/extensions/api/socket/socket_api.cc
@@ -7,6 +7,8 @@
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/socket/socket_api_controller.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browser_thread.h"
@@ -18,13 +20,36 @@ const char kBytesWrittenKey[] = "bytesWritten";
const char kSocketIdKey[] = "socketId";
const char kUDPSocketType[] = "udp";
-SocketCreateFunction::SocketCreateFunction() {
+SocketController* SocketApiFunction::controller() {
+ return profile()->GetExtensionService()->socket_controller();
}
-SocketCreateFunction::~SocketCreateFunction() {
+bool SocketApiFunction::RunImpl() {
+ if (!Prepare()) {
+ return false;
+ }
+ bool rv = BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&SocketApiFunction::WorkOnIOThread, this));
+ DCHECK(rv);
+ return true;
+}
+
+void SocketApiFunction::WorkOnIOThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ Work();
+ bool rv = BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&SocketApiFunction::RespondOnUIThread, this));
+ DCHECK(rv);
+}
+
+void SocketApiFunction::RespondOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ SendResponse(Respond());
}
-bool SocketCreateFunction::RunImpl() {
+bool SocketCreateFunction::Prepare() {
std::string socket_type;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &socket_type));
@@ -36,172 +61,81 @@ bool SocketCreateFunction::RunImpl() {
if (socket_type != kUDPSocketType) {
return false;
}
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&SocketCreateFunction::WorkOnIOThread, this));
- DCHECK(rv);
return true;
}
-void SocketCreateFunction::WorkOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+void SocketCreateFunction::Work() {
DictionaryValue* result = new DictionaryValue();
- SocketController* controller = SocketController::GetInstance();
-
- int socket_id = controller->CreateUdp(profile(), extension_id(),
- source_url());
+ int socket_id = controller()->CreateUdp(profile(), extension_id(),
+ source_url());
result->SetInteger(kSocketIdKey, socket_id);
result_.reset(result);
- bool rv = BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SocketCreateFunction::RespondOnUIThread, this));
- DCHECK(rv);
-}
-
-void SocketCreateFunction::RespondOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SendResponse(true);
}
-SocketDestroyFunction::SocketDestroyFunction() {
-}
-
-SocketDestroyFunction::~SocketDestroyFunction() {
+bool SocketCreateFunction::Respond() {
+ return true;
}
-bool SocketDestroyFunction::RunImpl() {
+bool SocketDestroyFunction::Prepare() {
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&SocketDestroyFunction::WorkOnIOThread, this));
- DCHECK(rv);
return true;
}
-void SocketDestroyFunction::WorkOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- SocketController* controller = SocketController::GetInstance();
- controller->DestroyUdp(socket_id_);
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SocketDestroyFunction::RespondOnUIThread, this));
- DCHECK(rv);
-}
-
-void SocketDestroyFunction::RespondOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SendResponse(true);
-}
-
-SocketConnectFunction::SocketConnectFunction() {
+void SocketDestroyFunction::Work() {
+ controller()->DestroyUdp(socket_id_);
}
-SocketConnectFunction::~SocketConnectFunction() {
+bool SocketDestroyFunction::Respond() {
+ return true;
}
-bool SocketConnectFunction::RunImpl() {
+bool SocketConnectFunction::Prepare() {
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&SocketConnectFunction::WorkOnIOThread, this));
- DCHECK(rv);
return true;
}
-void SocketConnectFunction::WorkOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- SocketController* controller = SocketController::GetInstance();
- bool result = controller->ConnectUdp(socket_id_, address_, port_);
+void SocketConnectFunction::Work() {
+ bool result = controller()->ConnectUdp(socket_id_, address_, port_);
result_.reset(Value::CreateBooleanValue(result));
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SocketConnectFunction::RespondOnUIThread, this));
- DCHECK(rv);
}
-void SocketConnectFunction::RespondOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SendResponse(true);
-}
-
-SocketCloseFunction::SocketCloseFunction() {
-}
-
-SocketCloseFunction::~SocketCloseFunction() {
+bool SocketConnectFunction::Respond() {
+ return true;
}
-bool SocketCloseFunction::RunImpl() {
+bool SocketCloseFunction::Prepare() {
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&SocketCloseFunction::WorkOnIOThread, this));
- DCHECK(rv);
return true;
}
-void SocketCloseFunction::WorkOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- SocketController* controller = SocketController::GetInstance();
- controller->CloseUdp(socket_id_);
+void SocketCloseFunction::Work() {
+ controller()->CloseUdp(socket_id_);
result_.reset(Value::CreateNullValue());
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SocketCloseFunction::RespondOnUIThread, this));
- DCHECK(rv);
}
-void SocketCloseFunction::RespondOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SendResponse(true);
-}
-
-SocketWriteFunction::SocketWriteFunction() {
-}
-
-SocketWriteFunction::~SocketWriteFunction() {
+bool SocketCloseFunction::Respond() {
+ return true;
}
-bool SocketWriteFunction::RunImpl() {
+bool SocketWriteFunction::Prepare() {
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &message_));
-
- bool rv = BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&SocketWriteFunction::WorkOnIOThread, this));
- DCHECK(rv);
return true;
}
-void SocketWriteFunction::WorkOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- SocketController* controller = SocketController::GetInstance();
- int bytesWritten = controller->WriteUdp(socket_id_, message_);
+void SocketWriteFunction::Work() {
+ int bytesWritten = controller()->WriteUdp(socket_id_, message_);
DictionaryValue* result = new DictionaryValue();
result->SetInteger(kBytesWrittenKey, bytesWritten);
result_.reset(result);
- bool rv = BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SocketWriteFunction::RespondOnUIThread, this));
- DCHECK(rv);
}
-void SocketWriteFunction::RespondOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SendResponse(true);
+bool SocketWriteFunction::Respond() {
+ return true;
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/socket/socket_api.h b/chrome/browser/extensions/api/socket/socket_api.h
index d28c497..8d1a7a2 100644
--- a/chrome/browser/extensions/api/socket/socket_api.h
+++ b/chrome/browser/extensions/api/socket/socket_api.h
@@ -12,38 +12,52 @@
namespace extensions {
+class SocketController;
+
extern const char kBytesWrittenKey[];
extern const char kSocketIdKey[];
extern const char kUdpSocketType[];
+class SocketApiFunction : public AsyncExtensionFunction {
+ protected:
+ // Set up for work. Guaranteed to happen on UI thread.
+ virtual bool Prepare() = 0;
+
+ // Do actual work. Guaranteed to happen on IO thread.
+ virtual void Work() = 0;
+
+ // Respond. Guaranteed to happen on UI thread.
+ virtual bool Respond() = 0;
+
+ virtual bool RunImpl() OVERRIDE;
+
+ SocketController* controller();
+
+ private:
+ void WorkOnIOThread();
+ void RespondOnUIThread();
+};
+
// Many of these socket functions are synchronous in the sense that
// they don't involve blocking operations, but we've made them all
// AsyncExtensionFunctions because the underlying UDPClientSocket
// library wants all operations to happen on the same thread as the
// one that created the socket. Too bad.
-class SocketCreateFunction : public AsyncExtensionFunction {
- public:
- SocketCreateFunction();
- virtual ~SocketCreateFunction();
- virtual bool RunImpl() OVERRIDE;
-
+class SocketCreateFunction : public SocketApiFunction {
protected:
- void WorkOnIOThread();
- void RespondOnUIThread();
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+ virtual bool Respond() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("experimental.socket.create")
};
-class SocketDestroyFunction : public AsyncExtensionFunction {
- public:
- SocketDestroyFunction();
- virtual ~SocketDestroyFunction();
- virtual bool RunImpl() OVERRIDE;
-
+class SocketDestroyFunction : public SocketApiFunction {
protected:
- void WorkOnIOThread();
- void RespondOnUIThread();
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+ virtual bool Respond() OVERRIDE;
private:
int socket_id_;
@@ -51,15 +65,11 @@ class SocketDestroyFunction : public AsyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.socket.destroy")
};
-class SocketConnectFunction : public AsyncExtensionFunction {
- public:
- SocketConnectFunction();
- virtual ~SocketConnectFunction();
- virtual bool RunImpl() OVERRIDE;
-
+class SocketConnectFunction : public SocketApiFunction {
protected:
- void WorkOnIOThread();
- void RespondOnUIThread();
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+ virtual bool Respond() OVERRIDE;
private:
int socket_id_;
@@ -69,15 +79,11 @@ class SocketConnectFunction : public AsyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.socket.connect")
};
-class SocketCloseFunction : public AsyncExtensionFunction {
- public:
- SocketCloseFunction();
- virtual ~SocketCloseFunction();
- virtual bool RunImpl() OVERRIDE;
-
+class SocketCloseFunction : public SocketApiFunction {
protected:
- void WorkOnIOThread();
- void RespondOnUIThread();
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+ virtual bool Respond() OVERRIDE;
private:
int socket_id_;
@@ -85,16 +91,13 @@ class SocketCloseFunction : public AsyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.socket.close")
};
-class SocketWriteFunction : public AsyncExtensionFunction {
- public:
- SocketWriteFunction();
- virtual ~SocketWriteFunction();
- virtual bool RunImpl() OVERRIDE;
-
+class SocketWriteFunction : public SocketApiFunction {
protected:
- void WorkOnIOThread();
- void RespondOnUIThread();
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+ virtual bool Respond() OVERRIDE;
+ private:
int socket_id_;
std::string message_;
diff --git a/chrome/browser/extensions/api/socket/socket_api_controller.cc b/chrome/browser/extensions/api/socket/socket_api_controller.cc
index 2195297..8758719 100644
--- a/chrome/browser/extensions/api/socket/socket_api_controller.cc
+++ b/chrome/browser/extensions/api/socket/socket_api_controller.cc
@@ -22,8 +22,8 @@ namespace extensions {
// we need to manage it in the context of an extension.
class Socket {
public:
- explicit Socket(const Profile* profile, const std::string& src_extension_id,
- const GURL& src_url);
+ Socket(const Profile* profile, const std::string& src_extension_id,
+ const GURL& src_url);
~Socket();
bool Connect(const net::IPEndPoint& ip_end_point);
@@ -38,7 +38,7 @@ class Socket {
std::string src_extension_id_;
GURL src_url_;
- net::UDPClientSocket* udp_client_socket_;
+ scoped_ptr<net::UDPClientSocket> udp_client_socket_;
bool is_connected_;
net::OldCompletionCallbackImpl<Socket> io_callback_;
@@ -101,30 +101,25 @@ int Socket::Write(const std::string message) {
return bytes_sent;
}
-SocketController* SocketController::GetInstance() {
- return Singleton<SocketController>::get();
+SocketController::SocketController() : next_socket_id_(1) {
}
-SocketController::SocketController() : next_socket_id_(1) {}
-
-SocketController::~SocketController() {
- STLDeleteValues(&socket_map_);
-}
+SocketController::~SocketController() {}
Socket* SocketController::GetSocket(int socket_id) {
// TODO(miket): we should verify that the extension asking for the
// socket is the same one that created it.
SocketMap::iterator i = socket_map_.find(socket_id);
if (i != socket_map_.end())
- return i->second;
+ return i->second.get();
return NULL;
}
int SocketController::CreateUdp(const Profile* profile,
const std::string& extension_id,
const GURL& src_url) {
- Socket* socket = new Socket(profile, extension_id, src_url);
- CHECK(socket);
+ linked_ptr<Socket> socket(new Socket(profile, extension_id, src_url));
+ CHECK(socket.get());
socket_map_[next_socket_id_] = socket;
return next_socket_id_++;
}
diff --git a/chrome/browser/extensions/api/socket/socket_api_controller.h b/chrome/browser/extensions/api/socket/socket_api_controller.h
index f35b10a..ff50bc0 100644
--- a/chrome/browser/extensions/api/socket/socket_api_controller.h
+++ b/chrome/browser/extensions/api/socket/socket_api_controller.h
@@ -9,8 +9,8 @@
#include <string>
#include <map>
+#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/singleton.h"
#include "googleurl/src/gurl.h"
#include "net/base/completion_callback.h"
@@ -30,25 +30,19 @@ namespace extensions {
class Socket;
-// The SocketController singleton keeps track of all our Sockets, and provides
-// a convenient set of methods to manipulate them.
+// SocketController keeps track of a collection of Sockets and provides a
+// convenient set of methods to manipulate them.
class SocketController {
public:
- static SocketController* GetInstance();
-
SocketController();
virtual ~SocketController();
// Create/Destroy are a pair. They represent the allocation and deallocation
// of the Socket object in memory.
//
- // TODO(miket): we currently require the app developer to remember to call
- // Destroy, which is a buzzkill in JavaScript. I believe that to solve this,
- // we'll have to associate each Socket with a creator extension, and then
- // clean up when the extension goes out of scope. As the API is defined
- // today, we're exposing only primitive socketIds to JavaScript, which seems
- // to imply that we won't be able to garbage-collect when individual sockets
- // "go out of scope" (in quotes because they never do).
+ // TODO(miket): aa's suggestion to track lifetime of callbacks associated
+ // with each socket, which will then let us clean up when we go out of scope
+ // rather than requiring that the app developer remember to call Destroy.
int CreateUdp(const Profile* profile, const std::string& extension_id,
const GURL& src_url);
bool DestroyUdp(int socket_id);
@@ -68,14 +62,12 @@ class SocketController {
private:
int next_socket_id_;
- typedef std::map<int, Socket*> SocketMap;
+ typedef std::map<int, linked_ptr<Socket> > SocketMap;
SocketMap socket_map_;
// Convenience method for accessing SocketMap.
Socket* GetSocket(int socket_id);
- friend struct DefaultSingletonTraits<SocketController>;
-
DISALLOW_COPY_AND_ASSIGN(SocketController);
};
diff --git a/chrome/browser/extensions/api/socket/socket_api_controller_unittest.cc b/chrome/browser/extensions/api/socket/socket_api_controller_unittest.cc
index 97961e4..376b66d 100644
--- a/chrome/browser/extensions/api/socket/socket_api_controller_unittest.cc
+++ b/chrome/browser/extensions/api/socket/socket_api_controller_unittest.cc
@@ -4,6 +4,7 @@
#include "testing/gtest/include/gtest/gtest.h"
+#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/socket/socket_api.h"
#include "chrome/browser/extensions/api/socket/socket_api_controller.h"
@@ -16,7 +17,7 @@ class SocketApiControllerTest : public testing::Test {
TEST_F(SocketApiControllerTest, TestSocketControllerLifetime) {
// We want to make sure that killing the controller while a bunch of
// sockets are alive doesn't crash.
- SocketController* controller = SocketController::GetInstance();
+ scoped_ptr<SocketController> controller(new SocketController());
// Create some sockets but don't do anything with them.
Profile* profile = NULL;
@@ -36,16 +37,6 @@ TEST_F(SocketApiControllerTest, TestSocketControllerLifetime) {
ASSERT_TRUE(socket_id != 0);
ASSERT_TRUE(controller->ConnectUdp(socket_id, address, kPort));
}
-
- // At this point, we're done, and we're relying on the RAE mechanism
- // of the Singleton class to delete the controller at process exit.
- // We'd have to jump through some icky hoops to turn off RAE and
- // manually delete in this test method, so we'll instead take it on
- // faith that the singleton will indeed delete itself, and that if
- // we had any heap management problems in the controller, they'd
- // show up later in this test process. I (miket) hereby confirm that
- // I manually added a temporary double-free in the controller
- // destructor and verified that the unit_tests process segfaulted.
}
} // namespace extensions
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 3a6ff8b..094a028 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -21,6 +21,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/task.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
@@ -31,6 +32,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/download/download_extension_api.h"
+#include "chrome/browser/extensions/api/socket/socket_api_controller.h"
#include "chrome/browser/extensions/app_notification_manager.h"
#include "chrome/browser/extensions/apps_promo.h"
#include "chrome/browser/extensions/component_loader.h"
@@ -386,7 +388,8 @@ ExtensionService::ExtensionService(Profile* profile,
permissions_manager_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
apps_promo_(profile->GetPrefs()),
event_routers_initialized_(false),
- extension_warnings_(profile) {
+ extension_warnings_(profile),
+ socket_controller_(new extensions::SocketController()) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Figure out if extension installation should be enabled.
@@ -470,6 +473,13 @@ ExtensionService::~ExtensionService() {
ExternalExtensionProviderInterface* provider = i->get();
provider->ServiceShutdown();
}
+
+ // TODO(miket): if we find ourselves adding more and more per-API
+ // controllers, we should manage them all with an
+ // APIControllerController (still working on that name).
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ new DeleteTask<extensions::SocketController>(socket_controller_));
}
void ExtensionService::InitEventRoutersAfterImport() {
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 67b0f4d..1b288df 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -75,6 +75,7 @@ class ExtensionInputMethodEventRouter;
namespace extensions {
class ComponentLoader;
class SettingsFrontend;
+class SocketController;
}
// This is an interface class to encapsulate the dependencies that
@@ -569,6 +570,10 @@ class ExtensionService
return &extension_warnings_;
}
+ extensions::SocketController* socket_controller() {
+ return socket_controller_;
+ }
+
private:
// Bundle of type (app or extension)-specific sync stuff.
struct SyncBundle {
@@ -819,6 +824,10 @@ class ExtensionService
// Contains an entry for each warning that shall be currently shown.
ExtensionWarningSet extension_warnings_;
+ // We need to control destruction of this object (it needs to happen on the
+ // IO thread), so we don't get to use any RAII devices with it.
+ extensions::SocketController* socket_controller_;
+
extensions::ProcessMap process_map_;
FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,