1/*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef BindingSecurity_h
32#define BindingSecurity_h
33
34#include "BindingSecurityBase.h"
35#include "Element.h"
36#include "Frame.h"
37#include "GenericBinding.h"
38#include "HTMLFrameElementBase.h"
39#include "HTMLNames.h"
40#include "HTMLParserIdioms.h"
41#include "Settings.h"
42
43namespace WebCore {
44
45class DOMWindow;
46class Node;
47
48// Security functions shared by various language bindings.
49template <class Binding>
50class BindingSecurity : public BindingSecurityBase {
51public:
52    // Check if the active execution context can access the target frame.
53    static bool canAccessFrame(State<Binding>*, Frame*, bool reportError);
54
55    // Check if it is safe to access the given node from the
56    // current security context.
57    static bool checkNodeSecurity(State<Binding>*, Node* target);
58
59    static bool allowPopUp(State<Binding>*);
60    static bool allowSettingFrameSrcToJavascriptUrl(State<Binding>*, HTMLFrameElementBase*, String value);
61    static bool allowSettingSrcToJavascriptURL(State<Binding>*, Element*, String name, String value);
62
63    static bool shouldAllowNavigation(State<Binding>*, Frame*);
64
65private:
66    explicit BindingSecurity() {}
67    ~BindingSecurity();
68
69    // Check if the current DOMWindow's security context can access the target
70    // DOMWindow.  This function does not report errors, so most callers should
71    // use canAccessFrame instead.
72    static bool canAccessWindow(State<Binding>*, DOMWindow* target);
73};
74
75// Implementations of templated methods must be in this file.
76
77template <class Binding>
78bool BindingSecurity<Binding>::canAccessWindow(State<Binding>* state,
79                                               DOMWindow* targetWindow)
80{
81    DOMWindow* activeWindow = state->activeWindow();
82    return canAccess(activeWindow, targetWindow);
83}
84
85template <class Binding>
86bool BindingSecurity<Binding>::canAccessFrame(State<Binding>* state,
87                                              Frame* target,
88                                              bool reportError)
89{
90    // The subject is detached from a frame, deny accesses.
91    if (!target)
92        return false;
93
94    if (!canAccessWindow(state, getDOMWindow(target))) {
95        if (reportError)
96            state->immediatelyReportUnsafeAccessTo(target);
97        return false;
98    }
99    return true;
100}
101
102template <class Binding>
103bool BindingSecurity<Binding>::checkNodeSecurity(State<Binding>* state, Node* node)
104{
105    if (!node)
106        return false;
107
108    Frame* target = getFrame(node);
109
110    if (!target)
111        return false;
112
113    return canAccessFrame(state, target, true);
114}
115
116template <class Binding>
117bool BindingSecurity<Binding>::allowPopUp(State<Binding>* state)
118{
119    if (state->processingUserGesture())
120        return true;
121
122    Frame* frame = state->firstFrame();
123    ASSERT(frame);
124    Settings* settings = frame->settings();
125    return settings && settings->javaScriptCanOpenWindowsAutomatically();
126}
127
128template <class Binding>
129bool BindingSecurity<Binding>::allowSettingFrameSrcToJavascriptUrl(State<Binding>* state, HTMLFrameElementBase* frame, String value)
130{
131    if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value))) {
132        Node* contentDoc = frame->contentDocument();
133        if (contentDoc && !checkNodeSecurity(state, contentDoc))
134            return false;
135    }
136    return true;
137}
138
139template <class Binding>
140bool BindingSecurity<Binding>::allowSettingSrcToJavascriptURL(State<Binding>* state, Element* element, String name, String value)
141{
142    if ((element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"))
143        return allowSettingFrameSrcToJavascriptUrl(state, static_cast<HTMLFrameElementBase*>(element), value);
144    return true;
145}
146
147template <class Binding>
148bool BindingSecurity<Binding>::shouldAllowNavigation(State<Binding>* state, Frame* frame)
149{
150    Frame* activeFrame = state->activeFrame();
151    return activeFrame && activeFrame->loader()->shouldAllowNavigation(frame);
152}
153
154}
155
156#endif // BindingSecurity_h
157