Commit c6463165 authored by mpcomplete@google.com's avatar mpcomplete@google.com

Refactor ExtensionView to support a UI-less extension instance.

- Introduce ExtensionHost, which is the guy that talks to the RenderViewHost.
- ExtensionView holds an ExtensionHost, and also renders its contents in an
  HWND.
- Added code to load a page optionally specified in the manifest as a
  background process whenever it exists.
Review URL: http://codereview.chromium.org/92043

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14902 0039d316-1c4b-4281-b951-d872f2087c98
parent 45671618
......@@ -1957,6 +1957,14 @@
RelativePath=".\extensions\extension_function_dispatcher.h"
>
</File>
<File
RelativePath=".\extensions\extension_host.cc"
>
</File>
<File
RelativePath=".\extensions\extension_host.h"
>
</File>
<File
RelativePath=".\extensions\extension_message_service.cc"
>
......
......@@ -222,6 +222,23 @@ Browser* BrowserList::FindBrowserWithType(Profile* p, Browser::Type t) {
return NULL;
}
// static
Browser* BrowserList::FindBrowserWithProfile(Profile* p) {
Browser* last_active = GetLastActive();
if (last_active && last_active->profile() == p)
return last_active;
BrowserList::const_iterator i;
for (i = BrowserList::begin(); i != BrowserList::end(); ++i) {
if (*i == last_active)
continue;
if ((*i)->profile() == p)
return *i;
}
return NULL;
}
// static
Browser* BrowserList::FindBrowserWithID(SessionID::id_type desired_id) {
BrowserList::const_iterator i;
......
......@@ -59,6 +59,11 @@ class BrowserList {
// is returned. Returns NULL if no such browser currently exists.
static Browser* FindBrowserWithType(Profile* p, Browser::Type t);
// Find an existing browser window with the provided profile. If the last
// active has the right profile, it is returned. Returns NULL if no such
// browser currently exists.
static Browser* FindBrowserWithProfile(Profile* p);
// Find an existing browser with the provided ID. Returns NULL if no such
// browser currently exists.
static Browser* FindBrowserWithID(SessionID::id_type desired_id);
......
......@@ -24,6 +24,7 @@ const wchar_t* Extension::kMatchesKey = L"matches";
const wchar_t* Extension::kNameKey = L"name";
const wchar_t* Extension::kPermissionsKey = L"permissions";
const wchar_t* Extension::kPluginsDirKey = L"plugins_dir";
const wchar_t* Extension::kBackgroundKey = L"background";
const wchar_t* Extension::kRunAtKey = L"run_at";
const wchar_t* Extension::kThemeKey = L"theme";
const wchar_t* Extension::kToolstripsKey = L"toolstrips";
......@@ -75,6 +76,8 @@ const char* Extension::kInvalidPermissionSchemeError =
"allowed.";
const char* Extension::kInvalidPluginsDirError =
"Invalid value for 'plugins_dir'.";
const char* Extension::kInvalidBackgroundError =
"Invalid value for 'background'.";
const char* Extension::kInvalidRunAtError =
"Invalid value for 'content_scripts[*].run_at'.";
const char* Extension::kInvalidToolstripError =
......@@ -403,6 +406,16 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
plugins_dir_ = path_.AppendASCII(plugins_dir);
}
// Initialize background url (optional).
if (source.HasKey(kBackgroundKey)) {
std::string background_str;
if (!source.GetString(kBackgroundKey, &background_str)) {
*error = kInvalidBackgroundError;
return false;
}
background_url_ = GetResourceURL(background_str);
}
// Initialize toolstrips (optional).
if (source.HasKey(kToolstripsKey)) {
ListValue* list_value;
......
......@@ -38,6 +38,7 @@ class Extension {
static const wchar_t* kNameKey;
static const wchar_t* kPermissionsKey;
static const wchar_t* kPluginsDirKey;
static const wchar_t* kBackgroundKey;
static const wchar_t* kRunAtKey;
static const wchar_t* kThemeKey;
static const wchar_t* kToolstripsKey;
......@@ -63,6 +64,7 @@ class Extension {
static const char* kInvalidMatchesError;
static const char* kInvalidNameError;
static const char* kInvalidPluginsDirError;
static const char* kInvalidBackgroundError;
static const char* kInvalidRunAtError;
static const char* kInvalidToolstripError;
static const char* kInvalidToolstripsError;
......@@ -122,6 +124,7 @@ class Extension {
const std::string& description() const { return description_; }
const UserScriptList& content_scripts() const { return content_scripts_; }
const FilePath& plugins_dir() const { return plugins_dir_; }
const GURL& background_url() const { return background_url_; }
const std::vector<std::string>& toolstrips() const { return toolstrips_; }
const std::vector<URLPattern>& permissions() const {
return permissions_; }
......@@ -163,6 +166,10 @@ class Extension {
// contains.
FilePath plugins_dir_;
// Optional URL to a master page of which a single instance should be always
// loaded in the background.
GURL background_url_;
// Paths to HTML files to be displayed in the toolbar.
std::vector<std::string> toolstrips_;
......@@ -174,6 +181,7 @@ class Extension {
// A map of resource id's to relative file paths.
std::map<const std::wstring, std::string> theme_paths_;
// The sites this extension has permission to talk to (using XHR, etc).
std::vector<URLPattern> permissions_;
// We implement copy, but not assign.
......
// 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_host.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/extensions/extension.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extension_view.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/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/common/resource_bundle.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "webkit/glue/context_menu.h"
ExtensionHost::ExtensionHost(Extension* extension, SiteInstance* site_instance)
: extension_(extension), view_(NULL), did_stop_loading_(false) {
render_view_host_ = new RenderViewHost(
site_instance, this, MSG_ROUTING_NONE, NULL);
render_view_host_->AllowExtensionBindings();
}
ExtensionHost::~ExtensionHost() {
render_view_host_->Shutdown(); // deletes render_view_host
}
SiteInstance* ExtensionHost::site_instance() const {
return render_view_host_->site_instance();
}
void ExtensionHost::CreateRenderView(const GURL& url,
RenderWidgetHostView* host_view) {
render_view_host_->set_view(host_view);
render_view_host_->CreateRenderView();
render_view_host_->NavigateToURL(url);
}
void ExtensionHost::DidContentsPreferredWidthChange(const int pref_width) {
if (view_)
view_->DidContentsPreferredWidthChange(pref_width);
}
void ExtensionHost::RenderViewCreated(RenderViewHost* rvh) {
URLRequestContext* context = rvh->process()->profile()->GetRequestContext();
ExtensionMessageService::GetInstance(context)->RegisterExtension(
extension_->id(), rvh->process()->pid());
}
WebPreferences ExtensionHost::GetWebkitPrefs() {
PrefService* prefs = render_view_host()->process()->profile()->GetPrefs();
const bool kIsDomUI = true;
return RenderViewHostDelegateHelper::GetWebkitPrefs(prefs, kIsDomUI);
}
void ExtensionHost::RunJavaScriptMessage(
const std::wstring& message,
const std::wstring& default_prompt,
const GURL& frame_url,
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"");
}
void ExtensionHost::DidStartLoading(RenderViewHost* render_view_host) {
static const StringPiece toolstrip_css(
ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_EXTENSIONS_TOOLSTRIP_CSS));
render_view_host->InsertCSSInWebFrame(L"", toolstrip_css.as_string());
}
void ExtensionHost::DidStopLoading(RenderViewHost* render_view_host) {
render_view_host->WasResized();
did_stop_loading_ = true;
if (view_)
view_->ShowIfCompletelyLoaded();
}
ExtensionFunctionDispatcher* ExtensionHost::
CreateExtensionFunctionDispatcher(RenderViewHost *render_view_host,
const std::string& extension_id) {
return new ExtensionFunctionDispatcher(render_view_host, GetBrowser(),
extension_id);
}
RenderViewHostDelegate::View* ExtensionHost::GetViewDelegate() const {
// TODO(erikkay) this is unfortunate. The interface declares that this method
// must be const (no good reason for it as far as I can tell) which means you
// can't return self without doing this const_cast. Either we need to change
// the interface, or we need to split out the view delegate into another
// object (which is how WebContents works).
return const_cast<ExtensionHost*>(this);
}
void ExtensionHost::CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event) {
delegate_view_helper_.CreateNewWindow(
route_id, modal_dialog_event, render_view_host()->process()->profile(),
site_instance());
}
void ExtensionHost::CreateNewWidget(int route_id, bool activatable) {
delegate_view_helper_.CreateNewWidget(route_id, activatable,
site_instance()->GetProcess());
}
void ExtensionHost::ShowCreatedWindow(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture) {
WebContents* contents = delegate_view_helper_.GetCreatedWindow(route_id);
if (contents) {
// TODO(erikkay) is it safe to pass in NULL as source?
GetBrowser()->AddTabContents(contents, disposition, initial_pos,
user_gesture);
}
}
void ExtensionHost::ShowCreatedWidget(int route_id,
const gfx::Rect& initial_pos) {
RenderWidgetHostView* widget_host_view =
delegate_view_helper_.GetCreatedWidget(route_id);
GetBrowser()->BrowserRenderWidgetShowing();
// TODO(erikkay): These two lines could be refactored with TabContentsView.
widget_host_view->InitAsPopup(render_view_host()->view(), initial_pos);
widget_host_view->GetRenderWidgetHost()->Init();
}
void ExtensionHost::ShowContextMenu(const ContextMenuParams& params) {
// TODO(erikkay) - This is a temporary hack. Show a menu here instead.
render_view_host()->InspectElementAt(params.x, params.y);
}
void ExtensionHost::StartDragging(const WebDropData& drop_data) {
}
void ExtensionHost::UpdateDragCursor(bool is_drop_target) {
}
void ExtensionHost::TakeFocus(bool reverse) {
}
void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
}
Browser* ExtensionHost::GetBrowser() {
if (view_)
return view_->browser();
Browser* browser = BrowserList::FindBrowserWithProfile(
render_view_host()->process()->profile());
// TODO(mpcomplete): what this verifies doesn't actually happen yet.
CHECK(browser) << "ExtensionHost running in Profile with no Browser active."
" It should have been deleted.";
return browser;
}
// 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_HOST_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_HOST_H_
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
class Browser;
class Extension;
class ExtensionView;
class RenderWidgetHost;
class RenderWidgetHostView;
class WebContents;
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
// privileges available to extensions. It may have a view to be shown in the
// in the browser UI, or it may be hidden.
class ExtensionHost : public RenderViewHostDelegate,
public RenderViewHostDelegate::View {
public:
ExtensionHost(Extension* extension, SiteInstance* site_instance);
~ExtensionHost();
void set_view(ExtensionView* view) { view_ = view; }
ExtensionView* view() const { return view_; }
Extension* extension() { return extension_; }
RenderViewHost* render_view_host() const { return render_view_host_; }
SiteInstance* site_instance() const;
bool did_stop_loading() const { return did_stop_loading_; }
// Initializes our RenderViewHost by creating its RenderView and navigating
// to the given URL. Uses host_view for the RenderViewHost's view (can be
// NULL).
void CreateRenderView(const GURL& url, RenderWidgetHostView* host_view);
// RenderViewHostDelegate
// 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 WebPreferences GetWebkitPrefs();
virtual void RunJavaScriptMessage(
const std::wstring& message,
const std::wstring& default_prompt,
const GURL& frame_url,
const int flags,
IPC::Message* reply_msg,
bool* did_suppress_message);
virtual void DidStartLoading(RenderViewHost* render_view_host);
virtual void DidStopLoading(RenderViewHost* render_view_host);
virtual RenderViewHostDelegate::View* GetViewDelegate() const;
virtual ExtensionFunctionDispatcher* CreateExtensionFunctionDispatcher(
RenderViewHost *render_view_host, const std::string& extension_id);
// RenderViewHostDelegate::View
virtual void CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event);
virtual void CreateNewWidget(int route_id, bool activatable);
virtual void ShowCreatedWindow(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture);
virtual void ShowCreatedWidget(int route_id,
const gfx::Rect& initial_pos);
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
private:
// If this ExtensionHost has a view, this returns the Browser that view is a
// part of. If this is a global background page, we use the active Browser
// instead.
Browser* GetBrowser();
// The extension that we're hosting in this view.
Extension* extension_;
// Optional view that shows the rendered content in the UI.
ExtensionView* view_;
// The host for our HTML content.
RenderViewHost* render_view_host_;
// Common implementations of some RenderViewHostDelegate::View methods.
RenderViewHostDelegateViewHelper delegate_view_helper_;
// Whether the RenderWidget has reported that it has stopped loading.
bool did_stop_loading_;
DISALLOW_COPY_AND_ASSIGN(ExtensionHost);
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_HOST_H_
......@@ -4,65 +4,65 @@
#include "chrome/browser/extensions/extension_view.h"
#include "base/command_line.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/character_encoding.h"
#include "chrome/browser/extensions/extension.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/jsmessage_box_handler.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/common/resource_bundle.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "webkit/glue/context_menu.h"
ExtensionView::ExtensionView(Extension* extension,
const GURL& url,
SiteInstance* instance,
Browser* browser)
: HWNDHtmlView(url, this, false, instance),
extension_(extension),
browser_(browser),
did_stop_loading_(false),
pending_preferred_width_(0) {
#include "chrome/views/widget/widget.h"
#if defined(OS_WIN)
#include "chrome/browser/renderer_host/render_widget_host_view_win.h"
#endif
ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser,
const GURL& content_url)
: host_(host), browser_(browser), content_url_(content_url),
initialized_(false) {
host_->set_view(this);
}
ExtensionView::~ExtensionView() {
if (GetHWND())
Detach();
}
ExtensionFunctionDispatcher* ExtensionView::
CreateExtensionFunctionDispatcher(RenderViewHost *render_view_host,
const std::string& extension_id) {
return new ExtensionFunctionDispatcher(render_view_host, browser_,
extension_id);
void ExtensionView::SetVisible(bool is_visible) {
HWNDView::SetVisible(is_visible);
// Also tell RenderWidgetHostView the new visibility. Despite its name, it is
// not part of the View heirarchy and does not know about the change unless we
// tell it.
if (render_view_host()->view()) {
if (is_visible)
render_view_host()->view()->Show();
else
render_view_host()->view()->Hide();
}
}
void ExtensionView::DidChangeBounds(const gfx::Rect& previous,
const gfx::Rect& current) {
// Propagate the new size to RenderWidgetHostView.
// We can't send size zero because RenderWidget DCHECKs that.
if (render_view_host()->view() && !current.IsEmpty())
render_view_host()->view()->SetSize(gfx::Size(width(), height()));
}
void ExtensionView::ShowIfCompletelyLoaded() {
// We wait to show the ExtensionView until it has loaded and our parent has
// given us a background. These can happen in different orders.
if (did_stop_loading_ && !render_view_host()->view()->background().empty()) {
if (host_->did_stop_loading() && render_view_host()->view() &&
!render_view_host()->view()->background().empty()) {
SetVisible(true);
DidContentsPreferredWidthChange(pending_preferred_width_);
}
}
void ExtensionView::SetBackground(const SkBitmap& background) {
HWNDHtmlView::SetBackground(background);
ShowIfCompletelyLoaded();
}
void ExtensionView::DidStopLoading(RenderViewHost* render_view_host) {
render_view_host->WasResized();
did_stop_loading_ = true;
if (initialized_ && render_view_host()->view()) {
render_view_host()->view()->SetBackground(background);
} else {
pending_background_ = background;
}
ShowIfCompletelyLoaded();
}
......@@ -87,97 +87,37 @@ void ExtensionView::DidContentsPreferredWidthChange(const int pref_width) {
}
}
void ExtensionView::CreatingRenderer() {
render_view_host()->AllowExtensionBindings();
SetVisible(false);
}
void ExtensionView::RenderViewCreated(RenderViewHost* rvh) {
URLRequestContext* context = rvh->process()->profile()->GetRequestContext();
ExtensionMessageService::GetInstance(context)->RegisterExtension(
extension_->id(), render_view_host()->process()->pid());
}
WebPreferences ExtensionView::GetWebkitPrefs() {
PrefService* prefs = render_view_host()->process()->profile()->GetPrefs();
bool isDomUI = true;
return RenderViewHostDelegateHelper::GetWebkitPrefs(prefs, isDomUI);
}
void ExtensionView::RunJavaScriptMessage(
const std::wstring& message,
const std::wstring& default_prompt,
const GURL& frame_url,
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"");
}
void ExtensionView::DidStartLoading(RenderViewHost* render_view_host) {
static const StringPiece toolstrip_css(
ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_EXTENSIONS_TOOLSTRIP_CSS));
render_view_host->InsertCSSInWebFrame(L"", toolstrip_css.as_string());
}
RenderViewHostDelegate::View* ExtensionView::GetViewDelegate() const {
// TODO(erikkay) this is unfortunate. The interface declares that this method
// must be const (no good reason for it as far as I can tell) which means you
// can't return self without doing this const_cast. Either we need to change
// the interface, or we need to split out the view delegate into another
// object (which is how WebContents works).
return const_cast<ExtensionView*>(this);
}
void ExtensionView::CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event) {
delegate_view_helper_.CreateNewWindow(route_id, modal_dialog_event,
browser_->profile(), site_instance());
}
void ExtensionView::CreateNewWidget(int route_id, bool activatable) {
delegate_view_helper_.CreateNewWidget(route_id, activatable,
site_instance()->GetProcess());
}
void ExtensionView::ShowCreatedWindow(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture) {
WebContents* contents = delegate_view_helper_.GetCreatedWindow(route_id);
if (contents) {
browser_->AddTabContents(contents, disposition, initial_pos, user_gesture);
void ExtensionView::ViewHierarchyChanged(bool is_add,
views::View *parent,
views::View *child) {
if (is_add && GetWidget() && !initialized_) {
initialized_ = true;
RenderWidgetHostView* view = RenderWidgetHostView::CreateViewForWidget(
render_view_host());
// TODO(mpcomplete): RWHV needs a cross-platform Init function.
#if defined(OS_WIN)
// Create the HWND. Note:
// RenderWidgetHostHWND supports windowed plugins, but if we ever also
// wanted to support constrained windows with this, we would need an
// additional HWND to parent off of because windowed plugin HWNDs cannot
// exist in the same z-order as constrained windows.
RenderWidgetHostViewWin* view_win =
static_cast<RenderWidgetHostViewWin*>(view);
HWND hwnd = view_win->Create(GetWidget()->GetNativeView());
view_win->ShowWindow(SW_SHOW);
Attach(hwnd);
#else
NOTIMPLEMENTED();
#endif
host_->CreateRenderView(content_url_, view);
SetVisible(false);
if (!pending_background_.empty()) {
render_view_host()->view()->SetBackground(pending_background_);
pending_background_.reset();
}
}
}
void ExtensionView::ShowCreatedWidget(int route_id,
const gfx::Rect& initial_pos) {
RenderWidgetHostView* widget_host_view =
delegate_view_helper_.GetCreatedWidget(route_id);
browser_->BrowserRenderWidgetShowing();
// TODO(erikkay): These two lines could be refactored with TabContentsView.
widget_host_view->InitAsPopup(render_view_host()->view(),
initial_pos);
widget_host_view->GetRenderWidgetHost()->Init();
}
void ExtensionView::ShowContextMenu(const ContextMenuParams& params) {
// TODO(erikkay) - This is a temporary hack. Show a menu here instead.
render_view_host()->InspectElementAt(params.x, params.y);
}
void ExtensionView::StartDragging(const WebDropData& drop_data) {
}
void ExtensionView::UpdateDragCursor(bool is_drop_target) {
}
void ExtensionView::TakeFocus(bool reverse) {
}
void ExtensionView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
}
......@@ -5,97 +5,68 @@
#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_VIEW_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_VIEW_H_
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
#include "build/build_config.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/extensions/extension_host.h"
#include "googleurl/src/gurl.h"
#include "skia/include/SkBitmap.h"
// TODO(port): Port these files.
#if defined(OS_WIN)
#include "chrome/browser/views/hwnd_html_view.h"
#include "chrome/views/controls/hwnd_view.h"
#else
#include "chrome/views/view.h"
#include "chrome/common/temp_scaffolding_stubs.h"
#endif
class Browser;
class Extension;
class ExtensionFunctionDispatcher;
class RenderWidgetHost;
class RenderWidgetHostView;
class WebContents;
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 RenderViewHostDelegate::View {
public:
// ExtensionView
ExtensionView(Extension* extension,
const GURL& url,
SiteInstance* instance,
Browser* browser);
Extension* extension() { return extension_; }
// HWNDHtmlView
virtual void CreatingRenderer();
virtual void SetBackground(const SkBitmap& background);
// RenderViewHostDelegate
// TODO(mpcomplete): GetProfile is unused.
virtual Profile* GetProfile() const { return NULL; }
virtual ExtensionFunctionDispatcher *CreateExtensionFunctionDispatcher(
RenderViewHost *render_view_host,
const std::string& extension_id);
virtual void RenderViewCreated(RenderViewHost* render_view_host);
virtual void DidContentsPreferredWidthChange(const int pref_width);
virtual void DidStopLoading(RenderViewHost* render_view_host);
virtual WebPreferences GetWebkitPrefs();
virtual void RunJavaScriptMessage(
const std::wstring& message,
const std::wstring& default_prompt,
const GURL& frame_url,
const int flags,
IPC::Message* reply_msg,
bool* did_suppress_message);
virtual void DidStartLoading(RenderViewHost* render_view_host);
virtual RenderViewHostDelegate::View* GetViewDelegate() const;
// RenderViewHostDelegate::View
virtual void CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event);
virtual void CreateNewWidget(int route_id, bool activatable);
virtual void ShowCreatedWindow(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture);
virtual void ShowCreatedWidget(int route_id,
const gfx::Rect& initial_pos);
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
// This handles the display portion of an ExtensionHost.
class ExtensionView : public views::HWNDView {
public:
ExtensionView(ExtensionHost* host, Browser* browser, const GURL& content_url);
~ExtensionView();
ExtensionHost* host() const { return host_.get(); }
Browser* browser() const { return browser_; }
Extension* extension() { return host_->extension(); }
RenderViewHost* render_view_host() { return host_->render_view_host(); }
// Notification from ExtensionHost.
void DidContentsPreferredWidthChange(const int pref_width);
// Set a custom background for the view. The background will be tiled.
void SetBackground(const SkBitmap& background);
// views::HWNDView
virtual void SetVisible(bool is_visible);
virtual void DidChangeBounds(const gfx::Rect& previous,
const gfx::Rect& current);
virtual void ViewHierarchyChanged(bool is_add,
views::View *parent, views::View *child);
private:
friend class ExtensionHost;
// We wait to show the ExtensionView until several things have loaded.
void ShowIfCompletelyLoaded();
// The extension that we're hosting in this view.
Extension* extension_;
// The running extension instance that we're displaying.
scoped_ptr<ExtensionHost> host_;
// The browser window that this view is in.
Browser* browser_;
// Common implementations of some RenderViewHostDelegate::View methods.
RenderViewHostDelegateViewHelper delegate_view_helper_;
// The URL to navigate the host to upon initialization.
GURL content_url_;
// True if we've been initialized.
bool initialized_;
// Whether the RenderWidget has reported that it has stopped loading.
bool did_stop_loading_;
// The background the view should have once it is initialized. This is set
// when the view has a custom background, but hasn't been initialized yet.
SkBitmap pending_background_;
// What we should set the preferred width to once the ExtensionView has
// loaded.
......
......@@ -6,7 +6,7 @@
#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_view.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/test_extension_loader.h"
#include "chrome/browser/tab_contents/site_instance.h"
......@@ -28,12 +28,13 @@ const char* kExtensionId = "00123456789abcdef0123456789abcdef0123456";
// This class starts up an extension process and waits until it tries to put
// up a javascript alert.
class MockExtensionView : public ExtensionView {
class MockExtensionHost : public ExtensionHost {
public:
MockExtensionView(Extension* extension, const GURL& url,
SiteInstance* instance, Browser* browser)
: ExtensionView(extension, url, instance, browser), got_message_(false) {
InitHidden();
MockExtensionHost(Extension* extension, const GURL& url,
SiteInstance* instance)
: ExtensionHost(extension, instance),
got_message_(false) {
CreateRenderView(url, NULL);
MessageLoop::current()->PostDelayedTask(FROM_HERE,
new MessageLoop::QuitTask, kAlertTimeoutMs);
ui_test_utils::RunMessageLoop();
......@@ -58,7 +59,7 @@ class MockExtensionView : public ExtensionView {
MessageLoopForUI::current()->Quit();
// Call super, otherwise we'll leak reply_msg.
ExtensionView::RunJavaScriptMessage(
ExtensionHost::RunJavaScriptMessage(
message, default_prompt, frame_url, flags,
reply_msg, did_suppress_message);
}
......@@ -100,8 +101,7 @@ 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()->GetExtensionsService()->GetSiteInstanceForURL(url),
browser());
EXPECT_TRUE(view.got_message());
MockExtensionHost host(extension, url,
browser()->profile()->GetExtensionsService()->GetSiteInstanceForURL(url));
EXPECT_TRUE(host.got_message());
}
......@@ -18,8 +18,9 @@
#include "chrome/browser/extensions/extension.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_view.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/plugin_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/site_instance.h"
......@@ -27,6 +28,8 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/unzip.h"
#include "chrome/browser/browser_list.h"
#if defined(OS_WIN)
#include "base/registry.h"
#endif
......@@ -82,6 +85,11 @@ ExtensionsService::ExtensionsService(Profile* profile,
}
ExtensionsService::~ExtensionsService() {
for (ExtensionHostList::iterator iter = background_hosts_.begin();
iter != background_hosts_.end(); ++iter) {
delete *iter;
}
for (ExtensionList::iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
delete *iter;
......@@ -163,6 +171,11 @@ void ExtensionsService::OnExtensionsLoaded(ExtensionList* new_extensions) {
script != scripts.end(); ++script) {
user_script_master_->AddLoneScript(*script);
}
// Start the process for the master page, if it exists.
if ((*extension)->background_url().is_valid()) {
CreateBackgroundHost(*extension, (*extension)->background_url());
}
}
// Since user scripts may have changed, tell UserScriptMaster to kick off
......@@ -189,7 +202,16 @@ void ExtensionsService::OnExtensionInstalled(FilePath path, bool update) {
ExtensionView* ExtensionsService::CreateView(Extension* extension,
const GURL& url,
Browser* browser) {
return new ExtensionView(extension, url, GetSiteInstanceForURL(url), browser);
return new ExtensionView(
new ExtensionHost(extension, GetSiteInstanceForURL(url)), browser, url);
}
void ExtensionsService::CreateBackgroundHost(Extension* extension,
const GURL& url) {
ExtensionHost* host =
new ExtensionHost(extension, GetSiteInstanceForURL(url));
host->CreateRenderView(url, NULL); // create a RenderViewHost with no view
background_hosts_.push_back(host);
}
SiteInstance* ExtensionsService::GetSiteInstanceForURL(const GURL& url) {
......
......@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include <list>
#include "base/file_path.h"
#include "base/message_loop.h"
......@@ -17,6 +18,7 @@
class Browser;
class BrowsingInstance;
class Extension;
class ExtensionHost;
class ExtensionView;
class ExtensionsServiceBackend;
class GURL;
......@@ -82,6 +84,10 @@ class ExtensionsService : public ExtensionsServiceFrontendInterface {
const GURL& url,
Browser* browser);
// Creates a new UI-less extension instance. Like CreateView, but not
// displayed anywhere.
void CreateBackgroundHost(Extension* extension, const GURL& url);
// Returns the SiteInstance that the given URL belongs to.
SiteInstance* GetSiteInstanceForURL(const GURL& url);
......@@ -112,6 +118,10 @@ class ExtensionsService : public ExtensionsServiceFrontendInterface {
// controls process grouping.
scoped_refptr<BrowsingInstance> browsing_instance_;
// The list of running viewless background extensions.
typedef std::list<ExtensionHost*> ExtensionHostList;
ExtensionHostList background_hosts_;
DISALLOW_COPY_AND_ASSIGN(ExtensionsService);
};
......
......@@ -184,6 +184,7 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) {
scripts[0].js_scripts()[0].path().value());
EXPECT_EQ(extension->path().AppendASCII("script2.js").value(),
scripts[0].js_scripts()[1].path().value());
EXPECT_TRUE(extension->plugins_dir().empty());
EXPECT_EQ(1u, scripts[1].url_patterns().size());
EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString());
EXPECT_EQ(extension->path().AppendASCII("js_files").AppendASCII("script3.js")
......@@ -204,6 +205,8 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) {
frontend->extensions()->at(1)->description());
EXPECT_EQ(frontend->extensions()->at(1)->path().AppendASCII("npapi").value(),
frontend->extensions()->at(1)->plugins_dir().value());
EXPECT_EQ(frontend->extensions()->at(1)->GetResourceURL("background.html"),
frontend->extensions()->at(1)->background_url());
ASSERT_EQ(0u, frontend->extensions()->at(1)->content_scripts().size());
EXPECT_EQ(std::string("20123456789abcdef0123456789abcdef0123456"),
......
......@@ -160,14 +160,12 @@ bool RenderViewHost::CreateRenderView() {
"Couldn't duplicate the modal dialog handle for the renderer.";
#endif
DCHECK(view());
ModalDialogEvent modal_dialog_event;
#if defined(OS_WIN)
modal_dialog_event.event = modal_dialog_event_handle;
#endif
Send(new ViewMsg_New(gfx::IdFromNativeView(view()->GetPluginNativeView()),
Send(new ViewMsg_New(GetPluginNativeViewId(),
modal_dialog_event,
delegate_->GetWebkitPrefs(),
routing_id()));
......
......@@ -4,7 +4,6 @@
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "base/gfx/native_widget_types.h"
#include "base/histogram.h"
#include "base/message_loop.h"
#include "base/keyboard_codes.h"
......@@ -79,15 +78,19 @@ RenderWidgetHost::~RenderWidgetHost() {
process_->Release(routing_id_);
}
gfx::NativeViewId RenderWidgetHost::GetPluginNativeViewId() {
if (view_)
return gfx::IdFromNativeView(view_->GetPluginNativeView());
return NULL;
}
void RenderWidgetHost::Init() {
DCHECK(process_->channel());
renderer_initialized_ = true;
// Send the ack along with the information on placement.
gfx::NativeView plugin_view = view_->GetPluginNativeView();
Send(new ViewMsg_CreatingNew_ACK(routing_id_,
gfx::IdFromNativeView(plugin_view)));
Send(new ViewMsg_CreatingNew_ACK(routing_id_, GetPluginNativeViewId()));
WasResized();
}
......@@ -459,7 +462,8 @@ void RenderWidgetHost::OnMsgClose() {
void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) {
// Note that we ignore the position.
view_->SetSize(pos.size());
if (view_)
view_->SetSize(pos.size());
}
void RenderWidgetHost::OnMsgPaintRect(
......
......@@ -8,6 +8,7 @@
#include <queue>
#include <vector>
#include "base/gfx/native_widget_types.h"
#include "base/gfx/size.h"
#include "base/scoped_ptr.h"
#include "base/timer.h"
......@@ -267,6 +268,9 @@ class RenderWidgetHost : public IPC::Channel::Listener {
// consistent if a new renderer is created.
void RendererExited();
// Retrieves the native view used to contain plugins.
gfx::NativeViewId GetPluginNativeViewId();
// Called when we an InputEvent was not processed by the renderer. This is
// overridden by RenderView to send upwards to its delegate.
virtual void UnhandledKeyboardEvent(const NativeWebKeyboardEvent& event) {}
......
......@@ -684,6 +684,8 @@
'browser/extensions/extension_function.h',
'browser/extensions/extension_function_dispatcher.cc',
'browser/extensions/extension_function_dispatcher.h',
'browser/extensions/extension_host.cc',
'browser/extensions/extension_host.h',
'browser/extensions/extension_message_service.cc',
'browser/extensions/extension_message_service.h',
'browser/extensions/extension_browser_event_router.cc',
......
......@@ -39,6 +39,7 @@ struct ViewHostMsg_DidPrintPage_Params;
namespace gfx {
class Rect;
class Widget;
}
namespace IPC {
......@@ -478,26 +479,38 @@ class BaseDragSource {
//---------------------------------------------------------------------------
// These stubs are for extensions
class HWNDHtmlView {
namespace views {
class HWNDView {
public:
HWNDHtmlView(const GURL& content_url, RenderViewHostDelegate* delegate,
bool allow_dom_ui_bindings, SiteInstance* instance) {
NOTIMPLEMENTED();
}
virtual ~HWNDHtmlView() {}
int width() { NOTIMPLEMENTED(); return 0; }
int height() { NOTIMPLEMENTED(); return 0; }
RenderViewHost* render_view_host() { NOTIMPLEMENTED(); return NULL; }
void InitHidden() { NOTIMPLEMENTED(); }
void set_preferred_size(const gfx::Size& size) { NOTIMPLEMENTED(); }
virtual void SetBackground(const SkBitmap&) { NOTIMPLEMENTED(); }
virtual void SetVisible(bool flag) { NOTIMPLEMENTED(); }
void SizeToPreferredSize() { NOTIMPLEMENTED(); }
HWNDHtmlView* GetParent() const { NOTIMPLEMENTED(); return NULL; }
bool IsVisible() const { NOTIMPLEMENTED(); return false; }
void Layout() { NOTIMPLEMENTED(); }
void SchedulePaint() { NOTIMPLEMENTED(); }
HWNDView* GetParent() const { NOTIMPLEMENTED(); return NULL; }
gfx::NativeWindow GetHWND() { NOTIMPLEMENTED(); return 0; }
void Detach() { NOTIMPLEMENTED(); }
gfx::Widget* GetWidget() { NOTIMPLEMENTED(); return NULL; }
};
} // namespace views
class HWNDHtmlView : public views::HWNDView {
public:
HWNDHtmlView(const GURL& content_url, RenderViewHostDelegate* delegate,
bool allow_dom_ui_bindings, SiteInstance* instance) {
NOTIMPLEMENTED();
}
virtual ~HWNDHtmlView() {}
RenderViewHost* render_view_host() { NOTIMPLEMENTED(); return NULL; }
SiteInstance* site_instance() { NOTIMPLEMENTED(); return NULL; }
};
#endif // CHROME_COMMON_TEMP_SCAFFOLDING_STUBS_H_
......@@ -2,5 +2,6 @@
"id": "10123456789ABCDEF0123456789ABCDEF0123456",
"version": "1.0.0.0",
"name": "My extension 2",
"plugins_dir": "npapi"
"plugins_dir": "npapi",
"background": "background.html"
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment