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/FloatRect.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)
48 The IE rule is: all features except for channelmode and fullscreen default to YES, but
49 if the user specifies a feature string, all features default to NO. (There is no public
50 standard that applies to this method.)
52 <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
53 We always allow a window to be resized, which is consistent with Firefox.
56 if (features.length() == 0) {
57 menuBarVisible = true;
58 statusBarVisible = true;
59 toolBarVisible = true;
60 locationBarVisible = true;
61 scrollbarsVisible = true;
66 menuBarVisible = false;
67 statusBarVisible = false;
68 toolBarVisible = false;
69 locationBarVisible = false;
70 scrollbarsVisible = false;
73 // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
75 int valueBegin, valueEnd;
78 int length = features.length();
79 String buffer = features.lower();
81 // skip to first non-separator, but don't skip past the end of the string
82 while (isWindowFeaturesSeparator(buffer[i])) {
89 // skip to first separator
90 while (!isWindowFeaturesSeparator(buffer[i]))
94 // skip to first '=', but don't skip past a ',' or the end of the string
95 while (buffer[i] != '=') {
96 if (buffer[i] == ',' || i >= length)
101 // skip to first non-separator, but don't skip past a ',' or the end of the string
102 while (isWindowFeaturesSeparator(buffer[i])) {
103 if (buffer[i] == ',' || i >= length)
109 // skip to first separator
110 while (!isWindowFeaturesSeparator(buffer[i]))
114 ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
116 String keyString(buffer.substring(keyBegin, keyEnd - keyBegin));
117 String valueString(buffer.substring(valueBegin, valueEnd - valueBegin));
118 setWindowFeature(keyString, valueString);
122 void WindowFeatures::setWindowFeature(const String& keyString, const String& valueString)
126 // Listing a key with no value is shorthand for key=yes
127 if (valueString.isEmpty() || valueString == "yes")
130 value = valueString.toInt();
132 // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
133 // This is consistent with Firefox, but could also be handled at another level.
135 if (keyString == "left" || keyString == "screenx") {
138 } else if (keyString == "top" || keyString == "screeny") {
141 } else if (keyString == "width" || keyString == "innerwidth") {
144 } else if (keyString == "height" || keyString == "innerheight") {
147 } else if (keyString == "menubar")
148 menuBarVisible = value;
149 else if (keyString == "toolbar")
150 toolBarVisible = value;
151 else if (keyString == "location")
152 locationBarVisible = value;
153 else if (keyString == "status")
154 statusBarVisible = value;
155 else if (keyString == "fullscreen")
157 else if (keyString == "scrollbars")
158 scrollbarsVisible = value;
160 additionalFeatures.append(keyString);
163 WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
166 , menuBarVisible(false)
167 , toolBarVisible(false)
168 , locationBarVisible(false)
172 DialogFeaturesMap features;
173 parseDialogFeatures(dialogFeaturesString, features);
175 const bool trusted = false;
177 // The following features from Microsoft's documentation are not implemented:
178 // - default font settings
179 // - width, height, left, and top specified in units other than "px"
180 // - edge (sunken or raised, default is raised)
181 // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
182 // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
183 // - unadorned: trusted && boolFeature(features, "unadorned");
185 width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
186 height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE
188 x = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - width, -1);
190 y = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - height, -1);
193 if (boolFeature(features, "center", true)) {
195 x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
199 y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
204 resizable = boolFeature(features, "resizable");
205 scrollbarsVisible = boolFeature(features, "scroll", true);
206 statusBarVisible = boolFeature(features, "status", !trusted);
209 bool WindowFeatures::boolFeature(const DialogFeaturesMap& features, const char* key, bool defaultValue)
211 DialogFeaturesMap::const_iterator it = features.find(key);
212 if (it == features.end())
214 const String& value = it->value;
215 return value.isNull() || value == "1" || value == "yes" || value == "on";
218 float WindowFeatures::floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max, float defaultValue)
220 DialogFeaturesMap::const_iterator it = features.find(key);
221 if (it == features.end())
223 // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
224 // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
226 double parsedNumber = it->value.toDouble(&ok);
227 if ((!parsedNumber && !ok) || std::isnan(parsedNumber))
229 if (parsedNumber < min || max <= min)
231 if (parsedNumber > max)
233 // FIXME: Seems strange to cast a double to int and then convert back to a float. Why is this a good idea?
234 return static_cast<int>(parsedNumber);
237 void WindowFeatures::parseDialogFeatures(const String& string, DialogFeaturesMap& map)
239 Vector<String> vector;
240 string.split(';', vector);
241 size_t size = vector.size();
242 for (size_t i = 0; i < size; ++i) {
243 const String& featureString = vector[i];
245 size_t separatorPosition = featureString.find('=');
246 size_t colonPosition = featureString.find(':');
247 if (separatorPosition != kNotFound && colonPosition != kNotFound)
248 continue; // ignore strings that have both = and :
249 if (separatorPosition == kNotFound)
250 separatorPosition = colonPosition;
252 String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
254 // Null string for value indicates key without value.
256 if (separatorPosition != kNotFound) {
257 value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
258 value = value.left(value.find(' '));
265 } // namespace WebCore