OLD | NEW |
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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 #include "core/paint/ObjectPainter.h" | 73 #include "core/paint/ObjectPainter.h" |
74 #include "core/paint/PaintInfo.h" | 74 #include "core/paint/PaintInfo.h" |
75 #include "core/paint/PaintLayer.h" | 75 #include "core/paint/PaintLayer.h" |
76 #include "core/paint/PaintLayerPainter.h" | 76 #include "core/paint/PaintLayerPainter.h" |
77 #include "core/paint/TransformRecorder.h" | 77 #include "core/paint/TransformRecorder.h" |
78 #include "core/plugins/PluginView.h" | 78 #include "core/plugins/PluginView.h" |
79 #include "core/probe/CoreProbes.h" | 79 #include "core/probe/CoreProbes.h" |
80 #include "core/svg/SVGDocumentExtensions.h" | 80 #include "core/svg/SVGDocumentExtensions.h" |
81 #include "core/timing/Performance.h" | 81 #include "core/timing/Performance.h" |
82 #include "platform/DragImage.h" | 82 #include "platform/DragImage.h" |
| 83 #include "platform/Histogram.h" |
83 #include "platform/PluginScriptForbiddenScope.h" | 84 #include "platform/PluginScriptForbiddenScope.h" |
84 #include "platform/RuntimeEnabledFeatures.h" | 85 #include "platform/RuntimeEnabledFeatures.h" |
85 #include "platform/ScriptForbiddenScope.h" | 86 #include "platform/ScriptForbiddenScope.h" |
86 #include "platform/WebFrameScheduler.h" | 87 #include "platform/WebFrameScheduler.h" |
87 #include "platform/graphics/GraphicsContext.h" | 88 #include "platform/graphics/GraphicsContext.h" |
88 #include "platform/graphics/StaticBitmapImage.h" | 89 #include "platform/graphics/StaticBitmapImage.h" |
89 #include "platform/graphics/paint/ClipRecorder.h" | 90 #include "platform/graphics/paint/ClipRecorder.h" |
90 #include "platform/graphics/paint/PaintCanvas.h" | 91 #include "platform/graphics/paint/PaintCanvas.h" |
91 #include "platform/graphics/paint/PaintController.h" | 92 #include "platform/graphics/paint/PaintController.h" |
92 #include "platform/graphics/paint/PaintRecordBuilder.h" | 93 #include "platform/graphics/paint/PaintRecordBuilder.h" |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 WebFrameScheduler* LocalFrame::FrameScheduler() { | 913 WebFrameScheduler* LocalFrame::FrameScheduler() { |
913 return frame_scheduler_.get(); | 914 return frame_scheduler_.get(); |
914 } | 915 } |
915 | 916 |
916 void LocalFrame::ScheduleVisualUpdateUnlessThrottled() { | 917 void LocalFrame::ScheduleVisualUpdateUnlessThrottled() { |
917 if (ShouldThrottleRendering()) | 918 if (ShouldThrottleRendering()) |
918 return; | 919 return; |
919 GetPage()->Animator().ScheduleVisualUpdate(this); | 920 GetPage()->Animator().ScheduleVisualUpdate(this); |
920 } | 921 } |
921 | 922 |
| 923 bool LocalFrame::CanNavigate(const Frame& target_frame) { |
| 924 String error_reason; |
| 925 const bool is_allowed_navigation = |
| 926 CanNavigateWithoutFramebusting(target_frame, error_reason); |
| 927 const bool sandboxed = |
| 928 GetSecurityContext()->GetSandboxFlags() != kSandboxNone; |
| 929 const bool has_user_gesture = HasReceivedUserGesture(); |
| 930 |
| 931 // Top navigation in sandbox with or w/o 'allow-top-navigation'. |
| 932 if (target_frame != this && sandboxed && target_frame == Tree().Top()) { |
| 933 UseCounter::Count(this, UseCounter::kTopNavInSandbox); |
| 934 if (!has_user_gesture) { |
| 935 UseCounter::Count(this, UseCounter::kTopNavInSandboxWithoutGesture); |
| 936 } |
| 937 } |
| 938 |
| 939 // Top navigation w/o sandbox or in sandbox with 'allow-top-navigation'. |
| 940 if (target_frame != this && |
| 941 !GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) && |
| 942 target_frame == Tree().Top()) { |
| 943 DEFINE_STATIC_LOCAL(EnumerationHistogram, framebust_histogram, |
| 944 ("WebCore.Framebust", 4)); |
| 945 const unsigned kUserGestureBit = 0x1; |
| 946 const unsigned kAllowedBit = 0x2; |
| 947 unsigned framebust_params = 0; |
| 948 |
| 949 if (has_user_gesture) |
| 950 framebust_params |= kUserGestureBit; |
| 951 |
| 952 UseCounter::Count(this, UseCounter::kTopNavigationFromSubFrame); |
| 953 if (sandboxed) { // Sandboxed with 'allow-top-navigation'. |
| 954 UseCounter::Count(this, UseCounter::kTopNavInSandboxWithPerm); |
| 955 if (!has_user_gesture) { |
| 956 UseCounter::Count(this, |
| 957 UseCounter::kTopNavInSandboxWithPermButNoGesture); |
| 958 } |
| 959 } |
| 960 |
| 961 if (is_allowed_navigation) |
| 962 framebust_params |= kAllowedBit; |
| 963 framebust_histogram.Count(framebust_params); |
| 964 if (has_user_gesture || is_allowed_navigation) |
| 965 return true; |
| 966 // Frame-busting used to be generally allowed in most situations, but may |
| 967 // now blocked if the document initiating the navigation has never received |
| 968 // a user gesture. |
| 969 if (!RuntimeEnabledFeatures:: |
| 970 framebustingNeedsSameOriginOrUserGestureEnabled()) { |
| 971 String target_frame_description = |
| 972 target_frame.IsLocalFrame() ? "with URL '" + |
| 973 ToLocalFrame(target_frame) |
| 974 .GetDocument() |
| 975 ->Url() |
| 976 .GetString() + |
| 977 "'" |
| 978 : "with origin '" + |
| 979 target_frame.GetSecurityContext() |
| 980 ->GetSecurityOrigin() |
| 981 ->ToString() + |
| 982 "'"; |
| 983 String message = "Frame with URL '" + GetDocument()->Url().GetString() + |
| 984 "' attempted to navigate its top-level window " + |
| 985 target_frame_description + |
| 986 ". Navigating the top-level window from a cross-origin " |
| 987 "iframe will soon require that the iframe has received " |
| 988 "a user gesture. See " |
| 989 "https://www.chromestatus.com/features/" |
| 990 "5851021045661696."; |
| 991 PrintNavigationWarning(message); |
| 992 return true; |
| 993 } |
| 994 error_reason = |
| 995 "The frame attempting navigation is targeting its top-level window, " |
| 996 "but is neither same-origin with its target nor has it received a " |
| 997 "user gesture. See " |
| 998 "https://www.chromestatus.com/features/5851021045661696."; |
| 999 PrintNavigationErrorMessage(target_frame, error_reason.Latin1().data()); |
| 1000 GetNavigationScheduler().SchedulePageBlock(GetDocument(), |
| 1001 ResourceError::ACCESS_DENIED); |
| 1002 return false; |
| 1003 } |
| 1004 if (!is_allowed_navigation && !error_reason.IsNull()) |
| 1005 PrintNavigationErrorMessage(target_frame, error_reason.Latin1().data()); |
| 1006 return is_allowed_navigation; |
| 1007 } |
| 1008 |
| 1009 static bool CanAccessAncestor(const SecurityOrigin& active_security_origin, |
| 1010 const Frame* target_frame) { |
| 1011 // targetFrame can be 0 when we're trying to navigate a top-level frame |
| 1012 // that has a 0 opener. |
| 1013 if (!target_frame) |
| 1014 return false; |
| 1015 |
| 1016 const bool is_local_active_origin = active_security_origin.IsLocal(); |
| 1017 for (const Frame* ancestor_frame = target_frame; ancestor_frame; |
| 1018 ancestor_frame = ancestor_frame->Tree().Parent()) { |
| 1019 const SecurityOrigin* ancestor_security_origin = |
| 1020 ancestor_frame->GetSecurityContext()->GetSecurityOrigin(); |
| 1021 if (active_security_origin.CanAccess(ancestor_security_origin)) |
| 1022 return true; |
| 1023 |
| 1024 // Allow file URL descendant navigation even when |
| 1025 // allowFileAccessFromFileURLs is false. |
| 1026 // FIXME: It's a bit strange to special-case local origins here. Should we |
| 1027 // be doing something more general instead? |
| 1028 if (is_local_active_origin && ancestor_security_origin->IsLocal()) |
| 1029 return true; |
| 1030 } |
| 1031 |
| 1032 return false; |
| 1033 } |
| 1034 |
| 1035 bool LocalFrame::CanNavigateWithoutFramebusting(const Frame& target_frame, |
| 1036 String& reason) { |
| 1037 if (&target_frame == this) |
| 1038 return true; |
| 1039 |
| 1040 if (GetSecurityContext()->IsSandboxed(kSandboxNavigation)) { |
| 1041 if (!target_frame.Tree().IsDescendantOf(this) && |
| 1042 !target_frame.IsMainFrame()) { |
| 1043 reason = |
| 1044 "The frame attempting navigation is sandboxed, and is therefore " |
| 1045 "disallowed from navigating its ancestors."; |
| 1046 return false; |
| 1047 } |
| 1048 |
| 1049 // Sandboxed frames can also navigate popups, if the |
| 1050 // 'allow-sandbox-escape-via-popup' flag is specified, or if |
| 1051 // 'allow-popups' flag is specified, or if the |
| 1052 if (target_frame.IsMainFrame() && target_frame != Tree().Top() && |
| 1053 GetSecurityContext()->IsSandboxed( |
| 1054 kSandboxPropagatesToAuxiliaryBrowsingContexts) && |
| 1055 (GetSecurityContext()->IsSandboxed(kSandboxPopups) || |
| 1056 target_frame.Client()->Opener() != this)) { |
| 1057 reason = |
| 1058 "The frame attempting navigation is sandboxed and is trying " |
| 1059 "to navigate a popup, but is not the popup's opener and is not " |
| 1060 "set to propagate sandboxing to popups."; |
| 1061 return false; |
| 1062 } |
| 1063 |
| 1064 // Top navigation is forbidden unless opted-in. allow-top-navigation or |
| 1065 // allow-top-navigation-by-user-activation will also skips origin checks. |
| 1066 if (target_frame == Tree().Top()) { |
| 1067 if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) && |
| 1068 GetSecurityContext()->IsSandboxed( |
| 1069 kSandboxTopNavigationByUserActivation)) { |
| 1070 reason = |
| 1071 "The frame attempting navigation of the top-level window is " |
| 1072 "sandboxed, but the flag of 'allow-top-navigation' or " |
| 1073 "'allow-top-navigation-by-user-activation' is not set."; |
| 1074 return false; |
| 1075 } |
| 1076 if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) && |
| 1077 !GetSecurityContext()->IsSandboxed( |
| 1078 kSandboxTopNavigationByUserActivation) && |
| 1079 !UserGestureIndicator::ProcessingUserGesture()) { |
| 1080 // With only 'allow-top-navigation-by-user-activation' (but not |
| 1081 // 'allow-top-navigation'), top navigation requires a user gesture. |
| 1082 reason = |
| 1083 "The frame attempting navigation of the top-level window is " |
| 1084 "sandboxed with the 'allow-top-navigation-by-user-activation' " |
| 1085 "flag, but has no user activation (aka gesture). See " |
| 1086 "https://www.chromestatus.com/feature/5629582019395584."; |
| 1087 return false; |
| 1088 } |
| 1089 return true; |
| 1090 } |
| 1091 } |
| 1092 |
| 1093 DCHECK(GetSecurityContext()->GetSecurityOrigin()); |
| 1094 SecurityOrigin& origin = *GetSecurityContext()->GetSecurityOrigin(); |
| 1095 |
| 1096 // This is the normal case. A document can navigate its decendant frames, |
| 1097 // or, more generally, a document can navigate a frame if the document is |
| 1098 // in the same origin as any of that frame's ancestors (in the frame |
| 1099 // hierarchy). |
| 1100 // |
| 1101 // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for |
| 1102 // historical information about this security check. |
| 1103 if (CanAccessAncestor(origin, &target_frame)) |
| 1104 return true; |
| 1105 |
| 1106 // Top-level frames are easier to navigate than other frames because they |
| 1107 // display their URLs in the address bar (in most browsers). However, there |
| 1108 // are still some restrictions on navigation to avoid nuisance attacks. |
| 1109 // Specifically, a document can navigate a top-level frame if that frame |
| 1110 // opened the document or if the document is the same-origin with any of |
| 1111 // the top-level frame's opener's ancestors (in the frame hierarchy). |
| 1112 // |
| 1113 // In both of these cases, the document performing the navigation is in |
| 1114 // some way related to the frame being navigate (e.g., by the "opener" |
| 1115 // and/or "parent" relation). Requiring some sort of relation prevents a |
| 1116 // document from navigating arbitrary, unrelated top-level frames. |
| 1117 if (!target_frame.Tree().Parent()) { |
| 1118 if (target_frame == Client()->Opener()) |
| 1119 return true; |
| 1120 if (CanAccessAncestor(origin, target_frame.Client()->Opener())) |
| 1121 return true; |
| 1122 } |
| 1123 |
| 1124 reason = |
| 1125 "The frame attempting navigation is neither same-origin with the target, " |
| 1126 "nor is it the target's parent or opener."; |
| 1127 return false; |
| 1128 } |
| 1129 |
922 LocalFrameClient* LocalFrame::Client() const { | 1130 LocalFrameClient* LocalFrame::Client() const { |
923 return static_cast<LocalFrameClient*>(Frame::Client()); | 1131 return static_cast<LocalFrameClient*>(Frame::Client()); |
924 } | 1132 } |
925 | 1133 |
926 ContentSettingsClient* LocalFrame::GetContentSettingsClient() { | 1134 ContentSettingsClient* LocalFrame::GetContentSettingsClient() { |
927 return Client() ? &Client()->GetContentSettingsClient() : nullptr; | 1135 return Client() ? &Client()->GetContentSettingsClient() : nullptr; |
928 } | 1136 } |
929 | 1137 |
930 PluginData* LocalFrame::GetPluginData() const { | 1138 PluginData* LocalFrame::GetPluginData() const { |
931 if (!Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) | 1139 if (!Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 node = GetDocument()->FocusedElement(); | 1195 node = GetDocument()->FocusedElement(); |
988 } | 1196 } |
989 | 1197 |
990 if (node) { | 1198 if (node) { |
991 return node->GetWebPluginContainerBase(); | 1199 return node->GetWebPluginContainerBase(); |
992 } | 1200 } |
993 return nullptr; | 1201 return nullptr; |
994 } | 1202 } |
995 | 1203 |
996 } // namespace blink | 1204 } // namespace blink |
OLD | NEW |