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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" 5 #include "chrome/browser/extensions/api/messaging/extension_message_port.h"
6 6
7 #include "base/scoped_observer.h"
7 #include "chrome/browser/profiles/profile.h" 8 #include "chrome/browser/profiles/profile.h"
9 #include "content/public/browser/navigation_details.h"
10 #include "content/public/browser/render_frame_host.h"
8 #include "content/public/browser/render_process_host.h" 11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/web_contents.h"
13 #include "content/public/browser/web_contents_observer.h"
9 #include "extensions/browser/extension_host.h" 14 #include "extensions/browser/extension_host.h"
10 #include "extensions/browser/process_manager.h" 15 #include "extensions/browser/process_manager.h"
16 #include "extensions/browser/process_manager_observer.h"
11 #include "extensions/common/extension_messages.h" 17 #include "extensions/common/extension_messages.h"
12 #include "extensions/common/manifest_handlers/background_info.h" 18 #include "extensions/common/manifest_handlers/background_info.h"
13 19
14 namespace extensions { 20 namespace extensions {
15 21
16 ExtensionMessagePort::ExtensionMessagePort(content::RenderProcessHost* process, 22 const char kReceivingEndDoesntExistError[] =
17 int routing_id, 23 "Could not establish connection. Receiving end does not exist.";
18 const std::string& extension_id) 24
19 : process_(process), 25 // Helper class to detect when frames are destroyed.
20 routing_id_(routing_id), 26 class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
21 extension_id_(extension_id), 27 public ProcessManagerObserver {
22 background_host_ptr_(NULL) { 28 public:
29 explicit FrameTracker(ExtensionMessagePort* port)
30 : pm_observer_(this), port_(port) {}
31 ~FrameTracker() override {}
32
33 void TrackExtensionProcessFrames() {
34 pm_observer_.Add(ProcessManager::Get(port_->browser_context_));
35 }
36
37 void TrackTabFrames(content::WebContents* tab) {
38 Observe(tab);
39 }
40
41 private:
42 // content::WebContentsObserver overrides:
43 void RenderFrameDeleted(content::RenderFrameHost* render_frame_host)
44 override {
45 port_->UnregisterFrame(render_frame_host);
46 }
47
48 void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host,
49 const content::LoadCommittedDetails& details,
50 const content::FrameNavigateParams&) override {
51 if (!details.is_in_page)
52 port_->UnregisterFrame(render_frame_host);
53 }
54
55 // extensions::ProcessManagerObserver overrides:
56 void OnExtensionFrameUnregistered(
57 const std::string& extension_id,
58 content::RenderFrameHost* render_frame_host) override {
59 if (extension_id == port_->extension_id_)
60 port_->UnregisterFrame(render_frame_host);
61 }
62
63 ScopedObserver<ProcessManager, ProcessManagerObserver> pm_observer_;
64 ExtensionMessagePort* port_; // Owns this FrameTracker.
65
66 DISALLOW_COPY_AND_ASSIGN(FrameTracker);
67 };
68
69 ExtensionMessagePort::ExtensionMessagePort(
70 base::WeakPtr<MessageService> message_service,
71 int port_id,
72 const std::string& extension_id,
73 content::RenderProcessHost* extension_process)
74 : weak_message_service_(message_service),
75 port_id_(port_id),
76 extension_id_(extension_id),
77 browser_context_(extension_process->GetBrowserContext()),
78 extension_process_(extension_process),
79 frames_(ProcessManager::Get(browser_context_)->
80 GetRenderFrameHostsForExtension(extension_id)),
81 did_create_port_(false),
82 background_host_ptr_(nullptr),
83 frame_tracker_(new FrameTracker(this)) {
84 frame_tracker_->TrackExtensionProcessFrames();
85 }
86
87 ExtensionMessagePort::ExtensionMessagePort(
88 base::WeakPtr<MessageService> message_service,
89 int port_id,
90 const std::string& extension_id,
91 content::RenderFrameHost* rfh,
92 bool include_child_frames)
93 : weak_message_service_(message_service),
94 port_id_(port_id),
95 extension_id_(extension_id),
96 browser_context_(rfh->GetProcess()->GetBrowserContext()),
97 extension_process_(nullptr),
98 did_create_port_(false),
99 background_host_ptr_(nullptr),
100 frame_tracker_(new FrameTracker(this)) {
101 content::WebContents* tab = content::WebContents::FromRenderFrameHost(rfh);
102 DCHECK(tab);
103 frame_tracker_->TrackTabFrames(tab);
104 if (include_child_frames) {
105 tab->ForEachFrame(base::Bind(&ExtensionMessagePort::RegisterFrame,
106 base::Unretained(this)));
107 } else {
108 RegisterFrame(rfh);
109 }
110 }
111
112 ExtensionMessagePort::~ExtensionMessagePort() {}
113
114 bool ExtensionMessagePort::IsValidPort() {
115 return !frames_.empty();
23 } 116 }
24 117
25 void ExtensionMessagePort::DispatchOnConnect( 118 void ExtensionMessagePort::DispatchOnConnect(
26 int dest_port_id,
27 const std::string& channel_name, 119 const std::string& channel_name,
28 scoped_ptr<base::DictionaryValue> source_tab, 120 scoped_ptr<base::DictionaryValue> source_tab,
29 int source_frame_id, 121 int source_frame_id,
30 int target_tab_id,
31 int target_frame_id,
32 int guest_process_id, 122 int guest_process_id,
33 int guest_render_frame_routing_id, 123 int guest_render_frame_routing_id,
34 const std::string& source_extension_id, 124 const std::string& source_extension_id,
35 const std::string& target_extension_id, 125 const std::string& target_extension_id,
36 const GURL& source_url, 126 const GURL& source_url,
37 const std::string& tls_channel_id) { 127 const std::string& tls_channel_id) {
38 ExtensionMsg_TabConnectionInfo source; 128 ExtensionMsg_TabConnectionInfo source;
39 if (source_tab) 129 if (source_tab)
40 source.tab.Swap(source_tab.get()); 130 source.tab.Swap(source_tab.get());
41 source.frame_id = source_frame_id; 131 source.frame_id = source_frame_id;
42 132
43 ExtensionMsg_ExternalConnectionInfo info; 133 ExtensionMsg_ExternalConnectionInfo info;
44 info.target_id = target_extension_id; 134 info.target_id = target_extension_id;
45 info.source_id = source_extension_id; 135 info.source_id = source_extension_id;
46 info.source_url = source_url; 136 info.source_url = source_url;
47 info.target_tab_id = target_tab_id;
48 info.target_frame_id = target_frame_id;
49 info.guest_process_id = guest_process_id; 137 info.guest_process_id = guest_process_id;
50 info.guest_render_frame_routing_id = guest_render_frame_routing_id; 138 info.guest_render_frame_routing_id = guest_render_frame_routing_id;
51 139
52 process_->Send(new ExtensionMsg_DispatchOnConnect( 140 SendToPort(make_scoped_ptr(new ExtensionMsg_DispatchOnConnect(
53 routing_id_, dest_port_id, channel_name, source, info, tls_channel_id)); 141 MSG_ROUTING_NONE, port_id_, channel_name, source, info, tls_channel_id)));
54 } 142 }
55 143
56 void ExtensionMessagePort::DispatchOnDisconnect( 144 void ExtensionMessagePort::DispatchOnDisconnect(
57 int source_port_id,
58 const std::string& error_message) { 145 const std::string& error_message) {
59 process_->Send(new ExtensionMsg_DispatchOnDisconnect( 146 SendToPort(make_scoped_ptr(new ExtensionMsg_DispatchOnDisconnect(
60 routing_id_, source_port_id, error_message)); 147 MSG_ROUTING_NONE, port_id_, error_message)));
61 } 148 }
62 149
63 void ExtensionMessagePort::DispatchOnMessage(const Message& message, 150 void ExtensionMessagePort::DispatchOnMessage(const Message& message) {
64 int target_port_id) { 151 SendToPort(make_scoped_ptr(new ExtensionMsg_DeliverMessage(
65 process_->Send(new ExtensionMsg_DeliverMessage( 152 MSG_ROUTING_NONE, port_id_, message)));
66 routing_id_, target_port_id, message));
67 } 153 }
68 154
69 void ExtensionMessagePort::IncrementLazyKeepaliveCount() { 155 void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
70 Profile* profile = 156 ProcessManager* pm = ProcessManager::Get(browser_context_);
71 Profile::FromBrowserContext(process_->GetBrowserContext());
72 extensions::ProcessManager* pm = ProcessManager::Get(profile);
73 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_); 157 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
74 if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension())) 158 if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension()))
75 pm->IncrementLazyKeepaliveCount(host->extension()); 159 pm->IncrementLazyKeepaliveCount(host->extension());
76 160
77 // Keep track of the background host, so when we decrement, we only do so if 161 // Keep track of the background host, so when we decrement, we only do so if
78 // the host hasn't reloaded. 162 // the host hasn't reloaded.
79 background_host_ptr_ = host; 163 background_host_ptr_ = host;
80 } 164 }
81 165
82 void ExtensionMessagePort::DecrementLazyKeepaliveCount() { 166 void ExtensionMessagePort::DecrementLazyKeepaliveCount() {
83 Profile* profile = 167 ProcessManager* pm = ProcessManager::Get(browser_context_);
84 Profile::FromBrowserContext(process_->GetBrowserContext());
85 extensions::ProcessManager* pm = ProcessManager::Get(profile);
86 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_); 168 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
87 if (host && host == background_host_ptr_) 169 if (host && host == background_host_ptr_)
88 pm->DecrementLazyKeepaliveCount(host->extension()); 170 pm->DecrementLazyKeepaliveCount(host->extension());
89 } 171 }
90 172
91 content::RenderProcessHost* ExtensionMessagePort::GetRenderProcessHost() { 173 void ExtensionMessagePort::OpenPort(int process_id, int routing_id) {
92 return process_; 174 DCHECK(routing_id != MSG_ROUTING_NONE || extension_process_);
175
176 did_create_port_ = true;
177 }
178
179 void ExtensionMessagePort::ClosePort(int process_id, int routing_id) {
180 if (routing_id == MSG_ROUTING_NONE) {
181 // The only non-frame-specific message is the response to an unhandled
182 // onConnect event in the extension process.
183 DCHECK(extension_process_);
184 frames_.clear();
185 CloseChannel();
186 return;
187 }
188
189 content::RenderFrameHost* rfh =
190 content::RenderFrameHost::FromID(process_id, routing_id);
191 if (rfh)
192 UnregisterFrame(rfh);
193 }
194
195 void ExtensionMessagePort::CloseChannel() {
196 std::string error_message = did_create_port_ ? std::string() :
197 kReceivingEndDoesntExistError;
198 if (weak_message_service_)
199 weak_message_service_->CloseChannel(port_id_, error_message);
200 }
201
202 void ExtensionMessagePort::RegisterFrame(content::RenderFrameHost* rfh) {
203 frames_.insert(rfh);
204 }
205
206 void ExtensionMessagePort::UnregisterFrame(content::RenderFrameHost* rfh) {
207 if (frames_.erase(rfh) != 0 && frames_.empty())
208 CloseChannel();
209 }
210
211 void ExtensionMessagePort::SendToPort(scoped_ptr<IPC::Message> msg) {
212 DCHECK_GT(frames_.size(), 0UL);
213 if (extension_process_) {
214 // All extension frames reside in the same process, so we can just send a
215 // single IPC message to the extension process as an optimization.
216 // The frame tracking is then only used to make sure that the port gets
217 // closed when all frames have closed / reloaded.
218 msg->set_routing_id(MSG_ROUTING_CONTROL);
219 extension_process_->Send(msg.release());
220 return;
221 }
222 for (content::RenderFrameHost* rfh : frames_) {
223 IPC::Message* msg_copy = new IPC::Message(*msg.get());
224 msg_copy->set_routing_id(rfh->GetRoutingID());
225 rfh->Send(msg_copy);
226 }
93 } 227 }
94 228
95 } // namespace extensions 229 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698