WindowFeatures.cpp [plain text]
#include "config.h"
#include "WindowFeatures.h"
#include "FloatRect.h"
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
static bool isWindowFeaturesSeparator(UChar c)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
}
WindowFeatures::WindowFeatures(const String& features)
: resizable(true)
, fullscreen(false)
, dialog(false)
{
if (features.isEmpty()) {
menuBarVisible = true;
statusBarVisible = true;
toolBarVisible = true;
locationBarVisible = true;
scrollbarsVisible = true;
return;
}
menuBarVisible = false;
statusBarVisible = false;
toolBarVisible = false;
locationBarVisible = false;
scrollbarsVisible = false;
unsigned keyBegin, keyEnd;
unsigned valueBegin, valueEnd;
String buffer = features.lower();
unsigned length = buffer.length();
for (unsigned i = 0; i < length; ) {
while (isWindowFeaturesSeparator(buffer[i])) {
if (i >= length)
break;
i++;
}
keyBegin = i;
while (!isWindowFeaturesSeparator(buffer[i]))
i++;
keyEnd = i;
while (buffer[i] != '=') {
if (buffer[i] == ',' || i >= length)
break;
i++;
}
while (isWindowFeaturesSeparator(buffer[i])) {
if (buffer[i] == ',' || i >= length)
break;
i++;
}
valueBegin = i;
while (!isWindowFeaturesSeparator(buffer[i]))
i++;
valueEnd = i;
ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
String keyString(buffer.substring(keyBegin, keyEnd - keyBegin));
String valueString(buffer.substring(valueBegin, valueEnd - valueBegin));
setWindowFeature(keyString, valueString);
}
}
void WindowFeatures::setWindowFeature(const String& keyString, const String& valueString)
{
int value;
if (valueString.isEmpty() || valueString == "yes")
value = 1;
else
value = valueString.toInt();
if (keyString == "left" || keyString == "screenx")
x = value;
else if (keyString == "top" || keyString == "screeny")
y = value;
else if (keyString == "width" || keyString == "innerwidth")
width = value;
else if (keyString == "height" || keyString == "innerheight")
height = value;
else if (keyString == "menubar")
menuBarVisible = value;
else if (keyString == "toolbar")
toolBarVisible = value;
else if (keyString == "location")
locationBarVisible = value;
else if (keyString == "status")
statusBarVisible = value;
else if (keyString == "fullscreen")
fullscreen = value;
else if (keyString == "scrollbars")
scrollbarsVisible = value;
else if (value == 1)
additionalFeatures.append(keyString);
}
WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
: menuBarVisible(false)
, toolBarVisible(false)
, locationBarVisible(false)
, fullscreen(false)
, dialog(true)
{
auto features = parseDialogFeatures(dialogFeaturesString);
const bool trusted = false;
width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450);
auto dialogLeft = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - *width, -1);
if (dialogLeft > 0)
x = dialogLeft;
auto dialogTop = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - *height, -1);
if (dialogTop > 0)
y = dialogTop;
if (boolFeature(features, "center", true)) {
if (!x)
x = screenAvailableRect.x() + (screenAvailableRect.width() - *width) / 2;
if (!y)
y = screenAvailableRect.y() + (screenAvailableRect.height() - *height) / 2;
}
resizable = boolFeature(features, "resizable");
scrollbarsVisible = boolFeature(features, "scroll", true);
statusBarVisible = boolFeature(features, "status", !trusted);
}
bool WindowFeatures::boolFeature(const HashMap<String, String>& features, const char* key, bool defaultValue)
{
auto it = features.find(key);
if (it == features.end())
return defaultValue;
const String& value = it->value;
return value.isNull() || value == "1" || value == "yes" || value == "on";
}
float WindowFeatures::floatFeature(const HashMap<String, String>& features, const char* key, float min, float max, float defaultValue)
{
auto it = features.find(key);
if (it == features.end())
return defaultValue;
bool ok;
double parsedNumber = it->value.toDouble(&ok);
if ((!parsedNumber && !ok) || std::isnan(parsedNumber))
return defaultValue;
if (parsedNumber < min || max <= min)
return min;
if (parsedNumber > max)
return max;
return static_cast<int>(parsedNumber);
}
HashMap<String, String> WindowFeatures::parseDialogFeatures(const String& string)
{
HashMap<String, String> features;
Vector<String> vector;
string.split(';', vector);
for (auto& featureString : vector) {
size_t separatorPosition = featureString.find('=');
size_t colonPosition = featureString.find(':');
if (separatorPosition != notFound && colonPosition != notFound)
continue; if (separatorPosition == notFound)
separatorPosition = colonPosition;
String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
String value;
if (separatorPosition != notFound) {
value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
value = value.left(value.find(' '));
}
features.set(key, value);
}
return features;
}
}