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

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: Vend frameIds at 1 location; minimize thread hops for webRequest Created 5 years 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) {}
Devlin 2015/12/10 21:53:06 Add an explicit destructor.
robwu 2015/12/11 00:53:47 Done.
31
32 void TrackExtensionProcessFrames() {
33 pm_observer_.Add(ProcessManager::Get(port_->browser_context_));
34 }
35
36 void TrackTabFrames(content::WebContents* tab) {
37 Observe(tab);
38 }
39
40 private:
41 // content::WebContentsObserver overrides:
42 void RenderFrameDeleted(content::RenderFrameHost* render_frame_host)
43 override {
44 port_->UnregisterFrame(render_frame_host);
45 }
46
47 void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host,
48 const content::LoadCommittedDetails& details,
49 const content::FrameNavigateParams&) override {
50 if (!details.is_in_page)
51 port_->UnregisterFrame(render_frame_host);
52 }
53
54 // extensions::ProcessManagerObserver overrides:
55 void OnExtensionFrameUnregistered(
56 const std::string& extension_id,
57 content::RenderFrameHost* render_frame_host) override {
58 if (extension_id == port_->extension_id_)
59 port_->UnregisterFrame(render_frame_host);
60 }
61
62 ScopedObserver<ProcessManager, ProcessManagerObserver> pm_observer_;
63 ExtensionMessagePort* port_; // Owns this FrameTracker.
64
65 DISALLOW_COPY_AND_ASSIGN(FrameTracker);
66 };
67
68 ExtensionMessagePort::ExtensionMessagePort(
69 base::WeakPtr<MessageService> message_service,
70 int port_id,
71 const std::string& extension_id,
72 content::RenderProcessHost* extension_process)
73 : weak_message_service_(message_service),
74 port_id_(port_id),
75 extension_id_(extension_id),
76 did_create_port_(false),
77 browser_context_(extension_process->GetBrowserContext()),
78 frames_(ProcessManager::Get(browser_context_)->
79 GetRenderFrameHostsForExtension(extension_id)),
80 extension_process_(extension_process),
81 background_host_ptr_(nullptr),
82 frame_tracker_(new FrameTracker(this)) {
83 frame_tracker_->TrackExtensionProcessFrames();
84 }
85
86 ExtensionMessagePort::ExtensionMessagePort(
87 base::WeakPtr<MessageService> message_service,
88 int port_id,
89 const std::string& extension_id,
90 content::RenderFrameHost* rfh,
91 bool include_child_frames)
92 : weak_message_service_(message_service),
93 port_id_(port_id),
94 extension_id_(extension_id),
95 did_create_port_(false),
96 browser_context_(rfh->GetProcess()->GetBrowserContext()),
97 extension_process_(nullptr),
98 background_host_ptr_(nullptr),
99 frame_tracker_(new FrameTracker(this)) {
100 content::WebContents* tab = content::WebContents::FromRenderFrameHost(rfh);
101 DCHECK(tab);
102 frame_tracker_->TrackTabFrames(tab);
103 if (include_child_frames) {
104 tab->ForEachFrame(base::Bind(&ExtensionMessagePort::RegisterFrame,
105 base::Unretained(this)));
106 } else {
107 RegisterFrame(rfh);
108 }
109 }
110
111 ExtensionMessagePort::~ExtensionMessagePort() {}
112
113 bool ExtensionMessagePort::IsValidPort() {
114 return !frames_.empty();
23 } 115 }
24 116
25 void ExtensionMessagePort::DispatchOnConnect( 117 void ExtensionMessagePort::DispatchOnConnect(
26 int dest_port_id,
27 const std::string& channel_name, 118 const std::string& channel_name,
28 scoped_ptr<base::DictionaryValue> source_tab, 119 scoped_ptr<base::DictionaryValue> source_tab,
29 int source_frame_id, 120 int source_frame_id,
30 int target_tab_id,
31 int target_frame_id,
32 int guest_process_id, 121 int guest_process_id,
33 int guest_render_frame_routing_id, 122 int guest_render_frame_routing_id,
34 const std::string& source_extension_id, 123 const std::string& source_extension_id,
35 const std::string& target_extension_id, 124 const std::string& target_extension_id,
36 const GURL& source_url, 125 const GURL& source_url,
37 const std::string& tls_channel_id) { 126 const std::string& tls_channel_id) {
38 ExtensionMsg_TabConnectionInfo source; 127 ExtensionMsg_TabConnectionInfo source;
39 if (source_tab) 128 if (source_tab)
40 source.tab.Swap(source_tab.get()); 129 source.tab.Swap(source_tab.get());
41 source.frame_id = source_frame_id; 130 source.frame_id = source_frame_id;
42 131
43 ExtensionMsg_ExternalConnectionInfo info; 132 ExtensionMsg_ExternalConnectionInfo info;
44 info.target_id = target_extension_id; 133 info.target_id = target_extension_id;
45 info.source_id = source_extension_id; 134 info.source_id = source_extension_id;
46 info.source_url = source_url; 135 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; 136 info.guest_process_id = guest_process_id;
50 info.guest_render_frame_routing_id = guest_render_frame_routing_id; 137 info.guest_render_frame_routing_id = guest_render_frame_routing_id;
51 138
52 process_->Send(new ExtensionMsg_DispatchOnConnect( 139 SendToPort(new ExtensionMsg_DispatchOnConnect(
53 routing_id_, dest_port_id, channel_name, source, info, tls_channel_id)); 140 MSG_ROUTING_NONE, port_id_, channel_name, source, info, tls_channel_id));
54 } 141 }
55 142
56 void ExtensionMessagePort::DispatchOnDisconnect( 143 void ExtensionMessagePort::DispatchOnDisconnect(
57 int source_port_id,
58 const std::string& error_message) { 144 const std::string& error_message) {
59 process_->Send(new ExtensionMsg_DispatchOnDisconnect( 145 SendToPort(new ExtensionMsg_DispatchOnDisconnect(
60 routing_id_, source_port_id, error_message)); 146 MSG_ROUTING_NONE, port_id_, error_message));
61 } 147 }
62 148
63 void ExtensionMessagePort::DispatchOnMessage(const Message& message, 149 void ExtensionMessagePort::DispatchOnMessage(const Message& message) {
64 int target_port_id) { 150 SendToPort(new ExtensionMsg_DeliverMessage(
65 process_->Send(new ExtensionMsg_DeliverMessage( 151 MSG_ROUTING_NONE, port_id_, message));
66 routing_id_, target_port_id, message));
67 } 152 }
68 153
69 void ExtensionMessagePort::IncrementLazyKeepaliveCount() { 154 void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
70 Profile* profile = 155 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_); 156 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
74 if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension())) 157 if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension()))
75 pm->IncrementLazyKeepaliveCount(host->extension()); 158 pm->IncrementLazyKeepaliveCount(host->extension());
76 159
77 // Keep track of the background host, so when we decrement, we only do so if 160 // Keep track of the background host, so when we decrement, we only do so if
78 // the host hasn't reloaded. 161 // the host hasn't reloaded.
79 background_host_ptr_ = host; 162 background_host_ptr_ = host;
80 } 163 }
81 164
82 void ExtensionMessagePort::DecrementLazyKeepaliveCount() { 165 void ExtensionMessagePort::DecrementLazyKeepaliveCount() {
83 Profile* profile = 166 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_); 167 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
87 if (host && host == background_host_ptr_) 168 if (host && host == background_host_ptr_)
88 pm->DecrementLazyKeepaliveCount(host->extension()); 169 pm->DecrementLazyKeepaliveCount(host->extension());
89 } 170 }
90 171
91 content::RenderProcessHost* ExtensionMessagePort::GetRenderProcessHost() { 172 void ExtensionMessagePort::OpenPort(int process_id, int routing_id) {
92 return process_; 173 DCHECK(routing_id != MSG_ROUTING_NONE || extension_process_);
174
175 // Mark port as active, so we can distinguish abnormal port closure from
176 // explicit port closure via disconnect().
177 did_create_port_ = true;
178 }
179
180 void ExtensionMessagePort::ClosePort(int process_id, int routing_id) {
181 if (routing_id == MSG_ROUTING_NONE) {
182 // The only non-frame-specific message is the response to an unhandled
183 // onConnect event in the extension process.
184 DCHECK(extension_process_);
185 frames_.clear();
186 CloseChannel();
187 return;
188 }
189
190 content::RenderFrameHost* rfh =
191 content::RenderFrameHost::FromID(process_id, routing_id);
192 if (rfh)
193 UnregisterFrame(rfh);
194 }
195
196 void ExtensionMessagePort::CloseChannel() {
197 std::string error_message = did_create_port_ ? std::string() :
198 kReceivingEndDoesntExistError;
199 if (weak_message_service_)
200 weak_message_service_->CloseChannel(port_id_, error_message);
201 }
202
203 void ExtensionMessagePort::RegisterFrame(content::RenderFrameHost* rfh) {
204 frames_.insert(rfh);
205 }
206
207 void ExtensionMessagePort::UnregisterFrame(content::RenderFrameHost* rfh) {
208 if (frames_.erase(rfh) != 0 && frames_.empty())
209 CloseChannel();
210 }
211
212 void ExtensionMessagePort::SendToPort(IPC::Message* msg) {
213 DCHECK_GT(frames_.size(), 0UL);
214 if (extension_process_) {
215 // All extension frames reside in the same process, so we can just send a
216 // single IPC message to the extension process as an optimization.
217 // The frame tracking is then only used to make sure that the port gets
218 // closed when all frames have closed / reloaded.
219 msg->set_routing_id(MSG_ROUTING_CONTROL);
220 extension_process_->Send(msg);
221 return;
222 }
223 for (content::RenderFrameHost* rfh : frames_) {
224 IPC::Message* msg_copy = new IPC::Message(*msg);
225 msg_copy->set_routing_id(rfh->GetRoutingID());
226 rfh->Send(msg_copy);
227 }
228 delete msg;
93 } 229 }
94 230
95 } // namespace extensions 231 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698