OLD | NEW |
---|---|
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 "base/scoped_observer.h" |
8 #include "chrome/browser/profiles/profile.h" | 8 #include "chrome/browser/profiles/profile.h" |
9 #include "content/public/browser/interstitial_page.h" | |
9 #include "content/public/browser/navigation_details.h" | 10 #include "content/public/browser/navigation_details.h" |
10 #include "content/public/browser/render_frame_host.h" | 11 #include "content/public/browser/render_frame_host.h" |
11 #include "content/public/browser/render_process_host.h" | 12 #include "content/public/browser/render_process_host.h" |
12 #include "content/public/browser/web_contents.h" | 13 #include "content/public/browser/web_contents.h" |
13 #include "content/public/browser/web_contents_observer.h" | 14 #include "content/public/browser/web_contents_observer.h" |
14 #include "extensions/browser/extension_host.h" | 15 #include "extensions/browser/extension_host.h" |
15 #include "extensions/browser/process_manager.h" | 16 #include "extensions/browser/process_manager.h" |
16 #include "extensions/browser/process_manager_observer.h" | 17 #include "extensions/browser/process_manager_observer.h" |
17 #include "extensions/common/extension_messages.h" | 18 #include "extensions/common/extension_messages.h" |
18 #include "extensions/common/manifest_handlers/background_info.h" | 19 #include "extensions/common/manifest_handlers/background_info.h" |
19 | 20 |
20 namespace extensions { | 21 namespace extensions { |
21 | 22 |
22 const char kReceivingEndDoesntExistError[] = | 23 const char kReceivingEndDoesntExistError[] = |
23 "Could not establish connection. Receiving end does not exist."; | 24 "Could not establish connection. Receiving end does not exist."; |
24 | 25 |
25 // Helper class to detect when frames are destroyed. | 26 // Helper class to detect when frames are destroyed. |
26 class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver, | 27 class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver, |
27 public ProcessManagerObserver { | 28 public ProcessManagerObserver { |
28 public: | 29 public: |
29 explicit FrameTracker(ExtensionMessagePort* port) | 30 explicit FrameTracker(ExtensionMessagePort* port) |
30 : pm_observer_(this), port_(port) {} | 31 : pm_observer_(this), port_(port), interstitial_frame_(nullptr) {} |
31 ~FrameTracker() override {} | 32 ~FrameTracker() override {} |
32 | 33 |
33 void TrackExtensionProcessFrames() { | 34 void TrackExtensionProcessFrames() { |
34 pm_observer_.Add(ProcessManager::Get(port_->browser_context_)); | 35 pm_observer_.Add(ProcessManager::Get(port_->browser_context_)); |
35 } | 36 } |
36 | 37 |
37 void TrackTabFrames(content::WebContents* tab) { | 38 void TrackTabFrames(content::WebContents* tab) { |
38 Observe(tab); | 39 Observe(tab); |
39 } | 40 } |
40 | 41 |
42 void TrackInterstitialFrame(content::WebContents* tab, | |
43 content::RenderFrameHost* interstitial_frame) { | |
44 DCHECK(interstitial_frame); | |
45 interstitial_frame_ = interstitial_frame; | |
46 Observe(tab); | |
47 } | |
48 | |
41 private: | 49 private: |
42 // content::WebContentsObserver overrides: | 50 // content::WebContentsObserver overrides: |
43 void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) | 51 void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) |
44 override { | 52 override { |
45 port_->UnregisterFrame(render_frame_host); | 53 port_->UnregisterFrame(render_frame_host); |
46 } | 54 } |
47 | 55 |
48 // TODO(robwu): This should be superfluous with RenderFrameDeleted above, but | |
49 // we are not entirely sure. | |
50 void FrameDeleted(content::RenderFrameHost* render_frame_host) override { | |
51 port_->UnregisterFrame(render_frame_host); | |
52 } | |
53 | |
54 void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, | 56 void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, |
55 const content::LoadCommittedDetails& details, | 57 const content::LoadCommittedDetails& details, |
56 const content::FrameNavigateParams&) override { | 58 const content::FrameNavigateParams&) override { |
57 if (!details.is_in_page) | 59 if (!details.is_in_page) |
58 port_->UnregisterFrame(render_frame_host); | 60 port_->UnregisterFrame(render_frame_host); |
59 } | 61 } |
62 | |
63 void DidDetachInterstitialPage() override { | |
64 if (interstitial_frame_) | |
65 port_->UnregisterFrame(interstitial_frame_); | |
66 } | |
60 | 67 |
61 // extensions::ProcessManagerObserver overrides: | 68 // extensions::ProcessManagerObserver overrides: |
62 void OnExtensionFrameUnregistered( | 69 void OnExtensionFrameUnregistered( |
63 const std::string& extension_id, | 70 const std::string& extension_id, |
64 content::RenderFrameHost* render_frame_host) override { | 71 content::RenderFrameHost* render_frame_host) override { |
65 if (extension_id == port_->extension_id_) | 72 if (extension_id == port_->extension_id_) |
66 port_->UnregisterFrame(render_frame_host); | 73 port_->UnregisterFrame(render_frame_host); |
67 } | 74 } |
68 | 75 |
69 ScopedObserver<ProcessManager, ProcessManagerObserver> pm_observer_; | 76 ScopedObserver<ProcessManager, ProcessManagerObserver> pm_observer_; |
70 ExtensionMessagePort* port_; // Owns this FrameTracker. | 77 ExtensionMessagePort* port_; // Owns this FrameTracker. |
71 | 78 |
79 // Set to the main frame of an interstitial if we are tracking an interstitial | |
80 // page, because RenderFrameDeleted is never triggered for frames in an | |
81 // interstitial (and we only support tracking the interstitial's main frame). | |
82 content::RenderFrameHost* interstitial_frame_; | |
83 | |
72 DISALLOW_COPY_AND_ASSIGN(FrameTracker); | 84 DISALLOW_COPY_AND_ASSIGN(FrameTracker); |
73 }; | 85 }; |
74 | 86 |
75 ExtensionMessagePort::ExtensionMessagePort( | 87 ExtensionMessagePort::ExtensionMessagePort( |
76 base::WeakPtr<MessageService> message_service, | 88 base::WeakPtr<MessageService> message_service, |
77 int port_id, | 89 int port_id, |
78 const std::string& extension_id, | 90 const std::string& extension_id, |
79 content::RenderProcessHost* extension_process) | 91 content::RenderProcessHost* extension_process) |
80 : weak_message_service_(message_service), | 92 : weak_message_service_(message_service), |
81 port_id_(port_id), | 93 port_id_(port_id), |
(...skipping 19 matching lines...) Expand all Loading... | |
101 bool include_child_frames) | 113 bool include_child_frames) |
102 : weak_message_service_(message_service), | 114 : weak_message_service_(message_service), |
103 port_id_(port_id), | 115 port_id_(port_id), |
104 extension_id_(extension_id), | 116 extension_id_(extension_id), |
105 browser_context_(rfh->GetProcess()->GetBrowserContext()), | 117 browser_context_(rfh->GetProcess()->GetBrowserContext()), |
106 extension_process_(nullptr), | 118 extension_process_(nullptr), |
107 did_create_port_(false), | 119 did_create_port_(false), |
108 background_host_ptr_(nullptr), | 120 background_host_ptr_(nullptr), |
109 frame_tracker_(new FrameTracker(this)) { | 121 frame_tracker_(new FrameTracker(this)) { |
110 content::WebContents* tab = content::WebContents::FromRenderFrameHost(rfh); | 122 content::WebContents* tab = content::WebContents::FromRenderFrameHost(rfh); |
111 CHECK(tab); | 123 content::InterstitialPage* interstitial = nullptr; |
124 if (!tab) { | |
125 interstitial = content::InterstitialPage::FromRenderFrameHost(rfh); | |
126 // A RenderFrameHost must be hosted in a WebContents or InterstitialPage. | |
127 CHECK(interstitial); | |
128 | |
129 tab = interstitial->GetUnderlyingWebContents(); | |
130 | |
131 // |tab| should never be nullptr, because an interstitial's lifetime is tied | |
132 // to a tab. This is a CHECK, not a DCHECK because we really need an | |
133 // observer subject to detect frame removal (via DidDetachInterstitialPage). | |
134 CHECK(tab); | |
135 | |
136 if (!rfh->GetParent()) { | |
137 // Only the main frame of an interstitial is supported, because frames in | |
Charlie Reis
2016/01/26 01:14:30
nit: Please move this comment above line 136, sinc
robwu
2016/01/26 11:29:32
Done.
| |
138 // the interstitial do not trigger RenderFrameCreated / RenderFrameDeleted | |
139 // on WebContentObservers. Consequently, (1) we cannot detect removal of | |
140 // RenderFrameHosts, and (2) even if we propagate the RenderFrameDeleted | |
141 // notification, then WebContentsObserverSanityChecker triggers a CHECK | |
142 // when it detects frame notifications without a corresponding | |
143 // RenderFrameCreated. | |
144 frame_tracker_->TrackInterstitialFrame(tab, rfh); | |
Charlie Reis
2016/01/26 01:14:30
Please add a comment above this line:
It is safe t
robwu
2016/01/26 11:29:32
Done.
| |
145 RegisterFrame(rfh); | |
146 } | |
147 return; | |
148 } | |
149 | |
112 frame_tracker_->TrackTabFrames(tab); | 150 frame_tracker_->TrackTabFrames(tab); |
113 if (include_child_frames) { | 151 if (include_child_frames) { |
114 tab->ForEachFrame(base::Bind(&ExtensionMessagePort::RegisterFrame, | 152 tab->ForEachFrame(base::Bind(&ExtensionMessagePort::RegisterFrame, |
115 base::Unretained(this))); | 153 base::Unretained(this))); |
116 } else { | 154 } else { |
117 RegisterFrame(rfh); | 155 RegisterFrame(rfh); |
118 } | 156 } |
119 } | 157 } |
120 | 158 |
121 ExtensionMessagePort::~ExtensionMessagePort() {} | 159 ExtensionMessagePort::~ExtensionMessagePort() {} |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 return; | 289 return; |
252 } | 290 } |
253 for (content::RenderFrameHost* rfh : frames_) { | 291 for (content::RenderFrameHost* rfh : frames_) { |
254 IPC::Message* msg_copy = new IPC::Message(*msg.get()); | 292 IPC::Message* msg_copy = new IPC::Message(*msg.get()); |
255 msg_copy->set_routing_id(rfh->GetRoutingID()); | 293 msg_copy->set_routing_id(rfh->GetRoutingID()); |
256 rfh->Send(msg_copy); | 294 rfh->Send(msg_copy); |
257 } | 295 } |
258 } | 296 } |
259 | 297 |
260 } // namespace extensions | 298 } // namespace extensions |
OLD | NEW |