diff options
author | rob <rob@robwu.nl> | 2016-01-06 13:22:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-06 21:22:58 +0000 |
commit | 3e2a0730e0dfb9c4dcbce45eea275270db900e90 (patch) | |
tree | bb5daf2237e4791771a94c2341d8764a7fe7d7b7 /extensions/renderer/messaging_bindings.cc | |
parent | 8bdc571018faac493cb358ea1f8b7314b9178aa4 (diff) | |
download | chromium_src-3e2a0730e0dfb9c4dcbce45eea275270db900e90.zip chromium_src-3e2a0730e0dfb9c4dcbce45eea275270db900e90.tar.gz chromium_src-3e2a0730e0dfb9c4dcbce45eea275270db900e90.tar.bz2 |
Use FrameTreeNode ID as frameId in extension APIs
Use FrameTreeNode IDs instead of RenderFrame routing IDs as "frame id"
in the extension APIs (webNavigation, webRequest, extension messaging)
because FTN IDs are globally unique, and RFH IDs are not.
This extends the public content API with:
- RenderFrameHost::FromFrameTreeNodeId
- RenderFrameHost::GetFrameTreeNodeId
- WebContents::FindFrameByFrameTreeNodeId
The extension APIs are modified as follows:
- webRequest:
* Frame IDs may be unavailable after frame removal (crbug.com/572930).
* Blocking webRequest handlers may be slower than before due to an
extra IO->UI->IO hop to determine the frameId (but this happens only
once per frame load).
- webNavigation:
* processId is no longer required in chrome.webNavigation.getFrame,
but marked as optional (deprecated) to make sure that the API is
backwards-compatible.
* frameId is constant across navigations.
- Extension messaging (chrome.runtime.connect and friends):
* Small change for extension developers in the following scenario:
1. Open port to tab.
2. Accept the port by listening to onConnect *in a child frame*.
3. Unload the document in the frame.
Old behavior: onDisconnect was not triggered in the background until
the tab was reloaded or closed.
New behavior: onDisconnect is called.
* Extension messaging works correctly in out-of-process frames.
* Move port lifetime management from renderer to browser.
* Tie port lifetime to frames instead of processes.
* Only notify frames in renderers if they have accepted the port.
* Remove obsolete work-around for crbug.com/520303.
* Unify open/close/postMessage logic in ChromeExtensionMessageFilter
(crbug.com/394383#c7)
- The extension frameId logic is no longer scattered over several files,
but resides in a single class (ExtensionApiFrameIdMap).
- IDs are now guaranteed to be -1 or higher (before this, -2 was
occasionally seen).
Depends on https://codereview.chromium.org/1413853005/
BUG=432875
TEST=browser_tests --gtest_filter=\
ExtensionWebRequestApiTest.*:\
WebNavigationApiTest.*:\
ExtensionApiTest.Messaging*:\
ExternallyConnectableMessagingTest.*:\
ExternallyConnectableMessagingWithTlsChannelIdTest.*
Review URL: https://codereview.chromium.org/1413543005
Cr-Commit-Position: refs/heads/master@{#367914}
Diffstat (limited to 'extensions/renderer/messaging_bindings.cc')
-rw-r--r-- | extensions/renderer/messaging_bindings.cc | 59 |
1 files changed, 23 insertions, 36 deletions
diff --git a/extensions/renderer/messaging_bindings.cc b/extensions/renderer/messaging_bindings.cc index a0a855f..722bc72 100644 --- a/extensions/renderer/messaging_bindings.cc +++ b/extensions/renderer/messaging_bindings.cc @@ -130,8 +130,6 @@ class PortTracker { base::LazyInstance<PortTracker> g_port_tracker = LAZY_INSTANCE_INITIALIZER; const char kPortClosedError[] = "Attempting to use a disconnected port object"; -const char kReceivingEndDoesntExistError[] = - "Could not establish connection. Receiving end does not exist."; class ExtensionImpl : public ObjectBackedNativeHandler { public: @@ -175,8 +173,8 @@ class ExtensionImpl : public ObjectBackedNativeHandler { // Sends a message along the given channel. void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { - content::RenderFrame* renderframe = context()->GetRenderFrame(); - if (!renderframe) + content::RenderFrame* render_frame = context()->GetRenderFrame(); + if (!render_frame) return; // Arguments are (int32_t port_id, string message). @@ -190,8 +188,8 @@ class ExtensionImpl : public ObjectBackedNativeHandler { return; } - renderframe->Send(new ExtensionHostMsg_PostMessage( - renderframe->GetRoutingID(), port_id, + render_frame->Send(new ExtensionHostMsg_PostMessage( + render_frame->GetRoutingID(), port_id, Message(*v8::String::Utf8Value(args[1]), blink::WebUserGestureIndicator::isProcessingUserGesture()))); } @@ -209,9 +207,10 @@ class ExtensionImpl : public ObjectBackedNativeHandler { // Send via the RenderThread because the RenderFrame might be closing. bool notify_browser = args[1].As<v8::Boolean>()->Value(); - if (notify_browser) { - content::RenderThread::Get()->Send( - new ExtensionHostMsg_CloseChannel(port_id, std::string())); + content::RenderFrame* render_frame = context()->GetRenderFrame(); + if (notify_browser && render_frame) { + render_frame->Send(new ExtensionHostMsg_CloseMessagePort( + render_frame->GetRoutingID(), port_id, true)); } ClearPortDataAndNotifyDispatcher(port_id); @@ -231,6 +230,8 @@ class ExtensionImpl : public ObjectBackedNativeHandler { // The frame a port lived in has been destroyed. When there are no more // frames with a reference to a given port, we will disconnect it and notify // the other end of the channel. + // TODO(robwu): Port lifetime management has moved to the browser, this is no + // longer needed. See .destroy_() inmessaging.js for more details. void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) { // Arguments are (int32_t port_id). CHECK(args.Length() == 1 && args[0]->IsInt32()); @@ -240,12 +241,11 @@ class ExtensionImpl : public ObjectBackedNativeHandler { // Releases the reference to |port_id| for this context, and clears all port // data if there are no more references. void ReleasePort(int port_id) { + content::RenderFrame* render_frame = context()->GetRenderFrame(); if (g_port_tracker.Get().RemoveReference(context(), port_id) && - !g_port_tracker.Get().HasPort(port_id)) { - // Send via the RenderThread because the RenderFrame might be closing. - content::RenderThread::Get()->Send( - new ExtensionHostMsg_CloseChannel(port_id, std::string())); - ClearPortDataAndNotifyDispatcher(port_id); + !g_port_tracker.Get().HasPort(port_id) && render_frame) { + render_frame->Send(new ExtensionHostMsg_CloseMessagePort( + render_frame->GetRoutingID(), port_id, false)); } } @@ -286,23 +286,6 @@ void DispatchOnConnectToScriptContext( const std::string& tls_channel_id, bool* port_created, ScriptContext* script_context) { - // Only dispatch the events if this is the requested target frame (0 = main - // frame; positive = child frame). - content::RenderFrame* renderframe = script_context->GetRenderFrame(); - if (info.target_frame_id == 0 && renderframe->GetWebFrame()->parent() != NULL) - return; - if (info.target_frame_id > 0 && - renderframe->GetRoutingID() != info.target_frame_id) - return; - - // Bandaid fix for crbug.com/520303. - // TODO(rdevlin.cronin): Fix this properly by routing messages to the correct - // RenderFrame from the browser (same with |target_frame_id| in fact). - if (info.target_tab_id != -1 && - info.target_tab_id != ExtensionFrameHelper::Get(renderframe)->tab_id()) { - return; - } - v8::Isolate* isolate = script_context->isolate(); v8::HandleScope handle_scope(isolate); @@ -472,11 +455,15 @@ void MessagingBindings::DispatchOnConnect( base::Bind(&DispatchOnConnectToScriptContext, target_port_id, channel_name, &source, info, tls_channel_id, &port_created)); - // If we didn't create a port, notify the other end of the channel (treat it - // as a disconnect). - if (!port_created) { - content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseChannel( - target_port_id, kReceivingEndDoesntExistError)); + int routing_id = restrict_to_render_frame + ? restrict_to_render_frame->GetRoutingID() + : MSG_ROUTING_NONE; + if (port_created) { + content::RenderThread::Get()->Send( + new ExtensionHostMsg_OpenMessagePort(routing_id, target_port_id)); + } else { + content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseMessagePort( + routing_id, target_port_id, false)); } } |