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

Side by Side Diff: third_party/WebKit/Source/core/frame/Frame.cpp

Issue 2877893002: Make UseCounter take a LocaFrame instead of any Frame (Closed)
Patch Set: Fix compile Created 3 years, 6 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 /* 1 /*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org> 3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org> 4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Simon Hausmann <hausmann@kde.org> 5 * 2000 Simon Hausmann <hausmann@kde.org>
6 * 2000 Stefan Schimanski <1Stein@gmx.de> 6 * 2000 Stefan Schimanski <1Stein@gmx.de>
7 * 2001 George Staikos <staikos@kde.org> 7 * 2001 George Staikos <staikos@kde.org>
8 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All 8 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
9 * rights reserved. 9 * rights reserved.
10 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> 10 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
(...skipping 27 matching lines...) Expand all
38 #include "core/frame/UseCounter.h" 38 #include "core/frame/UseCounter.h"
39 #include "core/html/HTMLFrameElementBase.h" 39 #include "core/html/HTMLFrameElementBase.h"
40 #include "core/input/EventHandler.h" 40 #include "core/input/EventHandler.h"
41 #include "core/layout/LayoutPart.h" 41 #include "core/layout/LayoutPart.h"
42 #include "core/layout/api/LayoutPartItem.h" 42 #include "core/layout/api/LayoutPartItem.h"
43 #include "core/loader/EmptyClients.h" 43 #include "core/loader/EmptyClients.h"
44 #include "core/loader/NavigationScheduler.h" 44 #include "core/loader/NavigationScheduler.h"
45 #include "core/page/FocusController.h" 45 #include "core/page/FocusController.h"
46 #include "core/page/Page.h" 46 #include "core/page/Page.h"
47 #include "core/probe/CoreProbes.h" 47 #include "core/probe/CoreProbes.h"
48 #include "platform/Histogram.h"
49 #include "platform/InstanceCounters.h" 48 #include "platform/InstanceCounters.h"
50 #include "platform/UserGestureIndicator.h" 49 #include "platform/UserGestureIndicator.h"
51 #include "platform/feature_policy/FeaturePolicy.h" 50 #include "platform/feature_policy/FeaturePolicy.h"
52 #include "platform/loader/fetch/ResourceError.h" 51 #include "platform/loader/fetch/ResourceError.h"
53 52
54 namespace blink { 53 namespace blink {
55 54
56 using namespace HTMLNames; 55 using namespace HTMLNames;
57 56
58 Frame::~Frame() { 57 Frame::~Frame() {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 return client; 124 return client;
126 } 125 }
127 126
128 ChromeClient& Frame::GetChromeClient() const { 127 ChromeClient& Frame::GetChromeClient() const {
129 if (Page* page = this->GetPage()) 128 if (Page* page = this->GetPage())
130 return page->GetChromeClient(); 129 return page->GetChromeClient();
131 return GetEmptyChromeClient(); 130 return GetEmptyChromeClient();
132 } 131 }
133 132
134 Frame* Frame::FindFrameForNavigation(const AtomicString& name, 133 Frame* Frame::FindFrameForNavigation(const AtomicString& name,
135 Frame& active_frame) { 134 LocalFrame& active_frame) {
136 Frame* frame = Tree().Find(name); 135 Frame* frame = Tree().Find(name);
137 if (!frame || !active_frame.CanNavigate(*frame)) 136 if (!frame || !active_frame.CanNavigate(*frame))
138 return nullptr; 137 return nullptr;
139 return frame; 138 return frame;
140 } 139 }
141 140
142 static bool CanAccessAncestor(const SecurityOrigin& active_security_origin,
143 const Frame* target_frame) {
144 // targetFrame can be 0 when we're trying to navigate a top-level frame
145 // that has a 0 opener.
146 if (!target_frame)
147 return false;
148
149 const bool is_local_active_origin = active_security_origin.IsLocal();
150 for (const Frame* ancestor_frame = target_frame; ancestor_frame;
151 ancestor_frame = ancestor_frame->Tree().Parent()) {
152 const SecurityOrigin* ancestor_security_origin =
153 ancestor_frame->GetSecurityContext()->GetSecurityOrigin();
154 if (active_security_origin.CanAccess(ancestor_security_origin))
155 return true;
156
157 // Allow file URL descendant navigation even when
158 // allowFileAccessFromFileURLs is false.
159 // FIXME: It's a bit strange to special-case local origins here. Should we
160 // be doing something more general instead?
161 if (is_local_active_origin && ancestor_security_origin->IsLocal())
162 return true;
163 }
164
165 return false;
166 }
167
168 bool Frame::CanNavigate(const Frame& target_frame) {
169 String error_reason;
170 const bool is_allowed_navigation =
171 CanNavigateWithoutFramebusting(target_frame, error_reason);
172 const bool sandboxed =
173 GetSecurityContext()->GetSandboxFlags() != kSandboxNone;
174 const bool has_user_gesture =
175 IsLocalFrame() ? ToLocalFrame(this)->HasReceivedUserGesture() : false;
176
177 // Top navigation in sandbox with or w/o 'allow-top-navigation'.
178 if (target_frame != this && sandboxed && target_frame == Tree().Top()) {
179 UseCounter::Count(&target_frame, UseCounter::kTopNavInSandbox);
180 if (!has_user_gesture) {
181 UseCounter::Count(&target_frame,
182 UseCounter::kTopNavInSandboxWithoutGesture);
183 }
184 }
185
186 // Top navigation w/o sandbox or in sandbox with 'allow-top-navigation'.
187 if (target_frame != this &&
188 !GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) &&
189 target_frame == Tree().Top()) {
190 DEFINE_STATIC_LOCAL(EnumerationHistogram, framebust_histogram,
191 ("WebCore.Framebust", 4));
192 const unsigned kUserGestureBit = 0x1;
193 const unsigned kAllowedBit = 0x2;
194 unsigned framebust_params = 0;
195 UseCounter::Count(&target_frame, UseCounter::kTopNavigationFromSubFrame);
196
197 if (has_user_gesture)
198 framebust_params |= kUserGestureBit;
199 if (sandboxed) { // Sandboxed with 'allow-top-navigation'.
200 UseCounter::Count(&target_frame, UseCounter::kTopNavInSandboxWithPerm);
201 if (!has_user_gesture) {
202 UseCounter::Count(&target_frame,
203 UseCounter::kTopNavInSandboxWithPermButNoGesture);
204 }
205 }
206
207 if (is_allowed_navigation)
208 framebust_params |= kAllowedBit;
209 framebust_histogram.Count(framebust_params);
210 if (has_user_gesture || is_allowed_navigation)
211 return true;
212 // Frame-busting used to be generally allowed in most situations, but may
213 // now blocked if the document initiating the navigation has never received
214 // a user gesture.
215 if (!RuntimeEnabledFeatures::
216 framebustingNeedsSameOriginOrUserGestureEnabled()) {
217 String target_frame_description =
218 target_frame.IsLocalFrame() ? "with URL '" +
219 ToLocalFrame(target_frame)
220 .GetDocument()
221 ->Url()
222 .GetString() +
223 "'"
224 : "with origin '" +
225 target_frame.GetSecurityContext()
226 ->GetSecurityOrigin()
227 ->ToString() +
228 "'";
229 String message = "Frame with URL '" +
230 ToLocalFrame(this)->GetDocument()->Url().GetString() +
231 "' attempted to navigate its top-level window " +
232 target_frame_description +
233 ". Navigating the top-level window from a cross-origin "
234 "iframe will soon require that the iframe has received "
235 "a user gesture. See "
236 "https://www.chromestatus.com/features/"
237 "5851021045661696.";
238 PrintNavigationWarning(message);
239 return true;
240 }
241 error_reason =
242 "The frame attempting navigation is targeting its top-level window, "
243 "but is neither same-origin with its target nor has it received a "
244 "user gesture. See "
245 "https://www.chromestatus.com/features/5851021045661696.";
246 PrintNavigationErrorMessage(target_frame, error_reason.Latin1().data());
247 if (IsLocalFrame()) {
248 ToLocalFrame(this)->GetNavigationScheduler().SchedulePageBlock(
249 ToLocalFrame(this)->GetDocument(), ResourceError::ACCESS_DENIED);
250 }
251 return false;
252 }
253 if (!is_allowed_navigation && !error_reason.IsNull())
254 PrintNavigationErrorMessage(target_frame, error_reason.Latin1().data());
255 return is_allowed_navigation;
256 }
257
258 bool Frame::CanNavigateWithoutFramebusting(const Frame& target_frame,
259 String& reason) {
260 if (&target_frame == this)
261 return true;
262
263 if (GetSecurityContext()->IsSandboxed(kSandboxNavigation)) {
264 if (!target_frame.Tree().IsDescendantOf(this) &&
265 !target_frame.IsMainFrame()) {
266 reason =
267 "The frame attempting navigation is sandboxed, and is therefore "
268 "disallowed from navigating its ancestors.";
269 return false;
270 }
271
272 // Sandboxed frames can also navigate popups, if the
273 // 'allow-sandbox-escape-via-popup' flag is specified, or if
274 // 'allow-popups' flag is specified, or if the
275 if (target_frame.IsMainFrame() && target_frame != Tree().Top() &&
276 GetSecurityContext()->IsSandboxed(
277 kSandboxPropagatesToAuxiliaryBrowsingContexts) &&
278 (GetSecurityContext()->IsSandboxed(kSandboxPopups) ||
279 target_frame.Client()->Opener() != this)) {
280 reason =
281 "The frame attempting navigation is sandboxed and is trying "
282 "to navigate a popup, but is not the popup's opener and is not "
283 "set to propagate sandboxing to popups.";
284 return false;
285 }
286
287 // Top navigation is forbidden unless opted-in. allow-top-navigation or
288 // allow-top-navigation-by-user-activation will also skips origin checks.
289 if (target_frame == Tree().Top()) {
290 if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) &&
291 GetSecurityContext()->IsSandboxed(
292 kSandboxTopNavigationByUserActivation)) {
293 reason =
294 "The frame attempting navigation of the top-level window is "
295 "sandboxed, but the flag of 'allow-top-navigation' or "
296 "'allow-top-navigation-by-user-activation' is not set.";
297 return false;
298 }
299 if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) &&
300 !GetSecurityContext()->IsSandboxed(
301 kSandboxTopNavigationByUserActivation) &&
302 !UserGestureIndicator::ProcessingUserGesture()) {
303 // With only 'allow-top-navigation-by-user-activation' (but not
304 // 'allow-top-navigation'), top navigation requires a user gesture.
305 reason =
306 "The frame attempting navigation of the top-level window is "
307 "sandboxed with the 'allow-top-navigation-by-user-activation' "
308 "flag, but has no user activation (aka gesture). See "
309 "https://www.chromestatus.com/feature/5629582019395584.";
310 return false;
311 }
312 return true;
313 }
314 }
315
316 DCHECK(GetSecurityContext()->GetSecurityOrigin());
317 SecurityOrigin& origin = *GetSecurityContext()->GetSecurityOrigin();
318
319 // This is the normal case. A document can navigate its decendant frames,
320 // or, more generally, a document can navigate a frame if the document is
321 // in the same origin as any of that frame's ancestors (in the frame
322 // hierarchy).
323 //
324 // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
325 // historical information about this security check.
326 if (CanAccessAncestor(origin, &target_frame))
327 return true;
328
329 // Top-level frames are easier to navigate than other frames because they
330 // display their URLs in the address bar (in most browsers). However, there
331 // are still some restrictions on navigation to avoid nuisance attacks.
332 // Specifically, a document can navigate a top-level frame if that frame
333 // opened the document or if the document is the same-origin with any of
334 // the top-level frame's opener's ancestors (in the frame hierarchy).
335 //
336 // In both of these cases, the document performing the navigation is in
337 // some way related to the frame being navigate (e.g., by the "opener"
338 // and/or "parent" relation). Requiring some sort of relation prevents a
339 // document from navigating arbitrary, unrelated top-level frames.
340 if (!target_frame.Tree().Parent()) {
341 if (target_frame == Client()->Opener())
342 return true;
343 if (CanAccessAncestor(origin, target_frame.Client()->Opener()))
344 return true;
345 }
346
347 reason =
348 "The frame attempting navigation is neither same-origin with the target, "
349 "nor is it the target's parent or opener.";
350 return false;
351 }
352
353 Frame* Frame::FindUnsafeParentScrollPropagationBoundary() { 141 Frame* Frame::FindUnsafeParentScrollPropagationBoundary() {
354 Frame* current_frame = this; 142 Frame* current_frame = this;
355 Frame* ancestor_frame = Tree().Parent(); 143 Frame* ancestor_frame = Tree().Parent();
356 144
357 while (ancestor_frame) { 145 while (ancestor_frame) {
358 if (!ancestor_frame->GetSecurityContext()->GetSecurityOrigin()->CanAccess( 146 if (!ancestor_frame->GetSecurityContext()->GetSecurityOrigin()->CanAccess(
359 GetSecurityContext()->GetSecurityOrigin())) 147 GetSecurityContext()->GetSecurityOrigin()))
360 return current_frame; 148 return current_frame;
361 current_frame = ancestor_frame; 149 current_frame = ancestor_frame;
362 ancestor_frame = ancestor_frame->Tree().Parent(); 150 ancestor_frame = ancestor_frame->Tree().Parent();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 is_loading_(false) { 218 is_loading_(false) {
431 InstanceCounters::IncrementCounter(InstanceCounters::kFrameCounter); 219 InstanceCounters::IncrementCounter(InstanceCounters::kFrameCounter);
432 220
433 if (owner_) 221 if (owner_)
434 owner_->SetContentFrame(*this); 222 owner_->SetContentFrame(*this);
435 else 223 else
436 page_->SetMainFrame(this); 224 page_->SetMainFrame(this);
437 } 225 }
438 226
439 } // namespace blink 227 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/frame/Frame.h ('k') | third_party/WebKit/Source/core/frame/LocalFrame.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698