diff options
11 files changed, 167 insertions, 2 deletions
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index dccc32a..96f0256 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -6,6 +6,7 @@ #include "base/singleton.h" #include "chrome/common/render_messages.h" +#include "chrome/common/url_constants.h" #include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" @@ -29,6 +30,14 @@ const char* kExtensionDeps[] = { RendererExtensionBindings::kName, }; +// Types for storage of per-renderer-singleton data structure that maps +// |extension_id| -> <List of v8 Contexts for the "views" of that extension> +typedef std::list< v8::Persistent<v8::Context> > ContextList; +typedef std::map<std::string, ContextList> ExtensionIdContextsMap; +struct ExtensionViewContexts { + ExtensionIdContextsMap contexts; +}; + class ExtensionImpl : public v8::Extension { public: ExtensionImpl() : v8::Extension( @@ -48,6 +57,12 @@ class ExtensionImpl : public v8::Extension { if (name->Equals(v8::String::New("GetNextRequestId"))) return v8::FunctionTemplate::New(GetNextRequestId); + else if (name->Equals(v8::String::New("RegisterExtension"))) + return v8::FunctionTemplate::New(RegisterExtension); + else if (name->Equals(v8::String::New("UnregisterExtension"))) + return v8::FunctionTemplate::New(UnregisterExtension); + else if (name->Equals(v8::String::New("GetViews"))) + return v8::FunctionTemplate::New(GetViews); else if (names->find(*v8::String::AsciiValue(name)) != names->end()) return v8::FunctionTemplate::New(StartRequest, name); @@ -63,6 +78,70 @@ class ExtensionImpl : public v8::Extension { return &Singleton<SingletonData>()->function_names_; } + static ContextList& GetRegisteredContexts(std::string extension_id) { + return Singleton<ExtensionViewContexts>::get()->contexts[extension_id]; + } + + static v8::Handle<v8::Value> RegisterExtension(const v8::Arguments& args) { + RenderView* renderview = GetRenderViewForCurrentContext(); + DCHECK(renderview); + GURL url = renderview->webview()->GetMainFrame()->GetURL(); + DCHECK(url.scheme() == chrome::kExtensionScheme); + + v8::Persistent<v8::Context> current_context = + v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); + DCHECK(!current_context.IsEmpty()); + + std::string extension_id = url.host(); + GetRegisteredContexts(extension_id).push_back(current_context); + return v8::String::New(extension_id.c_str()); + } + + static v8::Handle<v8::Value> UnregisterExtension(const v8::Arguments& args) { + DCHECK_EQ(args.Length(), 1); + DCHECK(args[0]->IsString()); + + std::string extension_id(*v8::String::Utf8Value(args[0])); + ContextList& contexts = GetRegisteredContexts(extension_id); + v8::Local<v8::Context> current_context = v8::Context::GetCurrent(); + DCHECK(!current_context.IsEmpty()); + + ContextList::iterator it = std::find(contexts.begin(), contexts.end(), + current_context); + if (it == contexts.end()) { + NOTREACHED(); + return v8::Undefined(); + } + + it->Dispose(); + it->Clear(); + contexts.erase(it); + + return v8::Undefined(); + } + + static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { + RenderView* renderview = GetRenderViewForCurrentContext(); + DCHECK(renderview); + GURL url = renderview->webview()->GetMainFrame()->GetURL(); + std::string extension_id = url.host(); + + ContextList& contexts = GetRegisteredContexts(extension_id); + DCHECK(contexts.size() > 0); + + v8::Local<v8::Array> views = v8::Array::New(contexts.size()); + int index = 0; + ContextList::const_iterator it = contexts.begin(); + for (; it != contexts.end(); ++it) { + v8::Local<v8::Value> window = (*it)->Global()->Get( + v8::String::New("window")); + DCHECK(!window.IsEmpty()); + views->Set(v8::Integer::New(index), window); + index++; + } + return views; + } + static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) { static int next_request_id = 0; return v8::Integer::New(next_request_id++); @@ -103,6 +182,11 @@ void ExtensionProcessBindings::SetFunctionNames( ExtensionImpl::SetFunctionNames(names); } +void ExtensionProcessBindings::RegisterExtensionContext(WebFrame* frame) { + frame->ExecuteScript(WebScriptSource(WebString::fromUTF8( + "chrome.self.register_();"))); +} + void ExtensionProcessBindings::ExecuteResponseInFrame( CallContext *call, int request_id, bool success, const std::string& response, diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h index a24e4e5..d5798cd 100644 --- a/chrome/renderer/extensions/extension_process_bindings.h +++ b/chrome/renderer/extensions/extension_process_bindings.h @@ -27,6 +27,7 @@ class ExtensionProcessBindings { static void SetFunctionNames(const std::vector<std::string>& names); static v8::Extension* Get(); + static void RegisterExtensionContext(WebFrame* frame); static void ExecuteResponseInFrame(CallContext *call, int request_id, bool success, const std::string& response, diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 210fd7f..d09b195 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -1532,6 +1532,12 @@ void RenderView::DocumentElementAvailable(WebFrame* frame) { if (frame->GetURL().SchemeIs(chrome::kExtensionScheme)) frame->GrantUniversalAccess(); + // Tell extensions to self-register their js contexts. + // TODO:(rafaelw): This is kind of gross. We need a way to call through + // the glue layer to retrieve the current v8::Context. + if (frame->GetURL().SchemeIs(chrome::kExtensionScheme)) + ExtensionProcessBindings::RegisterExtensionContext(frame); + if (RenderThread::current()) // Will be NULL during unit tests. RenderThread::current()->user_script_slave()->InjectScripts( frame, UserScript::DOCUMENT_START); diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd index c59e98c..cda253b 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. --> +without changes to the corresponding grd file. --> <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 9bd0aca3..5a9fcf1 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -10,6 +10,9 @@ var chrome; (function() { native function GetNextRequestId(); + native function RegisterExtension(); + native function UnregisterExtension(); + native function GetViews(); native function GetWindow(); native function GetCurrentWindow(); native function GetLastFocusedWindow(); @@ -499,7 +502,19 @@ var chrome; //---------------------------------------------------------------------------- // Self. - chrome.self = {}; + chrome.self = chrome.self || {}; chrome.self.onConnect = new chrome.Event("channel-connect"); + + // Register + chrome.self.register_ = function() { + var extensionId = RegisterExtension(); + window.addEventListener('unload', function() { + UnregisterExtension(extensionId); }, false); + delete chrome.self.register_; + } + + chrome.self.getViews = function() { + return GetViews(); + } })(); diff --git a/chrome/test/data/extensions/samples/getviews/bg.html b/chrome/test/data/extensions/samples/getviews/bg.html new file mode 100755 index 0000000..cdfbf58 --- /dev/null +++ b/chrome/test/data/extensions/samples/getviews/bg.html @@ -0,0 +1,9 @@ +<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="common.css">
+ <script src="common.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <div span id="me" onclick="claim();">Background Page</div>
+ </body>
+</html>
\ No newline at end of file diff --git a/chrome/test/data/extensions/samples/getviews/common.css b/chrome/test/data/extensions/samples/getviews/common.css new file mode 100755 index 0000000..99d72a0 --- /dev/null +++ b/chrome/test/data/extensions/samples/getviews/common.css @@ -0,0 +1,10 @@ +body {
+ font-size: 18px;
+}
+
+.strong {
+ background-color: red;
+}
+.weak {
+ color: pink;
+}
\ No newline at end of file diff --git a/chrome/test/data/extensions/samples/getviews/common.js b/chrome/test/data/extensions/samples/getviews/common.js new file mode 100755 index 0000000..e567088 --- /dev/null +++ b/chrome/test/data/extensions/samples/getviews/common.js @@ -0,0 +1,15 @@ +function claim() {
+ var views = chrome.self.getViews();
+ for (var i = 0; i < views.length; i++) {
+ views[i].respond(document.getElementById("me").innerHTML);
+ }
+}
+
+function respond(val) {
+ var me = document.getElementById("me");
+ if (val == me.innerHTML) {
+ me.className = "strong";
+ } else {
+ me.className = "weak";
+ }
+}
\ No newline at end of file diff --git a/chrome/test/data/extensions/samples/getviews/manifest.json b/chrome/test/data/extensions/samples/getviews/manifest.json new file mode 100755 index 0000000..84e18b1 --- /dev/null +++ b/chrome/test/data/extensions/samples/getviews/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "ViewTest", + "description": "Clicking on any toolstrip or background page should 'claim' the 'strong' typeface from the others by calling claim() directly on their window objects", + "version": "0.1", + "toolstrips": ["ts1.html", "ts2.html"], + "background_page": "bg.html" +} diff --git a/chrome/test/data/extensions/samples/getviews/ts1.html b/chrome/test/data/extensions/samples/getviews/ts1.html new file mode 100755 index 0000000..df2b006 --- /dev/null +++ b/chrome/test/data/extensions/samples/getviews/ts1.html @@ -0,0 +1,9 @@ +<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="common.css">
+ <script src="common.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <div span id="me" onclick="claim();">Toolstrip 1</div>
+ </body>
+</html>
\ No newline at end of file diff --git a/chrome/test/data/extensions/samples/getviews/ts2.html b/chrome/test/data/extensions/samples/getviews/ts2.html new file mode 100755 index 0000000..f5ee37e --- /dev/null +++ b/chrome/test/data/extensions/samples/getviews/ts2.html @@ -0,0 +1,9 @@ +<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="common.css">
+ <script src="common.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <div span id="me" onclick="claim();">Toolstrip 2</div>
+ </body>
+</html>
\ No newline at end of file |