Home | History | Annotate | Download | only in custom
      1 /*
      2  * Copyright (C) 2007, 2008, 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 #include "config.h"
     32 #include "V8HTMLDocument.h"
     33 
     34 #include "Frame.h"
     35 #include "HTMLAllCollection.h"
     36 #include "HTMLDocument.h"
     37 #include "HTMLCollection.h"
     38 #include "HTMLIFrameElement.h"
     39 #include "HTMLNames.h"
     40 #include "V8Binding.h"
     41 #include "V8DOMWindow.h"
     42 #include "V8HTMLAllCollection.h"
     43 #include "V8HTMLCollection.h"
     44 #include "V8IsolatedContext.h"
     45 #include "V8Node.h"
     46 #include "V8Proxy.h"
     47 #include <wtf/RefPtr.h>
     48 #include <wtf/StdLibExtras.h>
     49 
     50 namespace WebCore {
     51 
     52 v8::Handle<v8::Boolean> V8HTMLDocument::namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
     53 {
     54     // Only handle document.all.  Insert the marker object into the
     55     // shadow internal field to signal that document.all is no longer
     56     // shadowed.
     57     AtomicString key = v8StringToAtomicWebCoreString(name);
     58     DEFINE_STATIC_LOCAL(const AtomicString, all, ("all"));
     59     if (key != all)
     60         return deletionNotHandledByInterceptor();
     61 
     62     ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount);
     63     v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex);
     64     info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, marker);
     65     return v8::True();
     66 }
     67 
     68 v8::Handle<v8::Value> V8HTMLDocument::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
     69 {
     70     INC_STATS("DOM.HTMLDocument.NamedPropertyGetter");
     71     AtomicString key = v8StringToAtomicWebCoreString(name);
     72 
     73     // Special case for document.all.  If the value in the shadow
     74     // internal field is not the marker object, then document.all has
     75     // been temporarily shadowed and we return the value.
     76     DEFINE_STATIC_LOCAL(const AtomicString, all, ("all"));
     77     if (key == all) {
     78         ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount);
     79         v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex);
     80         v8::Local<v8::Value> value = info.Holder()->GetInternalField(V8HTMLDocument::shadowIndex);
     81         if (marker != value)
     82             return value;
     83     }
     84 
     85     HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder());
     86 
     87     // Fast case for named elements that are not there.
     88     if (!htmlDocument->hasNamedItem(key.impl()) && !htmlDocument->hasExtraNamedItem(key.impl()))
     89         return v8::Handle<v8::Value>();
     90 
     91     RefPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key);
     92     if (!items->length())
     93         return notHandledByInterceptor();
     94 
     95     if (items->length() == 1) {
     96         Node* node = items->firstItem();
     97         Frame* frame = 0;
     98         if (node->hasTagName(HTMLNames::iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame()))
     99             return toV8(frame->domWindow());
    100 
    101         return toV8(node);
    102     }
    103 
    104     return toV8(items.release());
    105 }
    106 
    107 v8::Handle<v8::Value> V8HTMLDocument::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo &info)
    108 {
    109     INC_STATS("DOM.HTMLDocument.IndexedPropertyGetter");
    110     v8::Local<v8::Integer> indexV8 = v8::Integer::NewFromUnsigned(index);
    111     return namedPropertyGetter(indexV8->ToString(), info);
    112 }
    113 
    114 // HTMLDocument ----------------------------------------------------------------
    115 
    116 // Concatenates "args" to a string. If args is empty, returns empty string.
    117 // Firefox/Safari/IE support non-standard arguments to document.write, ex:
    118 //   document.write("a", "b", "c") --> document.write("abc")
    119 //   document.write() --> document.write("")
    120 static String writeHelperGetString(const v8::Arguments& args)
    121 {
    122     String str = "";
    123     for (int i = 0; i < args.Length(); ++i)
    124         str += toWebCoreString(args[i]);
    125     return str;
    126 }
    127 
    128 v8::Handle<v8::Value> V8HTMLDocument::writeCallback(const v8::Arguments& args)
    129 {
    130     INC_STATS("DOM.HTMLDocument.write()");
    131     HTMLDocument* htmlDocument = V8HTMLDocument::toNative(args.Holder());
    132     Frame* frame = V8Proxy::retrieveFrameForCallingContext();
    133     htmlDocument->write(writeHelperGetString(args), frame ? frame->document() : NULL);
    134     return v8::Undefined();
    135 }
    136 
    137 v8::Handle<v8::Value> V8HTMLDocument::writelnCallback(const v8::Arguments& args)
    138 {
    139     INC_STATS("DOM.HTMLDocument.writeln()");
    140     HTMLDocument* htmlDocument = V8HTMLDocument::toNative(args.Holder());
    141     Frame* frame = V8Proxy::retrieveFrameForCallingContext();
    142     htmlDocument->writeln(writeHelperGetString(args), frame ? frame->document() : NULL);
    143     return v8::Undefined();
    144 }
    145 
    146 v8::Handle<v8::Value> V8HTMLDocument::openCallback(const v8::Arguments& args)
    147 {
    148     INC_STATS("DOM.HTMLDocument.open()");
    149     HTMLDocument* htmlDocument = V8HTMLDocument::toNative(args.Holder());
    150 
    151     if (args.Length() > 2) {
    152         if (Frame* frame = htmlDocument->frame()) {
    153             // Fetch the global object for the frame.
    154             v8::Local<v8::Context> context = V8Proxy::context(frame);
    155             // Bail out if we cannot get the context.
    156             if (context.IsEmpty())
    157                 return v8::Undefined();
    158             v8::Local<v8::Object> global = context->Global();
    159             // Get the open property of the global object.
    160             v8::Local<v8::Value> function = global->Get(v8::String::New("open"));
    161             // If the open property is not a function throw a type error.
    162             if (!function->IsFunction()) {
    163                 throwError("open is not a function");
    164                 return v8::Undefined();
    165             }
    166             // Wrap up the arguments and call the function.
    167             v8::Local<v8::Value>* params = new v8::Local<v8::Value>[args.Length()];
    168             for (int i = 0; i < args.Length(); i++)
    169                 params[i] = args[i];
    170 
    171             V8Proxy* proxy = V8Proxy::retrieve(frame);
    172             ASSERT(proxy);
    173 
    174             v8::Local<v8::Value> result = proxy->callFunction(v8::Local<v8::Function>::Cast(function), global, args.Length(), params);
    175             delete[] params;
    176             return result;
    177         }
    178     }
    179 
    180     Frame* frame = V8Proxy::retrieveFrameForCallingContext();
    181     htmlDocument->open(frame ? frame->document() : NULL);
    182     // Return the document.
    183     return args.Holder();
    184 }
    185 
    186 v8::Handle<v8::Value> V8HTMLDocument::allAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
    187 {
    188     INC_STATS("DOM.HTMLDocument.all._get");
    189     v8::Handle<v8::Object> holder = info.Holder();
    190     HTMLDocument* htmlDocument = V8HTMLDocument::toNative(holder);
    191     return toV8(htmlDocument->all());
    192 }
    193 
    194 void V8HTMLDocument::allAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
    195 {
    196     INC_STATS("DOM.HTMLDocument.all._set");
    197     v8::Handle<v8::Object> holder = info.Holder();
    198     ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount);
    199     info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, value);
    200 }
    201 
    202 v8::Handle<v8::Value> toV8(HTMLDocument* impl, bool forceNewObject)
    203 {
    204     if (!impl)
    205         return v8::Null();
    206     v8::Handle<v8::Object> wrapper = V8HTMLDocument::wrap(impl, forceNewObject);
    207     if (wrapper.IsEmpty())
    208         return wrapper;
    209     if (!V8IsolatedContext::getEntered()) {
    210         if (V8Proxy* proxy = V8Proxy::retrieve(impl->frame()))
    211             proxy->windowShell()->updateDocumentWrapper(wrapper);
    212     }
    213     // Create marker object and insert it in two internal fields.
    214     // This is used to implement temporary shadowing of document.all.
    215     ASSERT(wrapper->InternalFieldCount() == V8HTMLDocument::internalFieldCount);
    216     v8::Local<v8::Object> marker = v8::Object::New();
    217     wrapper->SetInternalField(V8HTMLDocument::markerIndex, marker);
    218     wrapper->SetInternalField(V8HTMLDocument::shadowIndex, marker);
    219     return wrapper;
    220 }
    221 
    222 } // namespace WebCore
    223