summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser.vcproj8
-rwxr-xr-xchrome/browser/extensions/extension_message_service.cc35
-rwxr-xr-xchrome/browser/extensions/extension_message_service.h5
-rwxr-xr-xchrome/browser/extensions/extension_process_manager.cc42
-rwxr-xr-xchrome/browser/extensions/extension_process_manager.h54
-rwxr-xr-xchrome/browser/extensions/extension_process_manager_unittest.cc42
-rwxr-xr-xchrome/browser/extensions/extension_view.cc11
-rwxr-xr-xchrome/browser/extensions/extension_view.h9
-rwxr-xr-xchrome/browser/extensions/extension_view_unittest.cc11
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc10
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc4
-rw-r--r--chrome/browser/views/hwnd_html_view.cc16
-rw-r--r--chrome/browser/views/hwnd_html_view.h12
-rw-r--r--chrome/chrome.gyp3
-rw-r--r--chrome/common/temp_scaffolding_stubs.h2
-rw-r--r--chrome/test/unit/unittests.vcproj4
16 files changed, 232 insertions, 36 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index 5e7cfbe..cf27ee4 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -1934,6 +1934,14 @@
>
</File>
<File
+ RelativePath=".\extensions\extension_process_manager.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\extensions\extension_process_manager.h"
+ >
+ </File>
+ <File
RelativePath=".\extensions\extension_protocols.cc"
>
</File>
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index 87469f9..ef2530a 100755
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -12,19 +12,41 @@
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/resource_message_filter.h"
#include "chrome/common/render_messages.h"
+#include "chrome/common/stl_util-inl.h"
// Since we have 2 ports for every channel, we just index channels by half the
// port ID.
-#define GET_CHANNEL_ID(port_id) (port_id / 2)
+#define GET_CHANNEL_ID(port_id) ((port_id) / 2)
// Port1 is always even, port2 is always odd.
-#define IS_PORT1_ID(port_id) ((port_id & 1) == 0)
+#define IS_PORT1_ID(port_id) (((port_id) & 1) == 0)
// Change even to odd and vice versa, to get the other side of a given channel.
-#define GET_OPPOSITE_PORT_ID(source_port_id) (source_port_id ^ 1)
+#define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1)
-ExtensionMessageService* ExtensionMessageService::GetInstance() {
- return Singleton<ExtensionMessageService>::get();
+namespace {
+typedef std::map<URLRequestContext*, ExtensionMessageService*> InstanceMap;
+struct SingletonData {
+ ~SingletonData() {
+ STLDeleteContainerPairSecondPointers(map.begin(), map.end());
+ }
+ Lock lock;
+ InstanceMap map;
+};
+} // namespace
+
+// static
+ExtensionMessageService* ExtensionMessageService::GetInstance(
+ URLRequestContext* context) {
+ SingletonData* data = Singleton<SingletonData>::get();
+ AutoLock lock(data->lock);
+
+ ExtensionMessageService* instance = data->map[context];
+ if (!instance) {
+ instance = new ExtensionMessageService();
+ data->map[context] = instance;
+ }
+ return instance;
}
ExtensionMessageService::ExtensionMessageService()
@@ -37,7 +59,8 @@ void ExtensionMessageService::RegisterExtension(
// TODO(mpcomplete): We need to ensure an extension always ends up in a single
// process. I think this means having an ExtensionProcessManager which holds
// a BrowsingContext for each extension.
- //DCHECK(process_ids_.find(extension_id) == process_ids_.end());
+ DCHECK(process_ids_.find(extension_id) == process_ids_.end() ||
+ process_ids_[extension_id] == render_process_id);
process_ids_[extension_id] = render_process_id;
}
diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h
index 0020a30..a63837a 100755
--- a/chrome/browser/extensions/extension_message_service.h
+++ b/chrome/browser/extensions/extension_message_service.h
@@ -12,6 +12,7 @@
class ExtensionView;
class ResourceMessageFilter;
+class URLRequestContext;
// This class manages message passing between renderer processes. It maintains
// a list of available extensions and which renderers each lives in, as well as
@@ -24,7 +25,9 @@ class ResourceMessageFilter;
// messages on the IO thread.
class ExtensionMessageService {
public:
- static ExtensionMessageService* GetInstance();
+ // Returns the message service for the given context. Messages can only
+ // be sent within a single context.
+ static ExtensionMessageService* GetInstance(URLRequestContext* context);
ExtensionMessageService();
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
new file mode 100755
index 0000000..245450c
--- /dev/null
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2009 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/extension_process_manager.h"
+
+#include "base/singleton.h"
+#include "chrome/browser/extensions/extension_view.h"
+#include "chrome/browser/tab_contents/site_instance.h"
+
+// static
+ExtensionProcessManager* ExtensionProcessManager::GetInstance() {
+ return Singleton<ExtensionProcessManager>::get();
+}
+
+ExtensionProcessManager::ExtensionProcessManager() {
+}
+
+ExtensionProcessManager::~ExtensionProcessManager() {
+}
+
+ExtensionView* ExtensionProcessManager::CreateView(Extension* extension,
+ const GURL& url,
+ Profile* profile) {
+ return new ExtensionView(extension, url, GetSiteInstanceForURL(url, profile));
+}
+
+SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(
+ const GURL& url, Profile* profile) {
+ BrowsingInstance* browsing_instance = GetBrowsingInstance(profile);
+ return browsing_instance->GetSiteInstanceForURL(url);
+}
+
+BrowsingInstance* ExtensionProcessManager::GetBrowsingInstance(
+ Profile* profile) {
+ BrowsingInstance* instance = browsing_instance_map_[profile];
+ if (!instance) {
+ instance = new BrowsingInstance(profile);
+ browsing_instance_map_[profile] = instance;
+ }
+ return instance;
+}
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
new file mode 100755
index 0000000..0d4048b
--- /dev/null
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2009 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_EXTENSION_PROCESS_MANAGER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PROCESS_MANAGER_H_
+
+#include "base/ref_counted.h"
+
+#include <map>
+
+class BrowsingInstance;
+class Extension;
+class ExtensionView;
+class GURL;
+class Profile;
+class SiteInstance;
+
+// This class controls what process new extension instances use. We use the
+// BrowsingInstance site grouping rules to group extensions. Since all
+// resources in a given extension have the same origin, they will be grouped
+// into the same process.
+//
+// We separate further by Profile: each Profile has its own group of extension
+// processes that never overlap with other Profiles.
+class ExtensionProcessManager {
+ public:
+ static ExtensionProcessManager* GetInstance();
+
+ // These are public for use by Singleton. Do not instantiate or delete
+ // manually.
+ ExtensionProcessManager();
+ ~ExtensionProcessManager();
+
+ // Creates a new ExtensionView, grouping it in the appropriate SiteInstance
+ // (and therefore process) based on the URL and profile.
+ ExtensionView* CreateView(Extension* extension,
+ const GURL& url,
+ Profile* profile);
+
+ // Returns the SiteInstance that the given URL belongs to in this profile.
+ SiteInstance* GetSiteInstanceForURL(const GURL& url, Profile* profile);
+ private:
+ // Returns our BrowsingInstance for the given profile. Lazily created and
+ // cached.
+ BrowsingInstance* GetBrowsingInstance(Profile* profile);
+
+ // Cache of BrowsingInstances grouped by Profile.
+ typedef std::map<Profile*, scoped_refptr<BrowsingInstance> >
+ BrowsingInstanceMap;
+ BrowsingInstanceMap browsing_instance_map_;
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_PROCESS_MANAGER_H_
diff --git a/chrome/browser/extensions/extension_process_manager_unittest.cc b/chrome/browser/extensions/extension_process_manager_unittest.cc
new file mode 100755
index 0000000..ae43367
--- /dev/null
+++ b/chrome/browser/extensions/extension_process_manager_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2009 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 "testing/gtest/include/gtest/gtest.h"
+
+#include "chrome/test/testing_profile.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/tab_contents/site_instance.h"
+
+class ExtensionProcessManagerTest : public testing::Test {
+};
+
+// Test that extensions get grouped in the right SiteInstance (and therefore
+// process) based on their URLs.
+TEST(ExtensionProcessManagerTest, ProcessGrouping) {
+ ExtensionProcessManager* manager = ExtensionProcessManager::GetInstance();
+
+ // Extensions in different profiles should always be different SiteInstances.
+ TestingProfile profile1(1);
+ TestingProfile profile2(2);
+
+ // Extensions with common origins ("scheme://id/") should be grouped in the
+ // same SiteInstance.
+ GURL ext1_url1("chrome-extensions://ext1_id/index.html");
+ GURL ext1_url2("chrome-extensions://ext1_id/toolstrips/toolstrip.html");
+ GURL ext2_url1("chrome-extensions://ext2_id/index.html");
+
+ scoped_refptr<SiteInstance> site11 =
+ manager->GetSiteInstanceForURL(ext1_url1, &profile1);
+ scoped_refptr<SiteInstance> site12 =
+ manager->GetSiteInstanceForURL(ext1_url2, &profile1);
+ EXPECT_EQ(site11, site12);
+
+ scoped_refptr<SiteInstance> site21 =
+ manager->GetSiteInstanceForURL(ext2_url1, &profile1);
+ EXPECT_NE(site11, site21);
+
+ scoped_refptr<SiteInstance> other_profile_site =
+ manager->GetSiteInstanceForURL(ext1_url1, &profile2);
+ EXPECT_NE(site11, other_profile_site);
+}
diff --git a/chrome/browser/extensions/extension_view.cc b/chrome/browser/extensions/extension_view.cc
index 11c33cf..969a046 100755
--- a/chrome/browser/extensions/extension_view.cc
+++ b/chrome/browser/extensions/extension_view.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/extensions/extension.h"
#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/resource_bundle.h"
@@ -15,10 +16,9 @@
ExtensionView::ExtensionView(Extension* extension,
const GURL& url,
- Profile* profile)
- : HWNDHtmlView(url, this, false),
- extension_(extension),
- profile_(profile) {
+ SiteInstance* instance)
+ : HWNDHtmlView(url, this, false, instance),
+ extension_(extension) {
// Set the width initially to 0, so that the WebCore::Document can
// correctly compute the minPrefWidth which is returned in
// DidContentsChangeSize()
@@ -58,7 +58,8 @@ void ExtensionView::CreatingRenderer() {
}
void ExtensionView::RenderViewCreated(RenderViewHost* rvh) {
- ExtensionMessageService::GetInstance()->RegisterExtension(
+ URLRequestContext* context = rvh->process()->profile()->GetRequestContext();
+ ExtensionMessageService::GetInstance(context)->RegisterExtension(
extension_->id(), render_view_host()->process()->pid());
}
diff --git a/chrome/browser/extensions/extension_view.h b/chrome/browser/extensions/extension_view.h
index 960a294..09c7788 100755
--- a/chrome/browser/extensions/extension_view.h
+++ b/chrome/browser/extensions/extension_view.h
@@ -15,7 +15,6 @@
#endif
class Extension;
-class Profile;
struct WebPreferences;
// This class is the browser component of an extension component's RenderView.
@@ -25,13 +24,14 @@ struct WebPreferences;
class ExtensionView : public HWNDHtmlView,
public RenderViewHostDelegate {
public:
- ExtensionView(Extension* extension, const GURL& url, Profile* profile);
+ ExtensionView(Extension* extension, const GURL& url, SiteInstance* instance);
// HWNDHtmlView
virtual void CreatingRenderer();
// RenderViewHostDelegate
- virtual Profile* GetProfile() const { return profile_; }
+ // TODO(mpcomplete): GetProfile is unused.
+ virtual Profile* GetProfile() const { return NULL; }
virtual void RenderViewCreated(RenderViewHost* render_view_host);
virtual void DidContentsPreferredWidthChange(const int pref_width);
virtual void DidStopLoading(RenderViewHost* render_view_host,
@@ -52,9 +52,6 @@ class ExtensionView : public HWNDHtmlView,
// The extension that we're hosting in this view.
Extension* extension_;
- // The profile that owns this extension.
- Profile* profile_;
-
DISALLOW_COPY_AND_ASSIGN(ExtensionView);
};
diff --git a/chrome/browser/extensions/extension_view_unittest.cc b/chrome/browser/extensions/extension_view_unittest.cc
index 69a1fb9..d3d52bf 100755
--- a/chrome/browser/extensions/extension_view_unittest.cc
+++ b/chrome/browser/extensions/extension_view_unittest.cc
@@ -6,9 +6,11 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_view.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/test_extension_loader.h"
+#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
@@ -28,8 +30,9 @@ const char* kExtensionId = "00123456789abcdef0123456789abcdef0123456";
// up a javascript alert.
class MockExtensionView : public ExtensionView {
public:
- MockExtensionView(Extension* extension, const GURL& url, Profile* profile)
- : ExtensionView(extension, url, profile), got_message_(false) {
+ MockExtensionView(Extension* extension, const GURL& url,
+ SiteInstance* instance)
+ : ExtensionView(extension, url, instance), got_message_(false) {
InitHidden();
MessageLoop::current()->PostDelayedTask(FROM_HERE,
new MessageLoop::QuitTask, kAlertTimeoutMs);
@@ -88,6 +91,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionViewTest, Index) {
GURL url = Extension::GetResourceURL(extension->url(), "toolstrip1.html");
// Start the extension process and wait for it to show a javascript alert.
- MockExtensionView view(extension, url, browser()->profile());
+ MockExtensionView view(
+ extension, url, ExtensionProcessManager::GetInstance()->
+ GetSiteInstanceForURL(url, browser()->profile()));
EXPECT_TRUE(view.got_message());
}
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index bd61cc7..1230f56 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -140,7 +140,8 @@ ResourceMessageFilter::ResourceMessageFilter(
ResourceMessageFilter::~ResourceMessageFilter() {
WorkerService::GetInstance()->RendererShutdown(this);
- ExtensionMessageService::GetInstance()->RendererShutdown(this);
+ ExtensionMessageService::GetInstance(request_context_.get())->
+ RendererShutdown(this);
if (handle())
base::CloseProcessHandle(handle());
@@ -158,7 +159,8 @@ void ResourceMessageFilter::Init(int render_process_id) {
render_process_id_ = render_process_id;
render_widget_helper_->Init(render_process_id, resource_dispatcher_host_);
app_cache_dispatcher_host_->Initialize(this);
- ExtensionMessageService::GetInstance()->RendererReady(this);
+ ExtensionMessageService::GetInstance(request_context_.get())->
+ RendererReady(this);
}
// Called on the IPC thread:
@@ -777,12 +779,12 @@ void ResourceMessageFilter::OnFreeTransportDIB(
void ResourceMessageFilter::OnOpenChannelToExtension(
const std::string& extension_id, int* port_id) {
- *port_id = ExtensionMessageService::GetInstance()->
+ *port_id = ExtensionMessageService::GetInstance(request_context_.get())->
OpenChannelToExtension(extension_id, this);
}
void ResourceMessageFilter::OnExtensionPostMessage(
int port_id, const std::string& message) {
- ExtensionMessageService::GetInstance()->
+ ExtensionMessageService::GetInstance(request_context_.get())->
PostMessageFromRenderer(port_id, message, this);
}
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index 36eaa3d..2c41482 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/drag_utils.h"
#include "chrome/browser/extensions/extension.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_view.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/metrics/user_metrics.h"
@@ -300,7 +301,8 @@ class ExtensionToolstrip : public views::View {
static const int kPadding = 2;
ExtensionToolstrip(Extension* extension, const GURL& url, Profile* profile)
- : view_(new ExtensionView(extension, url, profile)) {
+ : view_(ExtensionProcessManager::GetInstance()->CreateView(
+ extension, url, profile)) {
AddChildView(view_);
set_border(views::Border::CreateEmptyBorder(
kPadding, kPadding, kPadding, kPadding));
diff --git a/chrome/browser/views/hwnd_html_view.cc b/chrome/browser/views/hwnd_html_view.cc
index 95c98f9..9eb8cc4 100644
--- a/chrome/browser/views/hwnd_html_view.cc
+++ b/chrome/browser/views/hwnd_html_view.cc
@@ -11,6 +11,19 @@
#include "chrome/views/widget/widget.h"
#include "chrome/views/widget/widget_win.h"
+HWNDHtmlView::HWNDHtmlView(const GURL& content_url,
+ RenderViewHostDelegate* delegate,
+ bool allow_dom_ui_bindings, SiteInstance* instance)
+ : render_view_host_(NULL),
+ content_url_(content_url),
+ allow_dom_ui_bindings_(allow_dom_ui_bindings),
+ delegate_(delegate),
+ initialized_(false),
+ site_instance_(instance) {
+ if (!site_instance_)
+ site_instance_ = SiteInstance::CreateSiteInstance(delegate_->GetProfile());
+}
+
HWNDHtmlView::~HWNDHtmlView() {
if (render_view_host_) {
Detach();
@@ -29,8 +42,7 @@ void HWNDHtmlView::InitHidden() {
void HWNDHtmlView::Init(HWND parent_hwnd) {
DCHECK(!render_view_host_) << "Already initialized.";
RenderViewHost* rvh = new RenderViewHost(
- SiteInstance::CreateSiteInstance(delegate_->GetProfile()),
- delegate_, MSG_ROUTING_NONE, NULL);
+ site_instance_, delegate_, MSG_ROUTING_NONE, NULL);
render_view_host_ = rvh;
RenderWidgetHostViewWin* view = new RenderWidgetHostViewWin(rvh);
diff --git a/chrome/browser/views/hwnd_html_view.h b/chrome/browser/views/hwnd_html_view.h
index b4a0d6a..9a55496 100644
--- a/chrome/browser/views/hwnd_html_view.h
+++ b/chrome/browser/views/hwnd_html_view.h
@@ -10,6 +10,7 @@
class RenderViewHost;
class RenderViewHostDelegate;
+class SiteInstance;
// A simple view that wraps a RenderViewHost in an HWNDView to facilitate
// rendering HTML as arbitrary browser views.
@@ -17,13 +18,7 @@ class RenderViewHostDelegate;
class HWNDHtmlView : public views::HWNDView {
public:
HWNDHtmlView(const GURL& content_url, RenderViewHostDelegate* delegate,
- bool allow_dom_ui_bindings)
- : render_view_host_(NULL),
- content_url_(content_url),
- allow_dom_ui_bindings_(allow_dom_ui_bindings),
- delegate_(delegate),
- initialized_(false) {
- }
+ bool allow_dom_ui_bindings, SiteInstance* instance);
virtual ~HWNDHtmlView();
RenderViewHost* render_view_host() { return render_view_host_; }
@@ -50,6 +45,9 @@ class HWNDHtmlView : public views::HWNDView {
// Our HTML rendering component.
RenderViewHost* render_view_host_;
+ // The site instance that the renderer belongs to.
+ SiteInstance* site_instance_;
+
// Whether or not the rendered content is permitted to send messages back to
// the view, through |delegate_| via ProcessDOMUIMessage.
bool allow_dom_ui_bindings_;
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 0b76044..b3c4afb 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -655,6 +655,8 @@
'browser/extensions/extension_function_dispatcher.h',
'browser/extensions/extension_message_service.cc',
'browser/extensions/extension_message_service.h',
+ 'browser/extensions/extension_process_manager.cc',
+ 'browser/extensions/extension_process_manager.h',
'browser/extensions/extension_protocols.cc',
'browser/extensions/extension_protocols.h',
'browser/extensions/extension_tabs_module.cc',
@@ -2102,6 +2104,7 @@
'browser/download/download_request_manager_unittest.cc',
'browser/download/save_package_unittest.cc',
'browser/extensions/extension_content_script_inject_unittest.cc',
+ 'browser/extensions/extension_process_manager_unittest.cc',
'browser/extensions/extension_ui_unittest.cc',
'browser/extensions/extension_unittest.cc',
'browser/extensions/extensions_service_unittest.cc',
diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h
index d5359a9..f73eb3f 100644
--- a/chrome/common/temp_scaffolding_stubs.h
+++ b/chrome/common/temp_scaffolding_stubs.h
@@ -539,7 +539,7 @@ class BaseDragSource {
class HWNDHtmlView {
public:
HWNDHtmlView(const GURL& content_url, RenderViewHostDelegate* delegate,
- bool allow_dom_ui_bindings) {
+ bool allow_dom_ui_bindings, SiteInstance* instance) {
NOTIMPLEMENTED();
}
virtual ~HWNDHtmlView() {}
diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj
index fb35266..2bf265e 100644
--- a/chrome/test/unit/unittests.vcproj
+++ b/chrome/test/unit/unittests.vcproj
@@ -476,6 +476,10 @@
>
</File>
<File
+ RelativePath="..\..\browser\extensions\extension_process_manager_unittest.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\browser\extensions\extension_content_script_inject_unittest.cc"
>
</File>