2 * Copyright (C) 2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reseved.
5 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
24 #include "core/page/WindowFeatures.h"
26 #include "platform/geometry/IntRect.h"
27 #include "wtf/Assertions.h"
28 #include "wtf/MathExtras.h"
29 #include "wtf/text/StringHash.h"
33 // Though isspace() considers \t and \v to be whitespace, Win IE doesn't when parsing window features.
34 static bool isWindowFeaturesSeparator(UChar c
)
36 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r' || c
== '=' || c
== ',' || c
== '\0';
39 WindowFeatures::WindowFeatures(const String
& features
)
53 The IE rule is: all features except for channelmode and fullscreen default to YES, but
54 if the user specifies a feature string, all features default to NO. (There is no public
55 standard that applies to this method.)
57 <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
58 We always allow a window to be resized, which is consistent with Firefox.
61 if (features
.isEmpty()) {
62 menuBarVisible
= true;
63 statusBarVisible
= true;
64 toolBarVisible
= true;
65 locationBarVisible
= true;
66 scrollbarsVisible
= true;
70 menuBarVisible
= false;
71 statusBarVisible
= false;
72 toolBarVisible
= false;
73 locationBarVisible
= false;
74 scrollbarsVisible
= false;
76 // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
77 unsigned keyBegin
, keyEnd
;
78 unsigned valueBegin
, valueEnd
;
80 String buffer
= features
.lower();
81 unsigned length
= buffer
.length();
82 for (unsigned i
= 0; i
< length
; ) {
83 // skip to first non-separator, but don't skip past the end of the string
84 while (i
< length
&& isWindowFeaturesSeparator(buffer
[i
]))
88 // skip to first separator
89 while (i
< length
&& !isWindowFeaturesSeparator(buffer
[i
]))
93 ASSERT_WITH_SECURITY_IMPLICATION(i
<= length
);
95 // skip to first '=', but don't skip past a ',' or the end of the string
96 while (i
< length
&& buffer
[i
] != '=') {
102 ASSERT_WITH_SECURITY_IMPLICATION(i
<= length
);
104 // skip to first non-separator, but don't skip past a ',' or the end of the string
105 while (i
< length
&& isWindowFeaturesSeparator(buffer
[i
])) {
106 if (buffer
[i
] == ',')
112 ASSERT_WITH_SECURITY_IMPLICATION(i
<= length
);
114 // skip to first separator
115 while (i
< length
&& !isWindowFeaturesSeparator(buffer
[i
]))
119 ASSERT_WITH_SECURITY_IMPLICATION(i
<= length
);
121 String
keyString(buffer
.substring(keyBegin
, keyEnd
- keyBegin
));
122 String
valueString(buffer
.substring(valueBegin
, valueEnd
- valueBegin
));
123 setWindowFeature(keyString
, valueString
);
127 void WindowFeatures::setWindowFeature(const String
& keyString
, const String
& valueString
)
131 // Listing a key with no value is shorthand for key=yes
132 if (valueString
.isEmpty() || valueString
== "yes")
135 value
= valueString
.toInt();
137 // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
138 // This is consistent with Firefox, but could also be handled at another level.
140 if (keyString
== "left" || keyString
== "screenx") {
143 } else if (keyString
== "top" || keyString
== "screeny") {
146 } else if (keyString
== "width" || keyString
== "innerwidth") {
149 } else if (keyString
== "height" || keyString
== "innerheight") {
152 } else if (keyString
== "menubar") {
153 menuBarVisible
= value
;
154 } else if (keyString
== "toolbar") {
155 toolBarVisible
= value
;
156 } else if (keyString
== "location") {
157 locationBarVisible
= value
;
158 } else if (keyString
== "status") {
159 statusBarVisible
= value
;
160 } else if (keyString
== "fullscreen") {
162 } else if (keyString
== "scrollbars") {
163 scrollbarsVisible
= value
;
164 } else if (value
== 1) {
165 additionalFeatures
.append(keyString
);
169 WindowFeatures::WindowFeatures(const String
& dialogFeaturesString
, const IntRect
& screenAvailableRect
)
172 , menuBarVisible(false)
173 , toolBarVisible(false)
174 , locationBarVisible(false)
178 DialogFeaturesMap features
;
179 parseDialogFeatures(dialogFeaturesString
, features
);
181 const bool trusted
= false;
183 // The following features from Microsoft's documentation are not implemented:
184 // - default font settings
185 // - width, height, left, and top specified in units other than "px"
186 // - edge (sunken or raised, default is raised)
187 // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
188 // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
189 // - unadorned: trusted && boolFeature(features, "unadorned");
191 width
= intFeature(features
, "dialogwidth", 100, screenAvailableRect
.width(), 620); // default here came from frame size of dialog in MacIE
192 height
= intFeature(features
, "dialogheight", 100, screenAvailableRect
.height(), 450); // default here came from frame size of dialog in MacIE
194 x
= intFeature(features
, "dialogleft", screenAvailableRect
.x(), screenAvailableRect
.maxX() - width
, -1);
196 y
= intFeature(features
, "dialogtop", screenAvailableRect
.y(), screenAvailableRect
.maxY() - height
, -1);
199 if (boolFeature(features
, "center", true)) {
201 x
= screenAvailableRect
.x() + (screenAvailableRect
.width() - width
) / 2;
205 y
= screenAvailableRect
.y() + (screenAvailableRect
.height() - height
) / 2;
210 resizable
= boolFeature(features
, "resizable");
211 scrollbarsVisible
= boolFeature(features
, "scroll", true);
212 statusBarVisible
= boolFeature(features
, "status", !trusted
);
215 bool WindowFeatures::boolFeature(const DialogFeaturesMap
& features
, const char* key
, bool defaultValue
)
217 DialogFeaturesMap::const_iterator it
= features
.find(key
);
218 if (it
== features
.end())
220 const String
& value
= it
->value
;
221 return value
.isNull() || value
== "1" || value
== "yes" || value
== "on";
224 int WindowFeatures::intFeature(const DialogFeaturesMap
& features
, const char* key
, int min
, int max
, int defaultValue
)
226 DialogFeaturesMap::const_iterator it
= features
.find(key
);
227 if (it
== features
.end())
230 int parsedNumber
= it
->value
.toInt(&ok
);
233 if (parsedNumber
< min
|| max
<= min
)
235 if (parsedNumber
> max
)
240 void WindowFeatures::parseDialogFeatures(const String
& string
, DialogFeaturesMap
& map
)
242 Vector
<String
> vector
;
243 string
.split(';', vector
);
244 size_t size
= vector
.size();
245 for (size_t i
= 0; i
< size
; ++i
) {
246 const String
& featureString
= vector
[i
];
248 size_t separatorPosition
= featureString
.find('=');
249 size_t colonPosition
= featureString
.find(':');
250 if (separatorPosition
!= kNotFound
&& colonPosition
!= kNotFound
)
251 continue; // ignore strings that have both = and :
252 if (separatorPosition
== kNotFound
)
253 separatorPosition
= colonPosition
;
255 String key
= featureString
.left(separatorPosition
).stripWhiteSpace().lower();
257 // Null string for value indicates key without value.
259 if (separatorPosition
!= kNotFound
) {
260 value
= featureString
.substring(separatorPosition
+ 1).stripWhiteSpace().lower();
261 value
= value
.left(value
.find(' '));