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

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: Use 0UL Created 5 years, 2 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 "chrome/browser/profiles/profile.h" 7 #include "chrome/browser/profiles/profile.h"
8 #include "content/public/browser/render_frame_host.h"
8 #include "content/public/browser/render_process_host.h" 9 #include "content/public/browser/render_process_host.h"
10 #include "content/public/browser/web_contents.h"
11 #include "content/public/browser/web_contents_observer.h"
9 #include "extensions/browser/extension_host.h" 12 #include "extensions/browser/extension_host.h"
10 #include "extensions/browser/process_manager.h" 13 #include "extensions/browser/process_manager.h"
14 #include "extensions/browser/process_manager_observer.h"
11 #include "extensions/common/extension_messages.h" 15 #include "extensions/common/extension_messages.h"
12 #include "extensions/common/manifest_handlers/background_info.h" 16 #include "extensions/common/manifest_handlers/background_info.h"
13 17
14 namespace extensions { 18 namespace extensions {
15 19
16 ExtensionMessagePort::ExtensionMessagePort(content::RenderProcessHost* process, 20 const char kReceivingEndDoesntExistError[] =
17 int routing_id, 21 "Could not establish connection. Receiving end does not exist.";
18 const std::string& extension_id) 22
19 : process_(process), 23 // Helper class to detect when frames are destroyed.
20 routing_id_(routing_id), 24 class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
21 extension_id_(extension_id), 25 public ProcessManagerObserver {
22 background_host_ptr_(NULL) { 26 public:
27 // Watch all frames in an extension process.
28 explicit FrameTracker(ExtensionMessagePort* port) : port_(port) {
29 ProcessManager::Get(port_->browser_context_)->AddObserver(this);
Devlin 2015/10/30 01:49:39 nit: prefer scoped observer for usage like this.
robwu 2015/11/02 19:08:33 Done.
30 }
31 // Watch all frames in a tab.
32 // TODO(robwu): Check whether this includes background pages and <webview>s.
33 FrameTracker(ExtensionMessagePort* port, content::WebContents* tab)
34 : content::WebContentsObserver(tab), port_(port) {
Devlin 2015/10/30 01:49:38 This doesn't observe the process manager. The com
robwu 2015/11/02 19:08:33 Done.
35 }
36 ~FrameTracker() override {
37 ProcessManager::Get(port_->browser_context_)->RemoveObserver(this);
38 }
39 private:
40 // content::WebContentsObserver overrides:
41 void RenderFrameHostChanged(content::RenderFrameHost* old_host,
42 content::RenderFrameHost* new_host) override {
43 port_->UnregisterFrame(old_host);
44 }
45 void FrameDeleted(content::RenderFrameHost* render_frame_host) override {
46 port_->UnregisterFrame(render_frame_host);
47 }
48
49 // extensions::ProcessManagerObserver overrides:
50 void OnExtensionFrameUnregistered(
51 const std::string& extension_id,
52 content::RenderFrameHost* render_frame_host) override {
53 if (extension_id == port_->extension_id_)
54 port_->UnregisterFrame(render_frame_host);
55 }
56
57 ExtensionMessagePort* port_;
58 DISALLOW_COPY_AND_ASSIGN(FrameTracker);
59 };
60
61 ExtensionMessagePort::ExtensionMessagePort(
62 base::WeakPtr<MessageService> message_service,
63 int port_id,
64 const std::string& extension_id,
65 content::RenderProcessHost* extension_process)
66 : weak_message_service_(message_service),
67 port_id_(port_id),
68 extension_id_(extension_id),
69 did_create_port_(false),
70 browser_context_(extension_process->GetBrowserContext()),
71 frames_(ProcessManager::Get(browser_context_)->
72 GetRenderFrameHostsForExtension(extension_id)),
73 extension_process_(extension_process),
74 background_host_ptr_(nullptr),
75 frame_tracker_(new FrameTracker(this)) {
76 }
77
78 ExtensionMessagePort::ExtensionMessagePort(
79 base::WeakPtr<MessageService> message_service,
80 int port_id,
81 const std::string& extension_id,
82 content::RenderFrameHost* rfh,
83 bool include_child_frames)
84 : weak_message_service_(message_service),
85 port_id_(port_id),
86 extension_id_(extension_id),
87 did_create_port_(false),
88 browser_context_(rfh->GetProcess()->GetBrowserContext()),
89 frames_(),
90 extension_process_(nullptr),
91 background_host_ptr_(nullptr),
92 frame_tracker_() {
Devlin 2015/10/30 01:49:39 This will default-initialize itself; no need for t
robwu 2015/11/02 19:08:33 Acknowledged.
93 content::WebContents* tab = content::WebContents::FromRenderFrameHost(rfh);
94 DCHECK(tab);
95 frame_tracker_.reset(new FrameTracker(this, tab));
96 if (include_child_frames) {
97 tab->ForEachFrame(base::Bind(&ExtensionMessagePort::RegisterFrame,
98 base::Unretained(this)));
99 } else {
100 RegisterFrame(rfh);
101 }
102 }
103
104 ExtensionMessagePort::~ExtensionMessagePort() {
105 frame_tracker_.reset();
Devlin 2015/10/30 01:49:38 Why is the explicit destruction needed?
robwu 2015/11/02 19:08:33 It's not needed - removed.
23 } 106 }
24 107
25 void ExtensionMessagePort::DispatchOnConnect( 108 void ExtensionMessagePort::DispatchOnConnect(
26 int dest_port_id,
27 const std::string& channel_name, 109 const std::string& channel_name,
28 scoped_ptr<base::DictionaryValue> source_tab, 110 scoped_ptr<base::DictionaryValue> source_tab,
29 int source_frame_id, 111 int source_frame_id,
30 int target_tab_id,
31 int target_frame_id,
32 int guest_process_id, 112 int guest_process_id,
33 int guest_render_frame_routing_id, 113 int guest_render_frame_routing_id,
34 const std::string& source_extension_id, 114 const std::string& source_extension_id,
35 const std::string& target_extension_id, 115 const std::string& target_extension_id,
36 const GURL& source_url, 116 const GURL& source_url,
37 const std::string& tls_channel_id) { 117 const std::string& tls_channel_id) {
38 ExtensionMsg_TabConnectionInfo source; 118 ExtensionMsg_TabConnectionInfo source;
39 if (source_tab) 119 if (source_tab)
40 source.tab.Swap(source_tab.get()); 120 source.tab.Swap(source_tab.get());
41 source.frame_id = source_frame_id; 121 source.frame_id = source_frame_id;
42 122
43 ExtensionMsg_ExternalConnectionInfo info; 123 ExtensionMsg_ExternalConnectionInfo info;
44 info.target_id = target_extension_id; 124 info.target_id = target_extension_id;
45 info.source_id = source_extension_id; 125 info.source_id = source_extension_id;
46 info.source_url = source_url; 126 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; 127 info.guest_process_id = guest_process_id;
50 info.guest_render_frame_routing_id = guest_render_frame_routing_id; 128 info.guest_render_frame_routing_id = guest_render_frame_routing_id;
51 129
52 process_->Send(new ExtensionMsg_DispatchOnConnect( 130 SendToPort(new ExtensionMsg_DispatchOnConnect(
53 routing_id_, dest_port_id, channel_name, source, info, tls_channel_id)); 131 MSG_ROUTING_NONE, port_id_, channel_name, source, info, tls_channel_id));
54 } 132 }
55 133
56 void ExtensionMessagePort::DispatchOnDisconnect( 134 void ExtensionMessagePort::DispatchOnDisconnect(
57 int source_port_id,
58 const std::string& error_message) { 135 const std::string& error_message) {
59 process_->Send(new ExtensionMsg_DispatchOnDisconnect( 136 SendToPort(new ExtensionMsg_DispatchOnDisconnect(
60 routing_id_, source_port_id, error_message)); 137 MSG_ROUTING_NONE, port_id_, error_message));
61 } 138 }
62 139
63 void ExtensionMessagePort::DispatchOnMessage(const Message& message, 140 void ExtensionMessagePort::DispatchOnMessage(const Message& message) {
64 int target_port_id) { 141 SendToPort(new ExtensionMsg_DeliverMessage(
65 process_->Send(new ExtensionMsg_DeliverMessage( 142 MSG_ROUTING_NONE, port_id_, message));
66 routing_id_, target_port_id, message));
67 } 143 }
68 144
69 void ExtensionMessagePort::IncrementLazyKeepaliveCount() { 145 void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
70 Profile* profile = 146 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_); 147 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
74 if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension())) 148 if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension()))
75 pm->IncrementLazyKeepaliveCount(host->extension()); 149 pm->IncrementLazyKeepaliveCount(host->extension());
76 150
77 // Keep track of the background host, so when we decrement, we only do so if 151 // Keep track of the background host, so when we decrement, we only do so if
78 // the host hasn't reloaded. 152 // the host hasn't reloaded.
79 background_host_ptr_ = host; 153 background_host_ptr_ = host;
80 } 154 }
81 155
82 void ExtensionMessagePort::DecrementLazyKeepaliveCount() { 156 void ExtensionMessagePort::DecrementLazyKeepaliveCount() {
83 Profile* profile = 157 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_); 158 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_);
87 if (host && host == background_host_ptr_) 159 if (host && host == background_host_ptr_)
88 pm->DecrementLazyKeepaliveCount(host->extension()); 160 pm->DecrementLazyKeepaliveCount(host->extension());
89 } 161 }
90 162
91 content::RenderProcessHost* ExtensionMessagePort::GetRenderProcessHost() { 163 void ExtensionMessagePort::OpenPort(int process_id, int routing_id) {
92 return process_; 164 // Mark port as active, so we can distinguish abnormal port closure from
165 // explicit port closure via disconnect().
166 did_create_port_ = true;
167 }
168
169 void ExtensionMessagePort::ClosePort(int process_id, int routing_id) {
170 if (routing_id == MSG_ROUTING_NONE) {
171 // The only non-frame-specific message is the response to an unhandled
172 // onConnect event in the extension process.
173 DCHECK(extension_process_);
174 frames_.clear();
175 CloseChannel();
176 return;
177 }
178 content::RenderFrameHost* rfh =
179 content::RenderFrameHost::FromID(process_id, routing_id);
180 if (rfh)
181 UnregisterFrame(rfh);
182 }
183
184 void ExtensionMessagePort::CloseChannel() {
185 std::string error_message = did_create_port_ ? std::string() :
186 kReceivingEndDoesntExistError;
187 if (weak_message_service_)
188 weak_message_service_->CloseChannel(port_id_, error_message);
189 }
190
191 void ExtensionMessagePort::RegisterFrame(content::RenderFrameHost* rfh) {
192 frames_.insert(rfh);
193 }
194
195 void ExtensionMessagePort::UnregisterFrame(content::RenderFrameHost* rfh) {
196 if (frames_.erase(rfh) != 0 && frames_.empty())
197 CloseChannel();
198 }
199
200 void ExtensionMessagePort::SendToPort(IPC::Message* msg) {
201 if (extension_process_) {
202 msg->set_routing_id(MSG_ROUTING_CONTROL);
203 extension_process_->Send(msg);
204 return;
205 }
206 for (content::RenderFrameHost* rfh : frames_) {
Devlin 2015/10/30 01:49:39 Hmm... This is a bit confusing, because of the way
robwu 2015/10/31 00:10:44 |frames_| is used to avoid unnecessary IPC, since
Devlin 2015/10/31 00:19:56 What about extension iframes in web pages without
robwu 2015/11/02 19:08:33 Extension iframes currently don't have any access
207 IPC::Message* msg_copy = new IPC::Message(*msg);
208 msg_copy->set_routing_id(rfh->GetRoutingID());
209 rfh->Send(msg_copy);
210 }
211 delete msg;
93 } 212 }
94 213
95 } // namespace extensions 214 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698