summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-27 19:35:09 +0000
committermpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-27 19:35:09 +0000
commit81e6378c98d0e69339302527eb1de4735d1e2c3f (patch)
treed8020f1a2a842b0735c22a35e89a97ec7630bf17 /chrome/browser
parent4c8c60ee58cf2f22fcdc0cf3b30f1f5e8884f0ff (diff)
downloadchromium_src-81e6378c98d0e69339302527eb1de4735d1e2c3f.zip
chromium_src-81e6378c98d0e69339302527eb1de4735d1e2c3f.tar.gz
chromium_src-81e6378c98d0e69339302527eb1de4735d1e2c3f.tar.bz2
Prototype extension process. This is a proof of concept, with a lot of
rough edges. Mostly this just fires up a renderer with an "extension" object exposed, which right now only has a single method "getTestString". I also did some misc cleanup along the way. Review URL: http://codereview.chromium.org/27187 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10620 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.scons2
-rw-r--r--chrome/browser/browser.vcproj8
-rwxr-xr-xchrome/browser/extensions/extension_view.cc32
-rwxr-xr-xchrome/browser/extensions/extension_view.h46
-rwxr-xr-xchrome/browser/extensions/extension_view_unittest.cc108
-rw-r--r--chrome/browser/extensions/extensions_service.cc15
-rw-r--r--chrome/browser/extensions/extensions_service.h11
-rw-r--r--chrome/browser/profile.cc3
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc25
-rw-r--r--chrome/browser/renderer_host/render_view_host.h16
-rw-r--r--chrome/browser/tab_contents/interstitial_page.cc2
-rw-r--r--chrome/browser/views/hwnd_html_view.cc9
-rw-r--r--chrome/browser/views/hwnd_html_view.h14
13 files changed, 263 insertions, 28 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons
index 7e94112..ea53d85 100644
--- a/chrome/browser/browser.scons
+++ b/chrome/browser/browser.scons
@@ -506,6 +506,8 @@ input_files = ChromeFileList([
MSVSFilter('Extensions', [
'extensions/extension.cc',
'extensions/extension.h',
+ 'extensions/extension_view.cc',
+ 'extensions/extension_view.h',
'extensions/extension_error_reporter.cc',
'extensions/extension_error_reporter.h',
'extensions/extension_protocols.h',
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index e5995c1..6f1a886 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -1922,6 +1922,14 @@
>
</File>
<File
+ RelativePath=".\extensions\extension_view.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\extensions\extension_view.h"
+ >
+ </File>
+ <File
RelativePath=".\extensions\extensions_service.cc"
>
</File>
diff --git a/chrome/browser/extensions/extension_view.cc b/chrome/browser/extensions/extension_view.cc
new file mode 100755
index 0000000..1647ecb
--- /dev/null
+++ b/chrome/browser/extensions/extension_view.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2006-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_view.h"
+
+#include "chrome/browser/renderer_host/render_view_host.h"
+
+ExtensionView::ExtensionView(const GURL& url, Profile* profile) :
+ HWNDHtmlView(url, this, false), profile_(profile) {
+}
+
+void ExtensionView::CreatingRenderer() {
+ render_view_host()->AllowExtensionBindings();
+}
+
+WebPreferences ExtensionView::GetWebkitPrefs() {
+ // TODO(mpcomplete): return some reasonable prefs.
+ return WebPreferences();
+}
+
+void ExtensionView::RunJavaScriptMessage(
+ const std::wstring& message,
+ const std::wstring& default_prompt,
+ const int flags,
+ IPC::Message* reply_msg,
+ bool* did_suppress_message) {
+ // Automatically cancel the javascript alert (otherwise the renderer hangs
+ // indefinitely).
+ *did_suppress_message = true;
+ render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, L"");
+}
diff --git a/chrome/browser/extensions/extension_view.h b/chrome/browser/extensions/extension_view.h
new file mode 100755
index 0000000..5eb869c
--- /dev/null
+++ b/chrome/browser/extensions/extension_view.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2006-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_VIEW_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_VIEW_H_
+
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+
+// TODO(port): Port these files.
+#if defined(OS_WIN)
+#include "chrome/browser/views/hwnd_html_view.h"
+#else
+#include "chrome/common/temp_scaffolding_stubs.h"
+#endif
+
+class Profile;
+struct WebPreferences;
+
+// This class is the browser component of an extension component's RenderView.
+// It handles setting up the renderer process, if needed, with special
+// priviliges available to extensions. The view may be drawn to the screen or
+// hidden.
+class ExtensionView : public HWNDHtmlView,
+ public RenderViewHostDelegate {
+ public:
+ ExtensionView(const GURL& url, Profile* profile);
+
+ // HWNDHtmlView
+ virtual void CreatingRenderer();
+
+ // RenderViewHostDelegate
+ virtual Profile* GetProfile() const { return profile_; }
+ virtual WebPreferences GetWebkitPrefs();
+ virtual void RunJavaScriptMessage(
+ const std::wstring& message,
+ const std::wstring& default_prompt,
+ const int flags,
+ IPC::Message* reply_msg,
+ bool* did_suppress_message);
+
+ private:
+ Profile* profile_;
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_VIEW_H_
diff --git a/chrome/browser/extensions/extension_view_unittest.cc b/chrome/browser/extensions/extension_view_unittest.cc
new file mode 100755
index 0000000..930b068
--- /dev/null
+++ b/chrome/browser/extensions/extension_view_unittest.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2006-2008 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 "base/message_loop.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/extensions/extension_view.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+
+namespace {
+
+// How long to wait for the extension to put up a javascript alert before giving
+// up.
+const int kAlertTimeoutMs = 10000;
+
+// The extension we're using as our test case.
+const char* kExtensionId = "com.google.myextension1";
+
+// This class starts up an extension process and waits until it tries to put
+// up a javascript alert.
+class MockExtensionView : public ExtensionView {
+ public:
+ MockExtensionView(const GURL& url, Profile* profile)
+ : ExtensionView(url, profile), got_message_(false) {
+ InitHidden();
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ new MessageLoop::QuitTask, kAlertTimeoutMs);
+ ui_test_utils::RunMessageLoop();
+ }
+
+ bool got_message() { return got_message_; }
+ private:
+ virtual void RunJavaScriptMessage(
+ const std::wstring& message,
+ const std::wstring& default_prompt,
+ const int flags,
+ IPC::Message* reply_msg,
+ bool* did_suppress_message) {
+ got_message_ = true;
+ MessageLoopForUI::current()->Quit();
+ }
+
+ bool got_message_;
+};
+
+// This class waits for a specific extension to be loaded.
+class ExtensionLoadedObserver : public NotificationObserver {
+ public:
+ explicit ExtensionLoadedObserver() : extension_(NULL) {
+ registrar_.Add(this, NotificationType::EXTENSIONS_LOADED,
+ NotificationService::AllSources());
+ ui_test_utils::RunMessageLoop();
+ }
+
+ Extension* extension() { return extension_; }
+ private:
+ virtual void Observe(NotificationType type, const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::EXTENSIONS_LOADED) {
+ ExtensionList* extensions = Details<ExtensionList>(details).ptr();
+ for (size_t i = 0; i < (*extensions).size(); i++) {
+ if ((*extensions)[i]->id() == kExtensionId) {
+ extension_ = (*extensions)[i];
+ MessageLoopForUI::current()->Quit();
+ break;
+ }
+ }
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ NotificationRegistrar registrar_;
+ Extension* extension_;
+};
+
+} // namespace
+
+class ExtensionViewTest : public InProcessBrowserTest {
+};
+
+IN_PROC_BROWSER_TEST_F(ExtensionViewTest, TestMe) {
+ // Get the path to our extension.
+ FilePath path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("extensions").
+ AppendASCII("good").AppendASCII("extension1").AppendASCII("1");
+
+ // Load it.
+ Profile* profile = browser()->profile();
+ profile->GetExtensionsService()->Init();
+ profile->GetExtensionsService()->LoadExtension(path);
+
+ // Now wait for it to load, and grab a pointer to it.
+ Extension* extension = ExtensionLoadedObserver().extension();
+ ASSERT_TRUE(extension);
+ GURL url = Extension::GetResourceURL(extension->url(), "index.html");
+
+ // Start the extension process and wait for it to show a javascript alert.
+ MockExtensionView view(url, profile);
+ EXPECT_TRUE(view.got_message());
+}
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 9fc0040..3271920 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -16,7 +16,9 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/user_script_master.h"
+#include "chrome/browser/extensions/extension_view.h"
#include "chrome/browser/plugin_service.h"
+#include "chrome/browser/profile.h"
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/unzip.h"
@@ -63,12 +65,12 @@ const wchar_t kRegistryExtensionVersion[] = L"version";
const char kExternalInstallFile[] = "EXTERNAL_INSTALL";
}
-
-ExtensionsService::ExtensionsService(const FilePath& profile_directory,
+ExtensionsService::ExtensionsService(Profile* profile,
UserScriptMaster* user_script_master)
: message_loop_(MessageLoop::current()),
backend_(new ExtensionsServiceBackend),
- install_directory_(profile_directory.AppendASCII(kInstallDirectoryName)),
+ install_directory_(profile->GetPath().AppendASCII(kInstallDirectoryName)),
+ profile_(profile),
user_script_master_(user_script_master) {
}
@@ -104,6 +106,13 @@ bool ExtensionsService::Init() {
return true;
}
+void ExtensionsService::LaunchExtensionProcess(Extension* extension) {
+ // TODO(mpcomplete): Do something useful here.
+ GURL url = Extension::GetResourceURL(extension->url(), "index.html");
+ ExtensionView* view = new ExtensionView(url, profile_);
+ view->InitHidden();
+}
+
MessageLoop* ExtensionsService::GetMessageLoop() {
return message_loop_;
}
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index efba0086..7489de7 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -16,6 +16,7 @@
typedef std::vector<Extension*> ExtensionList;
class ExtensionsServiceBackend;
+class Profile;
class UserScriptMaster;
// Interface for the frontend to implement. Typically, this will be
@@ -51,8 +52,7 @@ class ExtensionsServiceFrontendInterface
// Manages installed and running Chromium extensions.
class ExtensionsService : public ExtensionsServiceFrontendInterface {
public:
- ExtensionsService(const FilePath& profile_directory,
- UserScriptMaster* user_script_master);
+ ExtensionsService(Profile* profile, UserScriptMaster* user_script_master);
~ExtensionsService();
// Gets the list of currently installed extensions.
@@ -63,6 +63,10 @@ class ExtensionsService : public ExtensionsServiceFrontendInterface {
// Initialize and start all installed extensions.
bool Init();
+ // Start the extension process for this extension. TODO(mpcomplete): not sure
+ // how this should actually work yet.
+ void LaunchExtensionProcess(Extension* extension);
+
// ExtensionsServiceFrontendInterface
virtual MessageLoop* GetMessageLoop();
virtual void InstallExtension(const FilePath& extension_path);
@@ -90,6 +94,9 @@ class ExtensionsService : public ExtensionsServiceFrontendInterface {
// The full path to the directory where extensions are installed.
FilePath install_directory_;
+ // The profile associated with this set of extensions.
+ Profile* profile_;
+
// The user script master for this profile.
scoped_refptr<UserScriptMaster> user_script_master_;
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 9600c6c..7c7041e 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -371,8 +371,7 @@ void ProfileImpl::InitExtensions() {
ExtensionErrorReporter::Init(true); // allow noisy errors.
user_script_master_ = new UserScriptMaster(
g_browser_process->file_thread()->message_loop(), script_dir);
- extensions_service_ = new ExtensionsService(
- FilePath(GetPath()), user_script_master_.get());
+ extensions_service_ = new ExtensionsService(this, user_script_master_.get());
// If we have extensions, the extension service will kick off the first scan
// after extensions are loaded. Otherwise, we need to do that now.
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 894e02a..3da3fef 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/common/bindings_policy.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/notification_service.h"
@@ -88,9 +89,8 @@ RenderViewHost::RenderViewHost(SiteInstance* instance,
renderer_initialized_(false),
waiting_for_drag_context_response_(false),
debugger_attached_(false),
- enable_dom_ui_bindings_(false),
+ enabled_bindings_(0),
pending_request_id_(0),
- enable_external_host_bindings_(false),
modal_dialog_count_(0),
navigations_suspended_(false),
suspended_nav_message_(NULL),
@@ -178,8 +178,7 @@ bool RenderViewHost::CreateRenderView() {
// If it's enabled, tell the renderer to set up the Javascript bindings for
// sending messages back to the browser.
- Send(new ViewMsg_AllowBindings(
- routing_id(), enable_dom_ui_bindings_, enable_external_host_bindings_));
+ Send(new ViewMsg_AllowBindings(routing_id(), enabled_bindings_));
// Let our delegate know that we created a RenderView.
delegate_->RenderViewCreated(this);
@@ -574,24 +573,30 @@ void RenderViewHost::DragSourceSystemDragEnded() {
}
void RenderViewHost::AllowDomAutomationBindings() {
- // Expose the binding that allows the DOM to send messages here.
- Send(new ViewMsg_AllowDomAutomationBindings(routing_id(), true));
+ DCHECK(!renderer_initialized_);
+ enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
+}
+
+void RenderViewHost::AllowExternalHostBindings() {
+ DCHECK(!renderer_initialized_);
+ enabled_bindings_ |= BindingsPolicy::EXTERNAL_HOST;
}
void RenderViewHost::AllowDOMUIBindings() {
DCHECK(!renderer_initialized_);
- enable_dom_ui_bindings_ = true;
+ enabled_bindings_ |= BindingsPolicy::DOM_UI;
RendererSecurityPolicy::GetInstance()->GrantDOMUIBindings(
process()->host_id());
}
-void RenderViewHost::AllowExternalHostBindings() {
- enable_external_host_bindings_ = true;
+void RenderViewHost::AllowExtensionBindings() {
+ DCHECK(!renderer_initialized_);
+ enabled_bindings_ |= BindingsPolicy::EXTENSION;
}
void RenderViewHost::SetDOMUIProperty(const std::string& name,
const std::string& value) {
- DCHECK(enable_dom_ui_bindings_);
+ DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
Send(new ViewMsg_SetDOMUIProperty(routing_id(), name, value));
}
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 7a0a8148..79c9ca6 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -308,10 +308,12 @@ class RenderViewHost : public RenderWidgetHost {
// Tell the render view to expose DOM automation bindings so that the js
// content can send JSON-encoded data back to automation in the parent
// process.
+ // Must be called before CreateRenderView().
void AllowDomAutomationBindings();
// Tell the render view to allow the javascript access to
// the external host via automation.
+ // Must be called before CreateRenderView().
void AllowExternalHostBindings();
// Tell the render view to expose DOM bindings so that the JS content
@@ -320,6 +322,10 @@ class RenderViewHost : public RenderWidgetHost {
// Must be called before CreateRenderView().
void AllowDOMUIBindings();
+ // Tell the render view to expose privileged bindings for use by extensions.
+ // Must be called before CreateRenderView().
+ void AllowExtensionBindings();
+
// Tells the renderer which render view should be inspected by developer
// tools loaded in it. This method should be called before renderer is
// created.
@@ -574,9 +580,9 @@ class RenderViewHost : public RenderWidgetHost {
// is the debugger attached to us or not
bool debugger_attached_;
- // True if we've been told to set up the the Javascript bindings for
- // sending messages back to the browser.
- bool enable_dom_ui_bindings_;
+ // A bitwise OR of bindings types that have been enabled for this RenderView.
+ // See BindingsPolicy for details.
+ int enabled_bindings_;
// The request_id for the pending cross-site request. Set to -1 if
// there is a pending request, but we have not yet started the unload
@@ -585,10 +591,6 @@ class RenderViewHost : public RenderWidgetHost {
// and thus started the unload process.
int pending_request_id_;
- // True if javascript access to the external host (through
- // automation) is allowed.
- bool enable_external_host_bindings_;
-
// Handle to an event that's set when the page is showing a modal dialog box
// (or equivalent constrained window). The renderer and plugin processes
// check this to know if they should pump messages/tasks then.
diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc
index 9781a0e..688c6f1 100644
--- a/chrome/browser/tab_contents/interstitial_page.cc
+++ b/chrome/browser/tab_contents/interstitial_page.cc
@@ -256,11 +256,11 @@ RenderViewHost* InterstitialPage::CreateRenderViewHost() {
view->set_parent_hwnd(tab_->GetContentNativeView());
WebContentsViewWin* web_contents_view =
static_cast<WebContentsViewWin*>(tab_->view());
+ render_view_host->AllowDomAutomationBindings();
render_view_host->CreateRenderView();
// SetSize must be called after CreateRenderView or the HWND won't show.
view->SetSize(web_contents_view->GetContainerSize());
- render_view_host->AllowDomAutomationBindings();
return render_view_host;
#else
// TODO(port): RenderWidgetHost* is implemented, but Create and
diff --git a/chrome/browser/views/hwnd_html_view.cc b/chrome/browser/views/hwnd_html_view.cc
index 7b7fbfc..000d92b 100644
--- a/chrome/browser/views/hwnd_html_view.cc
+++ b/chrome/browser/views/hwnd_html_view.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/views/widget.h"
+#include "chrome/views/widget_win.h"
HWNDHtmlView::~HWNDHtmlView() {
if (render_view_host_) {
@@ -18,6 +19,13 @@ HWNDHtmlView::~HWNDHtmlView() {
}
}
+void HWNDHtmlView::InitHidden() {
+ // TODO(mpcomplete): make it possible to create a RenderView without an HWND.
+ views::WidgetWin* win = new views::WidgetWin;
+ win->Init(NULL, gfx::Rect(), true);
+ win->SetContentsView(this);
+}
+
void HWNDHtmlView::Init(HWND parent_hwnd) {
DCHECK(!render_view_host_) << "Already initialized.";
RenderViewHost* rvh = new RenderViewHost(
@@ -40,6 +48,7 @@ void HWNDHtmlView::Init(HWND parent_hwnd) {
// Start up the renderer.
if (allow_dom_ui_bindings_)
rvh->AllowDOMUIBindings();
+ CreatingRenderer();
rvh->CreateRenderView();
rvh->NavigateToURL(content_url_);
initialized_ = true;
diff --git a/chrome/browser/views/hwnd_html_view.h b/chrome/browser/views/hwnd_html_view.h
index 4405f2a..67952a2 100644
--- a/chrome/browser/views/hwnd_html_view.h
+++ b/chrome/browser/views/hwnd_html_view.h
@@ -28,14 +28,22 @@ class HWNDHtmlView : public views::HWNDView {
RenderViewHost* render_view_host() { return render_view_host_; }
+ // Initialize the view without a parent window. Used for extensions that
+ // don't display UI.
+ void InitHidden();
+
protected:
- // View overrides.
- virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
+ // View overrides.
+ virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
+
+ // Called just before we create the RenderView, to give subclasses an
+ // opportunity to do some setup.
+ virtual void CreatingRenderer() {}
private:
// Initialize the view, parented to |parent|, and show it.
void Init(HWND parent);
-
+
// The URL of the HTML content to render and show in this view.
GURL content_url_;