diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-14 05:43:53 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-14 05:43:53 +0000 |
commit | 7b291f9c1394495724ddd81306e982e840075c08 (patch) | |
tree | fa2a2ef45f1b17018e716101395300da731d8599 /chrome/renderer | |
parent | cc4219ad7dd27008da3db5f0e23da9a6ab2f0387 (diff) | |
download | chromium_src-7b291f9c1394495724ddd81306e982e840075c08.zip chromium_src-7b291f9c1394495724ddd81306e982e840075c08.tar.gz chromium_src-7b291f9c1394495724ddd81306e982e840075c08.tar.bz2 |
Implementation of getBackgroundPage(), getToolstrips(), and
getTabContentses().
This lands http://codereview.chromium.org/159067.
Raf, the only thing you need to look at is the changes to extensions_process_bindings.js and extension_api.json.
BUG=13577
TEST=Browser tests added
Review URL: http://codereview.chromium.org/164458
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23422 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/extensions/bindings_utils.cc | 4 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_process_bindings.cc | 74 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 17 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 21 | ||||
-rw-r--r-- | chrome/renderer/renderer_resources.grd | 2 | ||||
-rw-r--r-- | chrome/renderer/resources/extension_process_bindings.js | 163 |
6 files changed, 189 insertions, 92 deletions
diff --git a/chrome/renderer/extensions/bindings_utils.cc b/chrome/renderer/extensions/bindings_utils.cc index 3d29f4b..13deb2a 100644 --- a/chrome/renderer/extensions/bindings_utils.cc +++ b/chrome/renderer/extensions/bindings_utils.cc @@ -68,8 +68,8 @@ ContextList::iterator FindContext(v8::Handle<v8::Context> context) { ContextList::iterator it = all_contexts.begin(); for (; it != all_contexts.end(); ++it) { - if ((*it)->context == context) - break; + if ((*it)->context == context) + break; } return it; diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index cf0f344..cb22bce 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -92,8 +92,8 @@ class ExtensionImpl : public ExtensionBase { v8::Handle<v8::String> name) { if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) { return v8::FunctionTemplate::New(GetExtensionAPIDefinition); - } else if (name->Equals(v8::String::New("GetViews"))) { - return v8::FunctionTemplate::New(GetViews); + } else if (name->Equals(v8::String::New("GetExtensionViews"))) { + return v8::FunctionTemplate::New(GetExtensionViews); } else if (name->Equals(v8::String::New("GetNextRequestId"))) { return v8::FunctionTemplate::New(GetNextRequestId); } else if (name->Equals(v8::String::New("OpenChannelToTab"))) { @@ -113,22 +113,66 @@ class ExtensionImpl : public ExtensionBase { return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>()); } - static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { - std::string extension_id = ExtensionIdForCurrentContext(); + static v8::Handle<v8::Value> GetExtensionViews(const v8::Arguments& args) { + if (args.Length() != 2) + return v8::Undefined(); + + if (!args[0]->IsInt32() || !args[1]->IsString()) + return v8::Undefined(); - ContextList contexts = - bindings_utils::GetContextsForExtension(extension_id); - DCHECK(contexts.size() > 0); + // |browser_window_id| == -1 means getting views attached to any browser + // window. + int browser_window_id = args[0]->Int32Value(); + + std::string view_type_string = *v8::String::Utf8Value(args[1]->ToString()); + // |view_type| == ViewType::INVALID means getting any type of views. + ViewType::Type view_type = ViewType::INVALID; + if (view_type_string == "TOOLSTRIP") { + view_type = ViewType::EXTENSION_TOOLSTRIP; + } else if (view_type_string == "BACKGROUND") { + view_type = ViewType::EXTENSION_BACKGROUND_PAGE; + } else if (view_type_string == "TAB") { + view_type = ViewType::TAB_CONTENTS; + } else if (view_type_string != "ALL") { + return v8::Undefined(); + } - v8::Local<v8::Array> views = v8::Array::New(contexts.size()); + v8::Local<v8::Array> views = v8::Array::New(); int index = 0; - ContextList::const_iterator it = contexts.begin(); - for (; it != contexts.end(); ++it) { - v8::Local<v8::Value> window = (*it)->context->Global()->Get( - v8::String::New("window")); - DCHECK(!window.IsEmpty()); - views->Set(v8::Integer::New(index), window); - index++; + RenderView::RenderViewSet* render_view_set_pointer = + Singleton<RenderView::RenderViewSet>::get(); + DCHECK(render_view_set_pointer->render_view_set_.size() > 0); + + v8::Local<v8::Value> window; + std::string current_extension_id = ExtensionIdForCurrentContext(); + std::set<RenderView* >::iterator it = + render_view_set_pointer->render_view_set_.begin(); + for (; it != render_view_set_pointer->render_view_set_.end(); ++it) { + if (view_type != ViewType::INVALID && (*it)->view_type() != view_type) + continue; + + GURL url = (*it)->webview()->GetMainFrame()->url(); + if (!url.SchemeIs(chrome::kExtensionScheme)) + continue; + std::string extension_id = url.host(); + if (extension_id != current_extension_id) + continue; + + if (browser_window_id != -1 && + (*it)->browser_window_id() != browser_window_id) { + continue; + } + + v8::Local<v8::Context> context = + (*it)->webview()->GetMainFrame()->mainWorldScriptContext(); + if (!context.IsEmpty()) { + v8::Local<v8::Value> window = context->Global(); + DCHECK(!window.IsEmpty()); + views->Set(v8::Integer::New(index), window); + index++; + if (view_type == ViewType::EXTENSION_BACKGROUND_PAGE) + break; + } } return views; } diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 1ddf4cc..9fd1f1d 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -19,6 +19,7 @@ #include "base/gfx/png_encoder.h" #include "base/gfx/native_widget_types.h" #include "base/process_util.h" +#include "base/singleton.h" #include "base/string_piece.h" #include "base/string_util.h" #include "build/build_config.h" @@ -201,10 +202,14 @@ RenderView::RenderView(RenderThreadBase* render_thread) preferred_width_(0), send_preferred_width_changes_(false), determine_page_text_after_loading_stops_(false), + view_type_(ViewType::INVALID), + browser_window_id_(-1), last_top_level_navigation_page_id_(-1) { + Singleton<RenderViewSet>()->render_view_set_.insert(this); } RenderView::~RenderView() { + Singleton<RenderViewSet>()->render_view_set_.erase(this); if (decrement_shared_popup_at_destruction_) shared_popup_counter_->data--; @@ -427,6 +432,10 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode, OnEnableIntrinsicWidthChangedMode) IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs) + IPC_MESSAGE_HANDLER(ViewMsg_UpdateBrowserWindowId, + OnUpdateBrowserWindowId) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyRenderViewType, + OnNotifyRendererViewType) IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt) IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive) @@ -2777,6 +2786,14 @@ void RenderView::OnMediaPlayerActionAt(int x, webview()->MediaPlayerActionAt(x, y, action); } +void RenderView::OnNotifyRendererViewType(ViewType::Type type) { + view_type_ = type; +} + +void RenderView::OnUpdateBrowserWindowId(int window_id) { + browser_window_id_ = window_id; +} + void RenderView::OnUpdateBackForwardListCount(int back_list_count, int forward_list_count) { history_back_list_count_ = back_list_count; diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index ef29a81..d7781e2 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -19,6 +19,7 @@ #include "build/build_config.h" #include "chrome/common/id_map.h" #include "chrome/common/renderer_preferences.h" +#include "chrome/common/view_types.h" #include "chrome/renderer/automation/dom_automation_controller.h" #include "chrome/renderer/dom_ui_bindings.h" #include "chrome/renderer/extensions/extension_process_bindings.h" @@ -98,6 +99,9 @@ class RenderView : public RenderWidget, public WebViewDelegate, public webkit_glue::DomSerializerDelegate { public: + struct RenderViewSet { + std::set<RenderView* > render_view_set_; + }; // Creates a new RenderView. The parent_hwnd specifies a HWND to use as the // parent of the WebView HWND that will be created. The modal_dialog_event // is set by the RenderView whenever a modal dialog alert is shown, so that @@ -132,6 +136,14 @@ class RenderView : public RenderWidget, return modal_dialog_event_.get(); } + int browser_window_id() { + return browser_window_id_; + } + + ViewType::Type view_type() { + return view_type_; + } + // IPC::Channel::Listener virtual void OnMessageReceived(const IPC::Message& msg); @@ -543,6 +555,8 @@ class RenderView : public RenderWidget, void OnMediaPlayerActionAt(int x, int y, const MediaPlayerAction& action); + void OnNotifyRendererViewType(ViewType::Type view_type); + void OnUpdateBrowserWindowId(int window_id); void OnUpdateBackForwardListCount(int back_list_count, int forward_list_count); void OnGetAccessibilityInfo( @@ -837,6 +851,13 @@ class RenderView : public RenderWidget, RendererPreferences renderer_preferences_; + // Type of view attached with RenderView, it could be INVALID, TAB_CONTENTS, + // EXTENSION_TOOLSTRIP, EXTENSION_BACKGROUND_PAGE, DEV_TOOLS_UI. + ViewType::Type view_type_; + + // Id number of browser window which RenderView is attached to. + int browser_window_id_; + // page id for the last navigation sent to the browser. int32 last_top_level_navigation_page_id_; diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd index e5c7fcf..eb128c7 100644 --- a/chrome/renderer/renderer_resources.grd +++ b/chrome/renderer/renderer_resources.grd @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- This comment is only here because changes to resources are not picked up -without changes to the corresponding grd file. rw2 --> +without changes to the corresponding grd file. aa1 --> <grit latest_public_release="0" current_release="1"> <outputs> <output filename="grit/renderer_resources.h" type="rc_header"> diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index e828bd5..f132e55 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -15,7 +15,7 @@ var chrome = chrome || {}; native function GetExtensionAPIDefinition(); native function StartRequest(); native function GetCurrentPageActions(extensionId); - native function GetViews(); + native function GetExtensionViews(); native function GetChromeHidden(); native function GetNextRequestId(); native function OpenChannelToTab(); @@ -122,19 +122,6 @@ var chrome = chrome || {}; return StartRequest(functionName, sargs, requestId, hasCallback); } - // Read api definitions and setup api functions in the chrome namespace. - // TODO(rafaelw): Consider defining a json schema for an api definition - // and validating either here, in a unit_test or both. - // TODO(rafaelw): Handle synchronous functions. - // TOOD(rafaelw): Consider providing some convenient override points - // for api functions that wish to insert themselves into the call. - var apiDefinitions = JSON.parse(GetExtensionAPIDefinition()); - - // |apiFunctions| is a hash of name -> object that stores the - // name & definition of the apiFunction. Custom handling of api functions - // is implemented by adding a "handleRequest" function to the object. - var apiFunctions = {}; - // Using forEach for convenience, and to bind |module|s & |apiDefs|s via // closures. function forEach(a, f) { @@ -149,49 +136,6 @@ var chrome = chrome || {}; }; } - forEach(apiDefinitions, function(apiDef) { - chrome[apiDef.namespace] = chrome[apiDef.namespace] || {}; - var module = chrome[apiDef.namespace]; - - // Setup Functions. - if (apiDef.functions) { - forEach(apiDef.functions, function(functionDef) { - // Module functions may have been defined earlier by hand. Don't clobber - // them. - if (module[functionDef.name]) - return; - - var apiFunction = {}; - apiFunction.definition = functionDef; - apiFunction.name = apiDef.namespace + "." + functionDef.name;; - apiFunctions[apiFunction.name] = apiFunction; - - module[functionDef.name] = bind(apiFunction, function() { - validate(arguments, this.definition.parameters); - - if (this.handleRequest) - return this.handleRequest.apply(this, arguments); - else - return sendRequest(this.name, arguments, - this.definition.parameters); - }); - }); - } - - // Setup Events - if (apiDef.events) { - forEach(apiDef.events, function(eventDef) { - // Module events may have been defined earlier by hand. Don't clobber - // them. - if (module[eventDef.name]) - return; - - var eventName = apiDef.namespace + "." + eventDef.name; - module[eventDef.name] = new chrome.Event(eventName); - }); - } - }); - // --- Setup additional api's not currently handled in common/extensions/api // Page action events send (pageActionId, {tabId, tabUrl}). @@ -205,26 +149,97 @@ var chrome = chrome || {}; } } - // Tabs connect() - apiFunctions["tabs.connect"].handleRequest = function(tabId, opt_name) { - var portId = OpenChannelToTab(tabId, chrome.extension.id_, opt_name || ""); - return chromeHidden.Port.createPort(portId, opt_name); - } - - // chrome.self / chrome.extension. - chrome.self = chrome.self || {}; - chromeHidden.onLoad.addListener(function (extensionId) { chrome.extension = new chrome.Extension(extensionId); - // TODO(mpcomplete): self.onConnect is deprecated. Remove it at 1.0. + + // TODO(mpcomplete): chrome.self is deprecated. Remove it at 1.0. // http://code.google.com/p/chromium/issues/detail?id=16356 - chrome.self.onConnect = chrome.extension.onConnect; + chrome.self = chrome.extension; + + // |apiFunctions| is a hash of name -> object that stores the + // name & definition of the apiFunction. Custom handling of api functions + // is implemented by adding a "handleRequest" function to the object. + var apiFunctions = {}; + + // Read api definitions and setup api functions in the chrome namespace. + // TODO(rafaelw): Consider defining a json schema for an api definition + // and validating either here, in a unit_test or both. + // TODO(rafaelw): Handle synchronous functions. + // TOOD(rafaelw): Consider providing some convenient override points + // for api functions that wish to insert themselves into the call. + var apiDefinitions = JSON.parse(GetExtensionAPIDefinition()); + + forEach(apiDefinitions, function(apiDef) { + chrome[apiDef.namespace] = chrome[apiDef.namespace] || {}; + var module = chrome[apiDef.namespace]; + + // Setup Functions. + if (apiDef.functions) { + forEach(apiDef.functions, function(functionDef) { + // Module functions may have been defined earlier by hand. Don't + // clobber them. + if (module[functionDef.name]) + return; + + var apiFunction = {}; + apiFunction.definition = functionDef; + apiFunction.name = apiDef.namespace + "." + functionDef.name;; + apiFunctions[apiFunction.name] = apiFunction; + + module[functionDef.name] = bind(apiFunction, function() { + validate(arguments, this.definition.parameters); + + if (this.handleRequest) + return this.handleRequest.apply(this, arguments); + else + return sendRequest(this.name, arguments, + this.definition.parameters); + }); + }); + } + + // Setup Events + if (apiDef.events) { + forEach(apiDef.events, function(eventDef) { + // Module events may have been defined earlier by hand. Don't clobber + // them. + if (module[eventDef.name]) + return; + + var eventName = apiDef.namespace + "." + eventDef.name; + module[eventDef.name] = new chrome.Event(eventName); + }); + } + }); + + apiFunctions["tabs.connect"].handleRequest = function(tabId, opt_name) { + var portId = OpenChannelToTab( + tabId, chrome.extension.id_, opt_name || ""); + return chromeHidden.Port.createPort(portId, opt_name); + } + + apiFunctions["extension.getViews"].handleRequest = function() { + return GetExtensionViews(-1, "ALL"); + } + + apiFunctions["extension.getBackgroundPage"].handleRequest = function() { + return GetExtensionViews(-1, "BACKGROUND")[0] || null; + } + + apiFunctions["extension.getToolstrips"].handleRequest = + function(windowId) { + if (typeof(windowId) == "undefined") + windowId = -1; + return GetExtensionViews(windowId, "TOOLSTRIP"); + } + + apiFunctions["extension.getTabContentses"].handleRequest = + function(windowId) { + if (typeof(windowId) == "undefined") + windowId = -1; + return GetExtensionViews(windowId, "TAB"); + } setupPageActionEvents(extensionId); }); - - // Self getViews(); - apiFunctions["self.getViews"].handleRequest = function() { - return GetViews(); - } -})(); + })(); |