Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Unified Diff: chrome/browser/extensions/api/messaging/extension_message_port.cc

Issue 1413543005: Use FrameTreeNode ID as frameId in extension APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/:/ / Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/messaging/extension_message_port.cc
diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.cc b/chrome/browser/extensions/api/messaging/extension_message_port.cc
index 1e4f87f901d6234975f9d3a6dccfcf139172fd3b..a22568f956a5f380d8481f1aefd13e875d3783de 100644
--- a/chrome/browser/extensions/api/messaging/extension_message_port.cc
+++ b/chrome/browser/extensions/api/messaging/extension_message_port.cc
@@ -4,31 +4,121 @@
#include "chrome/browser/extensions/api/messaging/extension_message_port.h"
+#include "base/scoped_observer.h"
#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/process_manager.h"
+#include "extensions/browser/process_manager_observer.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_handlers/background_info.h"
namespace extensions {
-ExtensionMessagePort::ExtensionMessagePort(content::RenderProcessHost* process,
- int routing_id,
- const std::string& extension_id)
- : process_(process),
- routing_id_(routing_id),
- extension_id_(extension_id),
- background_host_ptr_(NULL) {
+const char kReceivingEndDoesntExistError[] =
+ "Could not establish connection. Receiving end does not exist.";
+
+// Helper class to detect when frames are destroyed.
+class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
+ public ProcessManagerObserver {
+ public:
+ explicit FrameTracker(ExtensionMessagePort* port)
+ : pm_observer_(this), port_(port) {}
+ ~FrameTracker() override {}
+
+ void TrackExtensionProcessFrames() {
+ pm_observer_.Add(ProcessManager::Get(port_->browser_context_));
+ }
+
+ void TrackTabFrames(content::WebContents* tab) {
+ Observe(tab);
+ }
+
+ private:
+ // content::WebContentsObserver overrides:
+ void RenderFrameDeleted(content::RenderFrameHost* render_frame_host)
+ override {
+ port_->UnregisterFrame(render_frame_host);
+ }
+
+ void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host,
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams&) override {
+ if (!details.is_in_page)
+ port_->UnregisterFrame(render_frame_host);
+ }
+
+ // extensions::ProcessManagerObserver overrides:
+ void OnExtensionFrameUnregistered(
+ const std::string& extension_id,
+ content::RenderFrameHost* render_frame_host) override {
+ if (extension_id == port_->extension_id_)
+ port_->UnregisterFrame(render_frame_host);
+ }
+
+ ScopedObserver<ProcessManager, ProcessManagerObserver> pm_observer_;
+ ExtensionMessagePort* port_; // Owns this FrameTracker.
+
+ DISALLOW_COPY_AND_ASSIGN(FrameTracker);
+};
+
+ExtensionMessagePort::ExtensionMessagePort(
+ base::WeakPtr<MessageService> message_service,
+ int port_id,
+ const std::string& extension_id,
+ content::RenderProcessHost* extension_process)
+ : weak_message_service_(message_service),
+ port_id_(port_id),
+ extension_id_(extension_id),
+ browser_context_(extension_process->GetBrowserContext()),
+ extension_process_(extension_process),
+ frames_(ProcessManager::Get(browser_context_)->
+ GetRenderFrameHostsForExtension(extension_id)),
+ did_create_port_(false),
+ background_host_ptr_(nullptr),
+ frame_tracker_(new FrameTracker(this)) {
+ frame_tracker_->TrackExtensionProcessFrames();
+}
+
+ExtensionMessagePort::ExtensionMessagePort(
+ base::WeakPtr<MessageService> message_service,
+ int port_id,
+ const std::string& extension_id,
+ content::RenderFrameHost* rfh,
+ bool include_child_frames)
+ : weak_message_service_(message_service),
+ port_id_(port_id),
+ extension_id_(extension_id),
+ browser_context_(rfh->GetProcess()->GetBrowserContext()),
+ extension_process_(nullptr),
+ did_create_port_(false),
+ background_host_ptr_(nullptr),
+ frame_tracker_(new FrameTracker(this)) {
+ content::WebContents* tab = content::WebContents::FromRenderFrameHost(rfh);
+ DCHECK(tab);
+ frame_tracker_->TrackTabFrames(tab);
+ if (include_child_frames) {
+ tab->ForEachFrame(base::Bind(&ExtensionMessagePort::RegisterFrame,
+ base::Unretained(this)));
+ } else {
+ RegisterFrame(rfh);
+ }
+}
+
+ExtensionMessagePort::~ExtensionMessagePort() {}
+
+bool ExtensionMessagePort::IsValidPort() {
+ return !frames_.empty();
}
void ExtensionMessagePort::DispatchOnConnect(
- int dest_port_id,
const std::string& channel_name,
scoped_ptr<base::DictionaryValue> source_tab,
int source_frame_id,
- int target_tab_id,
- int target_frame_id,
int guest_process_id,
int guest_render_frame_routing_id,
const std::string& source_extension_id,
@@ -44,32 +134,26 @@ void ExtensionMessagePort::DispatchOnConnect(
info.target_id = target_extension_id;
info.source_id = source_extension_id;
info.source_url = source_url;
- info.target_tab_id = target_tab_id;
- info.target_frame_id = target_frame_id;
info.guest_process_id = guest_process_id;
info.guest_render_frame_routing_id = guest_render_frame_routing_id;
- process_->Send(new ExtensionMsg_DispatchOnConnect(
- routing_id_, dest_port_id, channel_name, source, info, tls_channel_id));
+ SendToPort(make_scoped_ptr(new ExtensionMsg_DispatchOnConnect(
+ MSG_ROUTING_NONE, port_id_, channel_name, source, info, tls_channel_id)));
}
void ExtensionMessagePort::DispatchOnDisconnect(
- int source_port_id,
const std::string& error_message) {
- process_->Send(new ExtensionMsg_DispatchOnDisconnect(
- routing_id_, source_port_id, error_message));
+ SendToPort(make_scoped_ptr(new ExtensionMsg_DispatchOnDisconnect(
+ MSG_ROUTING_NONE, port_id_, error_message)));
}
-void ExtensionMessagePort::DispatchOnMessage(const Message& message,
- int target_port_id) {
- process_->Send(new ExtensionMsg_DeliverMessage(
- routing_id_, target_port_id, message));
+void ExtensionMessagePort::DispatchOnMessage(const Message& message) {
+ SendToPort(make_scoped_ptr(new ExtensionMsg_DeliverMessage(
+ MSG_ROUTING_NONE, port_id_, message)));
}
void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
- Profile* profile =
- Profile::FromBrowserContext(process_->GetBrowserContext());
- extensions::ProcessManager* pm = ProcessManager::Get(profile);
+ ProcessManager* pm = ProcessManager::Get(browser_context_);
ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension()))
pm->IncrementLazyKeepaliveCount(host->extension());
@@ -80,16 +164,66 @@ void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
}
void ExtensionMessagePort::DecrementLazyKeepaliveCount() {
- Profile* profile =
- Profile::FromBrowserContext(process_->GetBrowserContext());
- extensions::ProcessManager* pm = ProcessManager::Get(profile);
+ ProcessManager* pm = ProcessManager::Get(browser_context_);
ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
if (host && host == background_host_ptr_)
pm->DecrementLazyKeepaliveCount(host->extension());
}
-content::RenderProcessHost* ExtensionMessagePort::GetRenderProcessHost() {
- return process_;
+void ExtensionMessagePort::OpenPort(int process_id, int routing_id) {
+ DCHECK(routing_id != MSG_ROUTING_NONE || extension_process_);
+
+ did_create_port_ = true;
+}
+
+void ExtensionMessagePort::ClosePort(int process_id, int routing_id) {
+ if (routing_id == MSG_ROUTING_NONE) {
+ // The only non-frame-specific message is the response to an unhandled
+ // onConnect event in the extension process.
+ DCHECK(extension_process_);
+ frames_.clear();
+ CloseChannel();
+ return;
+ }
+
+ content::RenderFrameHost* rfh =
+ content::RenderFrameHost::FromID(process_id, routing_id);
+ if (rfh)
+ UnregisterFrame(rfh);
+}
+
+void ExtensionMessagePort::CloseChannel() {
+ std::string error_message = did_create_port_ ? std::string() :
+ kReceivingEndDoesntExistError;
+ if (weak_message_service_)
+ weak_message_service_->CloseChannel(port_id_, error_message);
+}
+
+void ExtensionMessagePort::RegisterFrame(content::RenderFrameHost* rfh) {
+ frames_.insert(rfh);
+}
+
+void ExtensionMessagePort::UnregisterFrame(content::RenderFrameHost* rfh) {
+ if (frames_.erase(rfh) != 0 && frames_.empty())
+ CloseChannel();
+}
+
+void ExtensionMessagePort::SendToPort(scoped_ptr<IPC::Message> msg) {
+ DCHECK_GT(frames_.size(), 0UL);
+ if (extension_process_) {
+ // All extension frames reside in the same process, so we can just send a
+ // single IPC message to the extension process as an optimization.
+ // The frame tracking is then only used to make sure that the port gets
+ // closed when all frames have closed / reloaded.
+ msg->set_routing_id(MSG_ROUTING_CONTROL);
+ extension_process_->Send(msg.release());
+ return;
+ }
+ for (content::RenderFrameHost* rfh : frames_) {
+ IPC::Message* msg_copy = new IPC::Message(*msg.get());
+ msg_copy->set_routing_id(rfh->GetRoutingID());
+ rfh->Send(msg_copy);
+ }
}
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698