Index: third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp |
diff --git a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp |
index bc2246fb5e015b609bec62e12df43c6b1e88ae1f..9a42280e93f9f57dcfdc97d580e90b05a4ce0770 100644 |
--- a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp |
+++ b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp |
@@ -33,7 +33,9 @@ |
#include "bindings/core/v8/ExceptionState.h" |
#include "bindings/core/v8/V8BindingForCore.h" |
#include "bindings/core/v8/V8Location.h" |
+#include "bindings/core/v8/V8Window.h" |
#include "core/dom/Document.h" |
+#include "core/frame/DOMWindow.h" |
#include "core/frame/LocalDOMWindow.h" |
#include "core/frame/LocalFrame.h" |
#include "core/frame/Location.h" |
@@ -47,9 +49,8 @@ namespace blink { |
namespace { |
-bool CanAccessFrameInternal(const LocalDOMWindow* accessing_window, |
- const SecurityOrigin* target_frame_origin, |
- const DOMWindow* target_window) { |
+bool CanAccessWindowInternal(const LocalDOMWindow* accessing_window, |
+ const DOMWindow* target_window) { |
SECURITY_CHECK(!(target_window && target_window->GetFrame()) || |
target_window == target_window->GetFrame()->DomWindow()); |
@@ -62,11 +63,14 @@ bool CanAccessFrameInternal(const LocalDOMWindow* accessing_window, |
const SecurityOrigin* accessing_origin = |
accessing_window->document()->GetSecurityOrigin(); |
- if (!accessing_origin->CanAccess(target_frame_origin)) |
+ const LocalDOMWindow* local_target_window = ToLocalDOMWindow(target_window); |
+ if (!accessing_origin->CanAccess( |
+ local_target_window->document()->GetSecurityOrigin())) { |
return false; |
+ } |
// Notify the loader's client if the initial document has been accessed. |
- LocalFrame* target_frame = ToLocalDOMWindow(target_window)->GetFrame(); |
+ LocalFrame* target_frame = local_target_window->GetFrame(); |
if (target_frame && |
target_frame->Loader().StateMachine()->IsDisplayingInitialEmptyDocument()) |
target_frame->Loader().DidAccessInitialDocument(); |
@@ -74,12 +78,10 @@ bool CanAccessFrameInternal(const LocalDOMWindow* accessing_window, |
return true; |
} |
-bool CanAccessFrame(const LocalDOMWindow* accessing_window, |
- const SecurityOrigin* target_frame_origin, |
- const DOMWindow* target_window, |
- ExceptionState& exception_state) { |
- if (CanAccessFrameInternal(accessing_window, target_frame_origin, |
- target_window)) |
+bool CanAccessWindow(const LocalDOMWindow* accessing_window, |
+ const DOMWindow* target_window, |
+ ExceptionState& exception_state) { |
+ if (CanAccessWindowInternal(accessing_window, target_window)) |
return true; |
if (target_window) |
@@ -89,12 +91,10 @@ bool CanAccessFrame(const LocalDOMWindow* accessing_window, |
return false; |
} |
-bool CanAccessFrame(const LocalDOMWindow* accessing_window, |
- SecurityOrigin* target_frame_origin, |
- const DOMWindow* target_window, |
- BindingSecurity::ErrorReportOption reporting_option) { |
- if (CanAccessFrameInternal(accessing_window, target_frame_origin, |
- target_window)) |
+bool CanAccessWindow(const LocalDOMWindow* accessing_window, |
+ const DOMWindow* target_window, |
+ BindingSecurity::ErrorReportOption reporting_option) { |
+ if (CanAccessWindowInternal(accessing_window, target_window)) |
return true; |
if (accessing_window && target_window && |
@@ -104,6 +104,20 @@ bool CanAccessFrame(const LocalDOMWindow* accessing_window, |
return false; |
} |
+DOMWindow* FindWindow(v8::Isolate* isolate, |
+ const WrapperTypeInfo* type, |
+ v8::Local<v8::Object> holder) { |
+ if (V8Window::wrapperTypeInfo.Equals(type)) |
+ return V8Window::toImpl(holder); |
+ |
+ if (V8Location::wrapperTypeInfo.Equals(type)) |
+ return V8Location::toImpl(holder)->DomWindow(); |
+ |
+ // This function can handle only those types listed above. |
+ NOTREACHED(); |
+ return nullptr; |
+} |
+ |
} // namespace |
bool BindingSecurity::ShouldAllowAccessTo( |
@@ -111,12 +125,16 @@ bool BindingSecurity::ShouldAllowAccessTo( |
const DOMWindow* target, |
ExceptionState& exception_state) { |
DCHECK(target); |
- const Frame* frame = target->GetFrame(); |
- if (!frame || !frame->GetSecurityContext()) |
+ |
+ // TODO(https://crbug.com/723057): This is intended to match the legacy |
+ // behavior of when access checks revolved around Frame pointers rather than |
+ // DOMWindow pointers. This prevents web-visible behavior changes, since the |
+ // previous implementation had to follow the back pointer to the Frame, and |
+ // would have to early return when it was null. |
+ if (!target->GetFrame()) |
return false; |
- return CanAccessFrame(accessing_window, |
- frame->GetSecurityContext()->GetSecurityOrigin(), |
- target, exception_state); |
+ |
+ return CanAccessWindow(accessing_window, target, exception_state); |
} |
bool BindingSecurity::ShouldAllowAccessTo( |
@@ -124,32 +142,16 @@ bool BindingSecurity::ShouldAllowAccessTo( |
const DOMWindow* target, |
ErrorReportOption reporting_option) { |
DCHECK(target); |
- const Frame* frame = target->GetFrame(); |
- if (!frame || !frame->GetSecurityContext()) |
- return false; |
- return CanAccessFrame(accessing_window, |
- frame->GetSecurityContext()->GetSecurityOrigin(), |
- target, reporting_option); |
-} |
-bool BindingSecurity::ShouldAllowAccessTo( |
- const LocalDOMWindow* accessing_window, |
- const EventTarget* target, |
- ExceptionState& exception_state) { |
- DCHECK(target); |
- const DOMWindow* window = target->ToDOMWindow(); |
- if (!window) { |
- // We only need to check the access to Window objects which are |
- // cross-origin accessible. If it's not a Window, the object's |
- // origin must always be the same origin (or it already leaked). |
- return true; |
- } |
- const Frame* frame = window->GetFrame(); |
- if (!frame || !frame->GetSecurityContext()) |
+ // TODO(https://crbug.com/723057): This is intended to match the legacy |
+ // behavior of when access checks revolved around Frame pointers rather than |
+ // DOMWindow pointers. This prevents web-visible behavior changes, since the |
+ // previous implementation had to follow the back pointer to the Frame, and |
+ // would have to early return when it was null. |
+ if (!target->GetFrame()) |
return false; |
- return CanAccessFrame(accessing_window, |
- frame->GetSecurityContext()->GetSecurityOrigin(), |
- window, exception_state); |
+ |
+ return CanAccessWindow(accessing_window, target, reporting_option); |
} |
bool BindingSecurity::ShouldAllowAccessTo( |
@@ -157,12 +159,17 @@ bool BindingSecurity::ShouldAllowAccessTo( |
const Location* target, |
ExceptionState& exception_state) { |
DCHECK(target); |
- const Frame* frame = target->GetFrame(); |
- if (!frame || !frame->GetSecurityContext()) |
+ |
+ // TODO(https://crbug.com/723057): This is intended to match the legacy |
+ // behavior of when access checks revolved around Frame pointers rather than |
+ // DOMWindow pointers. This prevents web-visible behavior changes, since the |
+ // previous implementation had to follow the back pointer to the Frame, and |
+ // would have to early return when it was null. |
+ if (!target->DomWindow()->GetFrame()) |
return false; |
- return CanAccessFrame(accessing_window, |
- frame->GetSecurityContext()->GetSecurityOrigin(), |
- frame->DomWindow(), exception_state); |
+ |
+ return CanAccessWindow(accessing_window, target->DomWindow(), |
+ exception_state); |
} |
bool BindingSecurity::ShouldAllowAccessTo( |
@@ -170,12 +177,17 @@ bool BindingSecurity::ShouldAllowAccessTo( |
const Location* target, |
ErrorReportOption reporting_option) { |
DCHECK(target); |
- const Frame* frame = target->GetFrame(); |
- if (!frame || !frame->GetSecurityContext()) |
+ |
+ // TODO(https://crbug.com/723057): This is intended to match the legacy |
+ // behavior of when access checks revolved around Frame pointers rather than |
+ // DOMWindow pointers. This prevents web-visible behavior changes, since the |
+ // previous implementation had to follow the back pointer to the Frame, and |
+ // would have to early return when it was null. |
+ if (!target->DomWindow()->GetFrame()) |
return false; |
- return CanAccessFrame(accessing_window, |
- frame->GetSecurityContext()->GetSecurityOrigin(), |
- frame->DomWindow(), reporting_option); |
+ |
+ return CanAccessWindow(accessing_window, target->DomWindow(), |
+ reporting_option); |
} |
bool BindingSecurity::ShouldAllowAccessTo( |
@@ -184,9 +196,8 @@ bool BindingSecurity::ShouldAllowAccessTo( |
ExceptionState& exception_state) { |
if (!target) |
return false; |
- return CanAccessFrame(accessing_window, |
- target->GetDocument().GetSecurityOrigin(), |
- target->GetDocument().domWindow(), exception_state); |
+ return CanAccessWindow(accessing_window, target->GetDocument().domWindow(), |
+ exception_state); |
} |
bool BindingSecurity::ShouldAllowAccessTo( |
@@ -195,9 +206,8 @@ bool BindingSecurity::ShouldAllowAccessTo( |
ErrorReportOption reporting_option) { |
if (!target) |
return false; |
- return CanAccessFrame(accessing_window, |
- target->GetDocument().GetSecurityOrigin(), |
- target->GetDocument().domWindow(), reporting_option); |
+ return CanAccessWindow(accessing_window, target->GetDocument().domWindow(), |
+ reporting_option); |
} |
bool BindingSecurity::ShouldAllowAccessToFrame( |
@@ -206,9 +216,8 @@ bool BindingSecurity::ShouldAllowAccessToFrame( |
ExceptionState& exception_state) { |
if (!target || !target->GetSecurityContext()) |
return false; |
- return CanAccessFrame(accessing_window, |
- target->GetSecurityContext()->GetSecurityOrigin(), |
- target->DomWindow(), exception_state); |
+ return CanAccessWindow(accessing_window, target->DomWindow(), |
+ exception_state); |
} |
bool BindingSecurity::ShouldAllowAccessToFrame( |
@@ -217,25 +226,8 @@ bool BindingSecurity::ShouldAllowAccessToFrame( |
ErrorReportOption reporting_option) { |
if (!target || !target->GetSecurityContext()) |
return false; |
- return CanAccessFrame(accessing_window, |
- target->GetSecurityContext()->GetSecurityOrigin(), |
- target->DomWindow(), reporting_option); |
-} |
- |
-bool BindingSecurity::ShouldAllowAccessToDetachedWindow( |
- const LocalDOMWindow* accessing_window, |
- const DOMWindow* target, |
- ExceptionState& exception_state) { |
- CHECK(target && !target->GetFrame()) |
- << "This version of shouldAllowAccessToFrame() must be used only for " |
- << "detached windows."; |
- if (!target->IsLocalDOMWindow()) |
- return false; |
- Document* document = ToLocalDOMWindow(target)->document(); |
- if (!document) |
- return false; |
- return CanAccessFrame(accessing_window, document->GetSecurityOrigin(), target, |
- exception_state); |
+ return CanAccessWindow(accessing_window, target->DomWindow(), |
+ reporting_option); |
} |
bool BindingSecurity::ShouldAllowNamedAccessTo( |
@@ -280,13 +272,19 @@ bool BindingSecurity::ShouldAllowAccessToCreationContext( |
LocalFrame* frame = ToLocalFrameIfNotDetached(creation_context); |
ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, |
type->interface_name); |
+ // TODO(dcheng): Why doesn't this code just use DOMWindows throughout? Can't |
+ // we just always use ToLocalDOMWindow(creation_context)? |
if (!frame) { |
// Sandbox detached frames - they can't create cross origin objects. |
LocalDOMWindow* calling_window = CurrentDOMWindow(isolate); |
LocalDOMWindow* target_window = ToLocalDOMWindow(creation_context); |
- return ShouldAllowAccessToDetachedWindow(calling_window, target_window, |
- exception_state); |
+ // TODO(https://crbug.com/723057): This is tricky: this intentionally uses |
+ // the internal CanAccessWindow() helper rather than ShouldAllowAccessTo(). |
+ // ShouldAllowAccessTo() unconditionally denies access if the DOMWindow is |
+ // not attached to a Frame, but this code is intended for handling the |
+ // detached DOMWindow case. |
+ return CanAccessWindow(calling_window, target_window, exception_state); |
} |
const DOMWrapperWorld& current_world = |
DOMWrapperWorld::World(isolate->GetCurrentContext()); |
@@ -326,22 +324,28 @@ void BindingSecurity::InitWrapperCreationSecurityCheck() { |
} |
void BindingSecurity::FailedAccessCheckFor(v8::Isolate* isolate, |
- const Frame* target) { |
- // TODO(dcheng): See if this null check can be removed or hoisted to a |
- // different location. |
- if (!target) |
+ const WrapperTypeInfo* type, |
+ v8::Local<v8::Object> holder) { |
+ DOMWindow* target = FindWindow(isolate, type, holder); |
+ // Failing to find a target means something is wrong. Failing to throw an |
+ // exception could be a security issue, so just crash. |
+ CHECK(target); |
+ |
+ // TODO(https://crbug.com/723057): This is intended to match the legacy |
+ // behavior of when access checks revolved around Frame pointers rather than |
+ // DOMWindow pointers. This prevents web-visible behavior changes, since the |
+ // previous implementation had to follow the back pointer to the Frame, and |
+ // would have to early return when it was null. |
+ if (!target->GetFrame()) |
return; |
- DOMWindow* target_window = target->DomWindow(); |
- |
// TODO(dcheng): Add ContextType, interface name, and property name as |
// arguments, so the generated exception can be more descriptive. |
ExceptionState exception_state(isolate, ExceptionState::kUnknownContext, |
nullptr, nullptr); |
exception_state.ThrowSecurityError( |
- target_window->SanitizedCrossDomainAccessErrorMessage( |
- CurrentDOMWindow(isolate)), |
- target_window->CrossDomainAccessErrorMessage(CurrentDOMWindow(isolate))); |
+ target->SanitizedCrossDomainAccessErrorMessage(CurrentDOMWindow(isolate)), |
+ target->CrossDomainAccessErrorMessage(CurrentDOMWindow(isolate))); |
} |
} // namespace blink |