Changeset 42447 in webkit


Ignore:
Timestamp:
Apr 13, 2009 12:50:32 PM (15 years ago)
Author:
weinig@apple.com
Message:

WebCore:

2009-04-13 Sam Weinig <sam@webkit.org>

Reviewed by Oliver Hunt.

Move open and showModalDialog functions out of JSDOMWindowBase
and into JSDOMWindow by partially generating them.

This slightly changes the behavior of getting window.showModalDialog
when the embedding app does not support it to return undefined regardless
of shadowing. This should not be an issue in a practice, but will be addressed
when we add a generic way to handle runtime specialization of property
access.

  • DerivedSources.make: Remove JSDOMWindowBase.lut.h
  • WebCore.xcodeproj/project.pbxproj: Ditto.
  • bindings/js/JSDOMWindowBase.cpp: (WebCore::): (WebCore::JSDOMWindowBase::getOwnPropertySlot): Move canShowModalDialog check from here to JSDOMWindow::customGetOwnPropertySlot. (WebCore::JSDOMWindowBase::put): Remove dead code.
  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::createWindow): (WebCore::JSDOMWindow::open): (WebCore::JSDOMWindow::showModalDialog):
  • bindings/js/JSDOMWindowCustom.h: (WebCore::JSDOMWindow::customGetOwnPropertySlot):
  • page/DOMWindow.cpp: (WebCore::DOMWindow::parseModalDialogFeatures): Move from JSDOMWindowBase. (WebCore::DOMWindow::allowPopUp): Ditto. (WebCore::DOMWindow::canShowModalDialog): Ditto. (WebCore::DOMWindow::canShowModalDialogNow): Ditto.
  • page/DOMWindow.h:
  • page/DOMWindow.idl:

LayoutTests:

2009-04-13 Sam Weinig <sam@webkit.org>

Reviewed by Oliver Hunt.

Update tests after moving showModalDialog from JSDOMWindowBase to
JSDOMWindow and slightly changing the behavior when showModalDialog
is not available, as is the case for DumpRenderTree.

  • fast/dom/Window/window-function-frame-getter-precedence-expected.txt:
  • fast/dom/Window/window-properties-expected.txt:
  • platform/mac-leopard/fast/dom/Window/window-properties-expected.txt:
Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r42442 r42447  
     12009-04-13  Sam Weinig  <sam@webkit.org>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        Update tests after moving showModalDialog from JSDOMWindowBase to
     6        JSDOMWindow and slightly changing the behavior when showModalDialog
     7        is not available, as is the case for DumpRenderTree.
     8
     9        * fast/dom/Window/window-function-frame-getter-precedence-expected.txt:
     10        * fast/dom/Window/window-properties-expected.txt:
     11        * platform/mac-leopard/fast/dom/Window/window-properties-expected.txt:
     12
    1132009-04-13  Darin Fisher  <darin@chromium.org>
    214
  • trunk/LayoutTests/fast/dom/Window/window-function-frame-getter-precedence-expected.txt

    r30157 r42447  
    3131PASS: typeof window.addEventListener should be object and is.
    3232PASS: typeof window.removeEventListener should be object and is.
    33 PASS: typeof window.showModalDialog should be object and is.
     33FAIL: typeof window.showModalDialog should be object but instead is undefined
    3434PASS: typeof window.captureEvents should be object and is.
    3535PASS: typeof window.releaseEvents should be object and is.
  • trunk/LayoutTests/fast/dom/Window/window-properties-expected.txt

    r42441 r42447  
    17581758window.setInterval [function]
    17591759window.setTimeout [function]
     1760window.showModalDialog [undefined]
    17601761window.status [string]
    17611762window.statusbar [object BarInfo]
  • trunk/LayoutTests/platform/mac-leopard/fast/dom/Window/window-properties-expected.txt

    r42441 r42447  
    17531753window.setInterval [function]
    17541754window.setTimeout [function]
     1755window.showModalDialog [undefined]
    17551756window.status [string]
    17561757window.statusbar [object BarInfo]
  • trunk/WebCore/ChangeLog

    r42446 r42447  
     12009-04-13  Sam Weinig  <sam@webkit.org>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        Move open and showModalDialog functions out of JSDOMWindowBase
     6        and into JSDOMWindow by partially generating them.
     7
     8        This slightly changes the behavior of getting window.showModalDialog
     9        when the embedding app does not support it to return undefined regardless
     10        of shadowing.  This should not be an issue in a practice, but will be addressed
     11        when we add a generic way to handle runtime specialization of property
     12        access.
     13
     14        * DerivedSources.make: Remove JSDOMWindowBase.lut.h
     15        * WebCore.xcodeproj/project.pbxproj: Ditto.
     16        * bindings/js/JSDOMWindowBase.cpp:
     17        (WebCore::):
     18        (WebCore::JSDOMWindowBase::getOwnPropertySlot): Move canShowModalDialog check from
     19        here to JSDOMWindow::customGetOwnPropertySlot.
     20        (WebCore::JSDOMWindowBase::put): Remove dead code.
     21        * bindings/js/JSDOMWindowCustom.cpp:
     22        (WebCore::createWindow):
     23        (WebCore::JSDOMWindow::open):
     24        (WebCore::JSDOMWindow::showModalDialog):
     25        * bindings/js/JSDOMWindowCustom.h:
     26        (WebCore::JSDOMWindow::customGetOwnPropertySlot):
     27        * page/DOMWindow.cpp:
     28        (WebCore::DOMWindow::parseModalDialogFeatures): Move from JSDOMWindowBase.
     29        (WebCore::DOMWindow::allowPopUp): Ditto.
     30        (WebCore::DOMWindow::canShowModalDialog): Ditto.
     31        (WebCore::DOMWindow::canShowModalDialogNow): Ditto.
     32        * page/DOMWindow.h:
     33        * page/DOMWindow.idl:
     34
    1352009-04-13  Geoffrey Garen  <ggaren@apple.com>
    236
  • trunk/WebCore/DerivedSources.make

    r42361 r42447  
    387387    $(filter-out JSEventListener.h JSEventTarget.h JSRGBColor.h,$(DOM_CLASSES:%=JS%.h)) \
    388388    \
    389     JSDOMWindowBase.lut.h \
    390389    JSRGBColor.lut.h \
    391390    JSWorkerContextBase.lut.h \
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r42437 r42447  
    42584258                BCEFE1EA0DCA5F6400739219 /* JSXSLTProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCEFE1E80DCA5F6400739219 /* JSXSLTProcessor.cpp */; };
    42594259                BCEFE1EB0DCA5F6400739219 /* JSXSLTProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEFE1E90DCA5F6400739219 /* JSXSLTProcessor.h */; };
    4260                 BCF937E70E8B2E95005C7AB7 /* JSDOMWindowBase.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF937E60E8B2E95005C7AB7 /* JSDOMWindowBase.lut.h */; };
    42614260                BCFB2E5E0979E46400BA703D /* CachedResourceClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFB2E5D0979E46400BA703D /* CachedResourceClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
    42624261                BCFB2F76097A2E1A00BA703D /* Arena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFB2F74097A2E1A00BA703D /* Arena.cpp */; };
     
    90609059                BCEFE1E80DCA5F6400739219 /* JSXSLTProcessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXSLTProcessor.cpp; sourceTree = "<group>"; };
    90619060                BCEFE1E90DCA5F6400739219 /* JSXSLTProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSXSLTProcessor.h; sourceTree = "<group>"; };
    9062                 BCF937E60E8B2E95005C7AB7 /* JSDOMWindowBase.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMWindowBase.lut.h; sourceTree = "<group>"; };
    90639061                BCFB2E5D0979E46400BA703D /* CachedResourceClient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CachedResourceClient.h; sourceTree = "<group>"; };
    90649062                BCFB2F74097A2E1A00BA703D /* Arena.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Arena.cpp; sourceTree = "<group>"; };
     
    1360913607                                1403BA0B09EB18C700797C7F /* JSDOMWindow.cpp */,
    1361013608                                1403BA0E09EB18F800797C7F /* JSDOMWindow.h */,
    13611                                 BCF937E60E8B2E95005C7AB7 /* JSDOMWindowBase.lut.h */,
    1361213609                                BC94D14C0C275C68006BC617 /* JSHistory.cpp */,
    1361313610                                BC94D14D0C275C68006BC617 /* JSHistory.h */,
     
    1577915776                                E10BB3860F14B95000560E13 /* JSDOMStringList.h in Headers */,
    1578015777                                BC6932740D7E293900AE44D1 /* JSDOMWindowBase.h in Headers */,
    15781                                 BCF937E70E8B2E95005C7AB7 /* JSDOMWindowBase.lut.h in Headers */,
    1578215778                                652FBBBC0DE27CB60001D386 /* JSDOMWindowCustom.h in Headers */,
    1578315779                                BCBFB53D0DCD29CF0019B3E5 /* JSDOMWindowShell.h in Headers */,
  • trunk/WebCore/bindings/js/JSDOMWindowBase.cpp

    r42430 r42447  
    2929#include "DOMWindow.h"
    3030#include "Element.h"
    31 #include "FloatRect.h"
    3231#include "Frame.h"
    33 #include "FrameLoadRequest.h"
    3432#include "HTMLDocument.h"
    3533#include "InspectorController.h"
    3634#include "JSDOMWindowCustom.h"
    37 #include "JSEvent.h"
    3835#include "JSHTMLCollection.h"
    3936#include "JSNode.h"
    4037#include "Logging.h"
    4138#include "Page.h"
    42 #include "PlatformScreen.h"
    43 #include "RenderView.h"
    4439#include "ScheduledAction.h"
    4540#include "ScriptController.h"
    4641#include "SecurityOrigin.h"
    4742#include "Settings.h"
    48 #include "WindowFeatures.h"
    4943#include <runtime/JSLock.h>
    50 #include <wtf/MathExtras.h>
    5144
    5245using namespace JSC;
    5346
    54 static JSValuePtr windowProtoFuncOpen(ExecState*, JSObject*, JSValuePtr, const ArgList&);
    55 static JSValuePtr windowProtoFuncShowModalDialog(ExecState*, JSObject*, JSValuePtr, const ArgList&);
    56 
    57 #include "JSDOMWindowBase.lut.h"
    58 
    5947namespace WebCore {
    6048
    6149////////////////////// JSDOMWindowBase Object ////////////////////////
    6250
    63 const ClassInfo JSDOMWindowBase::s_info = { "Window", 0, &JSDOMWindowBaseTable, 0 };
    64 
    65 /*
    66 @begin JSDOMWindowBaseTable
    67 # -- Functions --
    68   open                          windowProtoFuncOpen                         DontDelete|Function 3
    69   showModalDialog               windowProtoFuncShowModalDialog              DontDelete|Function 1
    70 @end
    71 */
     51const ClassInfo JSDOMWindowBase::s_info = { "Window", 0, 0, 0 };
    7252
    7353JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
     
    10383{
    10484    return d()->impl->document();
    105 }
    106 
    107 static bool allowPopUp(ExecState* exec)
    108 {
    109     Frame* frame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    110 
    111     ASSERT(frame);
    112     if (frame->script()->processingUserGesture())
    113         return true;
    114     Settings* settings = frame->settings();
    115     return settings && settings->JavaScriptCanOpenWindowsAutomatically();
    116 }
    117 
    118 static HashMap<String, String> parseModalDialogFeatures(const String& featuresArg)
    119 {
    120     HashMap<String, String> map;
    121 
    122     Vector<String> features;
    123     featuresArg.split(';', features);
    124     Vector<String>::const_iterator end = features.end();
    125     for (Vector<String>::const_iterator it = features.begin(); it != end; ++it) {
    126         String s = *it;
    127         int pos = s.find('=');
    128         int colonPos = s.find(':');
    129         if (pos >= 0 && colonPos >= 0)
    130             continue; // ignore any strings that have both = and :
    131         if (pos < 0)
    132             pos = colonPos;
    133         if (pos < 0) {
    134             // null string for value means key without value
    135             map.set(s.stripWhiteSpace().lower(), String());
    136         } else {
    137             String key = s.left(pos).stripWhiteSpace().lower();
    138             String val = s.substring(pos + 1).stripWhiteSpace().lower();
    139             int spacePos = val.find(' ');
    140             if (spacePos != -1)
    141                 val = val.left(spacePos);
    142             map.set(key, val);
    143         }
    144     }
    145 
    146     return map;
    147 }
    148 
    149 static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& url,
    150     const String& frameName, const WindowFeatures& windowFeatures, JSValuePtr dialogArgs)
    151 {
    152     Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    153     ASSERT(activeFrame);
    154 
    155     ResourceRequest request;
    156 
    157     request.setHTTPReferrer(activeFrame->loader()->outgoingReferrer());
    158     FrameLoader::addHTTPOriginIfNeeded(request, activeFrame->loader()->outgoingOrigin());
    159     FrameLoadRequest frameRequest(request, frameName);
    160 
    161     // FIXME: It's much better for client API if a new window starts with a URL, here where we
    162     // know what URL we are going to open. Unfortunately, this code passes the empty string
    163     // for the URL, but there's a reason for that. Before loading we have to set up the opener,
    164     // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently
    165     // do an allowsAccessFrom call using the window we create, which can't be done before creating it.
    166     // We'd have to resolve all those issues to pass the URL instead of "".
    167 
    168     bool created;
    169     // We pass in the opener frame here so it can be used for looking up the frame name, in case the active frame
    170     // is different from the opener frame, and the name references a frame relative to the opener frame, for example
    171     // "_self" or "_parent".
    172     Frame* newFrame = activeFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created);
    173     if (!newFrame)
    174         return 0;
    175 
    176     newFrame->loader()->setOpener(openerFrame);
    177     newFrame->loader()->setOpenedByDOM();
    178 
    179     JSDOMWindow* newWindow = toJSDOMWindow(newFrame);
    180 
    181     if (dialogArgs)
    182         newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs);
    183 
    184     if (!protocolIs(url, "javascript") || newWindow->allowsAccessFrom(exec)) {
    185         KURL completedURL = url.isEmpty() ? KURL("") : activeFrame->document()->completeURL(url);
    186         bool userGesture = activeFrame->script()->processingUserGesture();
    187 
    188         if (created)
    189             newFrame->loader()->changeLocation(completedURL, activeFrame->loader()->outgoingReferrer(), false, false, userGesture);
    190         else if (!url.isEmpty())
    191             newFrame->loader()->scheduleLocationChange(completedURL.string(), activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
    192     }
    193 
    194     return newFrame;
    195 }
    196 
    197 static bool canShowModalDialog(const Frame* frame)
    198 {
    199     if (!frame)
    200         return false;
    201 
    202     Page* page = frame->page();
    203     if (!page)
    204         return false;
    205 
    206     return page->chrome()->canRunModal();
    207 }
    208 
    209 static bool canShowModalDialogNow(const Frame* frame)
    210 {
    211     if (!frame)
    212         return false;
    213 
    214     Page* page = frame->page();
    215     if (!page)
    216         return false;
    217 
    218     return page->chrome()->canRunModalNow();
    219 }
    220 
    221 static JSValuePtr showModalDialog(ExecState* exec, Frame* frame, const String& url, JSValuePtr dialogArgs, const String& featureArgs)
    222 {
    223     if (!canShowModalDialogNow(frame) || !allowPopUp(exec))
    224         return jsUndefined();
    225 
    226     const HashMap<String, String> features = parseModalDialogFeatures(featureArgs);
    227 
    228     const bool trusted = false;
    229 
    230     // The following features from Microsoft's documentation are not implemented:
    231     // - default font settings
    232     // - width, height, left, and top specified in units other than "px"
    233     // - edge (sunken or raised, default is raised)
    234     // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
    235     // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
    236     // - unadorned: trusted && boolFeature(features, "unadorned");
    237 
    238     if (!frame)
    239         return jsUndefined();
    240 
    241     FloatRect screenRect = screenAvailableRect(frame->view());
    242 
    243     WindowFeatures wargs;
    244     wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
    245     wargs.widthSet = true;
    246     wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
    247     wargs.heightSet = true;
    248 
    249     wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);
    250     wargs.xSet = wargs.x > 0;
    251     wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);
    252     wargs.ySet = wargs.y > 0;
    253 
    254     if (WindowFeatures::boolFeature(features, "center", true)) {
    255         if (!wargs.xSet) {
    256             wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;
    257             wargs.xSet = true;
    258         }
    259         if (!wargs.ySet) {
    260             wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;
    261             wargs.ySet = true;
    262         }
    263     }
    264 
    265     wargs.dialog = true;
    266     wargs.resizable = WindowFeatures::boolFeature(features, "resizable");
    267     wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);
    268     wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);
    269     wargs.menuBarVisible = false;
    270     wargs.toolBarVisible = false;
    271     wargs.locationBarVisible = false;
    272     wargs.fullscreen = false;
    273 
    274     Frame* dialogFrame = createWindow(exec, frame, url, "", wargs, dialogArgs);
    275     if (!dialogFrame)
    276         return jsUndefined();
    277 
    278     JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame);
    279 
    280     // Get the return value either just before clearing the dialog window's
    281     // properties (in JSDOMWindowBase::clear), or when on return from runModal.
    282     JSValuePtr returnValue = noValue();
    283     dialogWindow->setReturnValueSlot(&returnValue);
    284     dialogFrame->page()->chrome()->runModal();
    285     dialogWindow->setReturnValueSlot(0);
    286 
    287     // If we don't have a return value, get it now.
    288     // Either JSDOMWindowBase::clear was not called yet, or there was no return value,
    289     // and in that case, there's no harm in trying again (no benefit either).
    290     if (!returnValue)
    291         returnValue = dialogWindow->getDirect(Identifier(exec, "returnValue"));
    292 
    293     return returnValue ? returnValue : jsUndefined();
    29485}
    29586
     
    327118    if (impl()->frame()->tree()->child(propertyName)) {
    328119        slot.setCustom(this, childFrameGetter);
    329         return true;
    330     }
    331 
    332     const HashEntry* entry = JSDOMWindowBaseTable.entry(exec, propertyName);
    333     if (entry) {
    334         if (entry->attributes() & Function) {
    335             if (entry->function() == windowProtoFuncShowModalDialog) {
    336                 if (!canShowModalDialog(impl()->frame()))
    337                     return false;
    338             }
    339             if (allowsAccessFrom(exec))
    340                 setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
    341             else
    342                 slot.setUndefined();
    343         } else
    344             slot.setCustom(this, entry->propertyGetter());
    345120        return true;
    346121    }
     
    388163void JSDOMWindowBase::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
    389164{
    390     const HashEntry* entry = JSDOMWindowBaseTable.entry(exec, propertyName);
    391     if (entry) {
    392         if (entry->attributes() & Function) {
    393             if (allowsAccessFrom(exec))
    394                 Base::put(exec, propertyName, value, slot);
    395             return;
    396         }
    397         if (entry->attributes() & ReadOnly)
    398             return;
    399     }
    400 
    401165    if (allowsAccessFrom(exec))
    402166        Base::put(exec, propertyName, value, slot);
     
    510274}
    511275
    512 } // namespace WebCore
    513 
    514 using namespace WebCore;
    515 
    516 JSValuePtr windowProtoFuncOpen(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
    517 {
    518     JSDOMWindow* window = toJSDOMWindow(thisValue);
    519     if (!window)
    520         return throwError(exec, TypeError);
    521     if (!window->allowsAccessFrom(exec))
    522         return jsUndefined();
    523 
    524     Frame* frame = window->impl()->frame();
    525     if (!frame)
    526         return jsUndefined();
    527     Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    528     if (!activeFrame)
    529         return  jsUndefined();
    530 
    531     Page* page = frame->page();
    532 
    533     String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
    534     AtomicString frameName = args.at(exec, 1).isUndefinedOrNull() ? "_blank" : AtomicString(args.at(exec, 1).toString(exec));
    535 
    536     // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
    537     // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
    538     if (!allowPopUp(exec) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
    539         return jsUndefined();
    540 
    541     // Get the target frame for the special cases of _top and _parent.  In those
    542     // cases, we can schedule a location change right now and return early.
    543     bool topOrParent = false;
    544     if (frameName == "_top") {
    545         frame = frame->tree()->top();
    546         topOrParent = true;
    547     } else if (frameName == "_parent") {
    548         if (Frame* parent = frame->tree()->parent())
    549             frame = parent;
    550         topOrParent = true;
    551     }
    552     if (topOrParent) {
    553         if (!activeFrame->loader()->shouldAllowNavigation(frame))
    554             return jsUndefined();
    555 
    556         String completedURL;
    557         if (!urlString.isEmpty())
    558             completedURL = activeFrame->document()->completeURL(urlString).string();
    559 
    560         const JSDOMWindow* targetedWindow = toJSDOMWindow(frame);
    561         if (!completedURL.isEmpty() && (!protocolIs(completedURL, "javascript") || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {
    562             bool userGesture = activeFrame->script()->processingUserGesture();
    563             frame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
    564         }
    565         return toJS(exec, frame->domWindow());
    566     }
    567 
    568     // In the case of a named frame or a new window, we'll use the createWindow() helper
    569     WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 2)));
    570     FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
    571                          windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
    572     DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
    573 
    574     windowFeatures.x = windowRect.x();
    575     windowFeatures.y = windowRect.y();
    576     windowFeatures.height = windowRect.height();
    577     windowFeatures.width = windowRect.width();
    578 
    579     frame = createWindow(exec, frame, urlString, frameName, windowFeatures, noValue());
    580 
    581     if (!frame)
    582         return jsUndefined();
    583 
    584     return toJS(exec, frame->domWindow()); // global object
    585 }
    586 
    587 JSValuePtr windowProtoFuncShowModalDialog(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
    588 {
    589     JSDOMWindow* window = toJSDOMWindow(thisValue);
    590     if (!window)
    591         return throwError(exec, TypeError);
    592     if (!window->allowsAccessFrom(exec))
    593         return jsUndefined();
    594 
    595     Frame* frame = window->impl()->frame();
    596     if (!frame)
    597         return jsUndefined();
    598 
    599     return showModalDialog(exec, frame, valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0)), args.at(exec, 1), valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 2)));
    600 }
    601 
    602 namespace WebCore {
    603 
    604276void JSDOMWindowBase::setReturnValueSlot(JSValuePtr* slot)
    605277{
    606278    d()->returnValueSlot = slot;
    607279}
    608 
    609 ////////////////////// timeouts ////////////////////////
    610280
    611281int JSDOMWindowBase::installTimeout(ScheduledAction* a, int t, bool singleShot)
  • trunk/WebCore/bindings/js/JSDOMWindowCustom.cpp

    r42446 r42447  
    2626#include "Document.h"
    2727#include "ExceptionCode.h"
     28#include "FloatRect.h"
    2829#include "Frame.h"
     30#include "FrameLoadRequest.h"
    2931#include "FrameLoader.h"
    3032#include "FrameTree.h"
     33#include "FrameView.h"
    3134#include "History.h"
    3235#include "JSAudioConstructor.h"
     
    4851#include "MediaPlayer.h"
    4952#include "MessagePort.h"
     53#include "Page.h"
     54#include "PlatformScreen.h"
    5055#include "ScriptController.h"
    5156#include "Settings.h"
     57#include "WindowFeatures.h"
    5258#include <runtime/JSObject.h>
    5359#include <runtime/PrototypeFunction.h>
     
    145151}
    146152
     153// Custom Attributes
     154
    147155JSValuePtr JSDOMWindow::history(ExecState* exec) const
    148156{
     
    263271#endif
    264272
     273// Custom functions
     274
     275// Helper for window.open() and window.showModalDialog()
     276static Frame* createWindow(ExecState* exec, Frame* activeFrame, Frame* openerFrame,
     277                           const String& url, const String& frameName,
     278                           const WindowFeatures& windowFeatures, JSValuePtr dialogArgs)
     279{
     280    ASSERT(activeFrame);
     281
     282    ResourceRequest request;
     283
     284    request.setHTTPReferrer(activeFrame->loader()->outgoingReferrer());
     285    FrameLoader::addHTTPOriginIfNeeded(request, activeFrame->loader()->outgoingOrigin());
     286    FrameLoadRequest frameRequest(request, frameName);
     287
     288    // FIXME: It's much better for client API if a new window starts with a URL, here where we
     289    // know what URL we are going to open. Unfortunately, this code passes the empty string
     290    // for the URL, but there's a reason for that. Before loading we have to set up the opener,
     291    // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently
     292    // do an allowsAccessFrom call using the window we create, which can't be done before creating it.
     293    // We'd have to resolve all those issues to pass the URL instead of "".
     294
     295    bool created;
     296    // We pass in the opener frame here so it can be used for looking up the frame name, in case the active frame
     297    // is different from the opener frame, and the name references a frame relative to the opener frame, for example
     298    // "_self" or "_parent".
     299    Frame* newFrame = activeFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created);
     300    if (!newFrame)
     301        return 0;
     302
     303    newFrame->loader()->setOpener(openerFrame);
     304    newFrame->loader()->setOpenedByDOM();
     305
     306    JSDOMWindow* newWindow = toJSDOMWindow(newFrame);
     307
     308    if (dialogArgs)
     309        newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs);
     310
     311    if (!protocolIs(url, "javascript") || newWindow->allowsAccessFrom(exec)) {
     312        KURL completedURL = url.isEmpty() ? KURL("") : activeFrame->document()->completeURL(url);
     313        bool userGesture = activeFrame->script()->processingUserGesture();
     314
     315        if (created)
     316            newFrame->loader()->changeLocation(completedURL, activeFrame->loader()->outgoingReferrer(), false, false, userGesture);
     317        else if (!url.isEmpty())
     318            newFrame->loader()->scheduleLocationChange(completedURL.string(), activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
     319    }
     320
     321    return newFrame;
     322}
     323
     324JSValuePtr JSDOMWindow::open(ExecState* exec, const ArgList& args)
     325{
     326    Frame* frame = impl()->frame();
     327    if (!frame)
     328        return jsUndefined();
     329    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
     330    if (!activeFrame)
     331        return  jsUndefined();
     332
     333    Page* page = frame->page();
     334
     335    String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
     336    AtomicString frameName = args.at(exec, 1).isUndefinedOrNull() ? "_blank" : AtomicString(args.at(exec, 1).toString(exec));
     337
     338    // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
     339    // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
     340    if (!DOMWindow::allowPopUp(activeFrame) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
     341        return jsUndefined();
     342
     343    // Get the target frame for the special cases of _top and _parent.  In those
     344    // cases, we can schedule a location change right now and return early.
     345    bool topOrParent = false;
     346    if (frameName == "_top") {
     347        frame = frame->tree()->top();
     348        topOrParent = true;
     349    } else if (frameName == "_parent") {
     350        if (Frame* parent = frame->tree()->parent())
     351            frame = parent;
     352        topOrParent = true;
     353    }
     354    if (topOrParent) {
     355        if (!activeFrame->loader()->shouldAllowNavigation(frame))
     356            return jsUndefined();
     357
     358        String completedURL;
     359        if (!urlString.isEmpty())
     360            completedURL = activeFrame->document()->completeURL(urlString).string();
     361
     362        const JSDOMWindow* targetedWindow = toJSDOMWindow(frame);
     363        if (!completedURL.isEmpty() && (!protocolIs(completedURL, "javascript") || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {
     364            bool userGesture = activeFrame->script()->processingUserGesture();
     365            frame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
     366        }
     367        return toJS(exec, frame->domWindow());
     368    }
     369
     370    // In the case of a named frame or a new window, we'll use the createWindow() helper
     371    WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 2)));
     372    FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
     373                         windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
     374    DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
     375
     376    windowFeatures.x = windowRect.x();
     377    windowFeatures.y = windowRect.y();
     378    windowFeatures.height = windowRect.height();
     379    windowFeatures.width = windowRect.width();
     380
     381    frame = createWindow(exec, activeFrame, frame, urlString, frameName, windowFeatures, noValue());
     382
     383    if (!frame)
     384        return jsUndefined();
     385
     386    return toJS(exec, frame->domWindow());
     387}
     388
     389JSValuePtr JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args)
     390{
     391    Frame* frame = impl()->frame();
     392    if (!frame)
     393        return jsUndefined();
     394
     395    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
     396
     397    if (!DOMWindow::canShowModalDialogNow(frame) || !DOMWindow::allowPopUp(activeFrame))
     398        return jsUndefined();
     399
     400    String url = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
     401    JSValuePtr dialogArgs = args.at(exec, 1);
     402    String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 2));
     403
     404    HashMap<String, String> features;
     405    DOMWindow::parseModalDialogFeatures(featureArgs, features);
     406
     407    const bool trusted = false;
     408
     409    // The following features from Microsoft's documentation are not implemented:
     410    // - default font settings
     411    // - width, height, left, and top specified in units other than "px"
     412    // - edge (sunken or raised, default is raised)
     413    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
     414    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
     415    // - unadorned: trusted && boolFeature(features, "unadorned");
     416
     417    FloatRect screenRect = screenAvailableRect(frame->view());
     418
     419    WindowFeatures wargs;
     420    wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
     421    wargs.widthSet = true;
     422    wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
     423    wargs.heightSet = true;
     424
     425    wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);
     426    wargs.xSet = wargs.x > 0;
     427    wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);
     428    wargs.ySet = wargs.y > 0;
     429
     430    if (WindowFeatures::boolFeature(features, "center", true)) {
     431        if (!wargs.xSet) {
     432            wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;
     433            wargs.xSet = true;
     434        }
     435        if (!wargs.ySet) {
     436            wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;
     437            wargs.ySet = true;
     438        }
     439    }
     440
     441    wargs.dialog = true;
     442    wargs.resizable = WindowFeatures::boolFeature(features, "resizable");
     443    wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);
     444    wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);
     445    wargs.menuBarVisible = false;
     446    wargs.toolBarVisible = false;
     447    wargs.locationBarVisible = false;
     448    wargs.fullscreen = false;
     449
     450    Frame* dialogFrame = createWindow(exec, activeFrame, frame, url, "", wargs, dialogArgs);
     451    if (!dialogFrame)
     452        return jsUndefined();
     453
     454    JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame);
     455
     456    // Get the return value either just before clearing the dialog window's
     457    // properties (in JSDOMWindowBase::clear), or when on return from runModal.
     458    JSValuePtr returnValue = noValue();
     459    dialogWindow->setReturnValueSlot(&returnValue);
     460    dialogFrame->page()->chrome()->runModal();
     461    dialogWindow->setReturnValueSlot(0);
     462
     463    // If we don't have a return value, get it now.
     464    // Either JSDOMWindowBase::clear was not called yet, or there was no return value,
     465    // and in that case, there's no harm in trying again (no benefit either).
     466    if (!returnValue)
     467        returnValue = dialogWindow->getDirect(Identifier(exec, "returnValue"));
     468
     469    return returnValue ? returnValue : jsUndefined();
     470}
     471
    265472JSValuePtr JSDOMWindow::postMessage(ExecState* exec, const ArgList& args)
    266473{
  • trunk/WebCore/bindings/js/JSDOMWindowCustom.h

    r42201 r42447  
    107107                    return true;
    108108                }
     109            } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
     110                if (!DOMWindow::canShowModalDialog(impl()->frame())) {
     111                    slot.setUndefined();
     112                    return true;
     113                }
    109114            }
    110115        }
  • trunk/WebCore/page/DOMWindow.cpp

    r42446 r42447  
    145145}
    146146
     147void DOMWindow::parseModalDialogFeatures(const String& featuresArg, HashMap<String, String>& map)
     148{
     149    Vector<String> features;
     150    featuresArg.split(';', features);
     151    Vector<String>::const_iterator end = features.end();
     152    for (Vector<String>::const_iterator it = features.begin(); it != end; ++it) {
     153        String s = *it;
     154        int pos = s.find('=');
     155        int colonPos = s.find(':');
     156        if (pos >= 0 && colonPos >= 0)
     157            continue; // ignore any strings that have both = and :
     158        if (pos < 0)
     159            pos = colonPos;
     160        if (pos < 0) {
     161            // null string for value means key without value
     162            map.set(s.stripWhiteSpace().lower(), String());
     163        } else {
     164            String key = s.left(pos).stripWhiteSpace().lower();
     165            String val = s.substring(pos + 1).stripWhiteSpace().lower();
     166            int spacePos = val.find(' ');
     167            if (spacePos != -1)
     168                val = val.left(spacePos);
     169            map.set(key, val);
     170        }
     171    }
     172}
     173
     174bool DOMWindow::allowPopUp(Frame* activeFrame)
     175{
     176    ASSERT(activeFrame);
     177    if (activeFrame->script()->processingUserGesture())
     178        return true;
     179    Settings* settings = activeFrame->settings();
     180    return settings && settings->JavaScriptCanOpenWindowsAutomatically();
     181}
     182
     183bool DOMWindow::canShowModalDialog(const Frame* frame)
     184{
     185    if (!frame)
     186        return false;
     187    Page* page = frame->page();
     188    if (!page)
     189        return false;
     190    return page->chrome()->canRunModal();
     191}
     192
     193bool DOMWindow::canShowModalDialogNow(const Frame* frame)
     194{
     195    if (!frame)
     196        return false;
     197    Page* page = frame->page();
     198    if (!page)
     199        return false;
     200    return page->chrome()->canRunModalNow();
     201}
     202
    147203DOMWindow::DOMWindow(Frame* frame)
    148204    : m_frame(frame)
  • trunk/WebCore/page/DOMWindow.h

    r42446 r42447  
    8686
    8787        static void adjustWindowRect(const FloatRect& screen, FloatRect& window, const FloatRect& pendingChanges);
     88        static void parseModalDialogFeatures(const String& featuresArg, HashMap<String, String>& map);
     89
     90        static bool allowPopUp(Frame* activeFrame);
     91        static bool canShowModalDialog(const Frame*);
     92        static bool canShowModalDialogNow(const Frame*);
    8893
    8994        // DOM Level 0
  • trunk/WebCore/page/DOMWindow.idl

    r42441 r42447  
    7070        void print();
    7171        void stop();
     72
     73        [Custom] DOMWindow open(in DOMString url,
     74                                in DOMString name,
     75                                in [Optional] DOMString options);
     76
     77        [Custom] DOMObject showModalDialog(in DOMString url,
     78                                           in [Optional] DOMObject dialogArgs,
     79                                           in [Optional] DOMString featureArgs);
    7280
    7381        void alert(in DOMString message);
     
    467475
    468476#if defined(V8_BINDING)
    469     // These were implemented in JSCDOMWindowBase and not moved to IDL yet.
    470 
    471     [Custom] DOMWindow open(in DOMString url,
    472                             in DOMString name,
    473                             in [Optional] DOMString options);
    474 
    475     [Custom] DOMObject showModalDialog(in DOMString url,
    476                                        in [Optional] DOMObject dialogArgs,
    477                                        in [Optional] DOMString featureArgs);
    478 
    479     // window.toString requires special handling
     477    // window.toString() requires special handling in V8
    480478    [V8DoNotCheckSignature, DoNotCheckDomainSecurity, Custom, DontEnum] DOMString toString();
    481479#endif // defined(V8_BINDING)
Note: See TracChangeset for help on using the changeset viewer.