PageRenderTime 25ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/qt/qtwebkit/Source/WebCore/page/WindowFeatures.cpp

https://gitlab.com/x33n/phantomjs
C++ | 265 lines | 181 code | 34 blank | 50 comment | 100 complexity | 754397f0de403c4901babb30b4626758 MD5 | raw file
  1. /*
  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)
  6. *
  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.
  11. *
  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.
  16. *
  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
  20. * USA
  21. */
  22. #include "config.h"
  23. #include "WindowFeatures.h"
  24. #include "FloatRect.h"
  25. #include <wtf/Assertions.h>
  26. #include <wtf/MathExtras.h>
  27. #include <wtf/text/StringHash.h>
  28. namespace WebCore {
  29. // Though isspace() considers \t and \v to be whitespace, Win IE doesn't when parsing window features.
  30. static bool isWindowFeaturesSeparator(UChar c)
  31. {
  32. return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
  33. }
  34. WindowFeatures::WindowFeatures(const String& features)
  35. : xSet(false)
  36. , ySet(false)
  37. , widthSet(false)
  38. , heightSet(false)
  39. , fullscreen(false)
  40. , dialog(false)
  41. {
  42. /*
  43. The IE rule is: all features except for channelmode and fullscreen default to YES, but
  44. if the user specifies a feature string, all features default to NO. (There is no public
  45. standard that applies to this method.)
  46. <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
  47. We always allow a window to be resized, which is consistent with Firefox.
  48. */
  49. if (features.length() == 0) {
  50. menuBarVisible = true;
  51. statusBarVisible = true;
  52. toolBarVisible = true;
  53. locationBarVisible = true;
  54. scrollbarsVisible = true;
  55. resizable = true;
  56. return;
  57. }
  58. menuBarVisible = false;
  59. statusBarVisible = false;
  60. toolBarVisible = false;
  61. locationBarVisible = false;
  62. scrollbarsVisible = false;
  63. resizable = true;
  64. // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
  65. int keyBegin, keyEnd;
  66. int valueBegin, valueEnd;
  67. int i = 0;
  68. int length = features.length();
  69. String buffer = features.lower();
  70. while (i < length) {
  71. // skip to first non-separator, but don't skip past the end of the string
  72. while (isWindowFeaturesSeparator(buffer[i])) {
  73. if (i >= length)
  74. break;
  75. i++;
  76. }
  77. keyBegin = i;
  78. // skip to first separator
  79. while (!isWindowFeaturesSeparator(buffer[i]))
  80. i++;
  81. keyEnd = i;
  82. // skip to first '=', but don't skip past a ',' or the end of the string
  83. while (buffer[i] != '=') {
  84. if (buffer[i] == ',' || i >= length)
  85. break;
  86. i++;
  87. }
  88. // skip to first non-separator, but don't skip past a ',' or the end of the string
  89. while (isWindowFeaturesSeparator(buffer[i])) {
  90. if (buffer[i] == ',' || i >= length)
  91. break;
  92. i++;
  93. }
  94. valueBegin = i;
  95. // skip to first separator
  96. while (!isWindowFeaturesSeparator(buffer[i]))
  97. i++;
  98. valueEnd = i;
  99. ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
  100. String keyString(buffer.substring(keyBegin, keyEnd - keyBegin));
  101. String valueString(buffer.substring(valueBegin, valueEnd - valueBegin));
  102. setWindowFeature(keyString, valueString);
  103. }
  104. }
  105. void WindowFeatures::setWindowFeature(const String& keyString, const String& valueString)
  106. {
  107. int value;
  108. // Listing a key with no value is shorthand for key=yes
  109. if (valueString.isEmpty() || valueString == "yes")
  110. value = 1;
  111. else
  112. value = valueString.toInt();
  113. // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
  114. // This is consistent with Firefox, but could also be handled at another level.
  115. if (keyString == "left" || keyString == "screenx") {
  116. xSet = true;
  117. x = value;
  118. } else if (keyString == "top" || keyString == "screeny") {
  119. ySet = true;
  120. y = value;
  121. } else if (keyString == "width" || keyString == "innerwidth") {
  122. widthSet = true;
  123. width = value;
  124. } else if (keyString == "height" || keyString == "innerheight") {
  125. heightSet = true;
  126. height = value;
  127. } else if (keyString == "menubar")
  128. menuBarVisible = value;
  129. else if (keyString == "toolbar")
  130. toolBarVisible = value;
  131. else if (keyString == "location")
  132. locationBarVisible = value;
  133. else if (keyString == "status")
  134. statusBarVisible = value;
  135. else if (keyString == "fullscreen")
  136. fullscreen = value;
  137. else if (keyString == "scrollbars")
  138. scrollbarsVisible = value;
  139. else if (value == 1)
  140. additionalFeatures.append(keyString);
  141. }
  142. WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
  143. : widthSet(true)
  144. , heightSet(true)
  145. , menuBarVisible(false)
  146. , toolBarVisible(false)
  147. , locationBarVisible(false)
  148. , fullscreen(false)
  149. , dialog(true)
  150. {
  151. DialogFeaturesMap features;
  152. parseDialogFeatures(dialogFeaturesString, features);
  153. const bool trusted = false;
  154. // The following features from Microsoft's documentation are not implemented:
  155. // - default font settings
  156. // - width, height, left, and top specified in units other than "px"
  157. // - edge (sunken or raised, default is raised)
  158. // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
  159. // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
  160. // - unadorned: trusted && boolFeature(features, "unadorned");
  161. width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
  162. height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE
  163. x = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - width, -1);
  164. xSet = x > 0;
  165. y = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - height, -1);
  166. ySet = y > 0;
  167. if (boolFeature(features, "center", true)) {
  168. if (!xSet) {
  169. x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
  170. xSet = true;
  171. }
  172. if (!ySet) {
  173. y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
  174. ySet = true;
  175. }
  176. }
  177. resizable = boolFeature(features, "resizable");
  178. scrollbarsVisible = boolFeature(features, "scroll", true);
  179. statusBarVisible = boolFeature(features, "status", !trusted);
  180. }
  181. bool WindowFeatures::boolFeature(const DialogFeaturesMap& features, const char* key, bool defaultValue)
  182. {
  183. DialogFeaturesMap::const_iterator it = features.find(key);
  184. if (it == features.end())
  185. return defaultValue;
  186. const String& value = it->value;
  187. return value.isNull() || value == "1" || value == "yes" || value == "on";
  188. }
  189. float WindowFeatures::floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max, float defaultValue)
  190. {
  191. DialogFeaturesMap::const_iterator it = features.find(key);
  192. if (it == features.end())
  193. return defaultValue;
  194. // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
  195. // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
  196. bool ok;
  197. double parsedNumber = it->value.toDouble(&ok);
  198. if ((!parsedNumber && !ok) || std::isnan(parsedNumber))
  199. return defaultValue;
  200. if (parsedNumber < min || max <= min)
  201. return min;
  202. if (parsedNumber > max)
  203. return max;
  204. // FIXME: Seems strange to cast a double to int and then convert back to a float. Why is this a good idea?
  205. return static_cast<int>(parsedNumber);
  206. }
  207. void WindowFeatures::parseDialogFeatures(const String& string, DialogFeaturesMap& map)
  208. {
  209. Vector<String> vector;
  210. string.split(';', vector);
  211. size_t size = vector.size();
  212. for (size_t i = 0; i < size; ++i) {
  213. const String& featureString = vector[i];
  214. size_t separatorPosition = featureString.find('=');
  215. size_t colonPosition = featureString.find(':');
  216. if (separatorPosition != notFound && colonPosition != notFound)
  217. continue; // ignore strings that have both = and :
  218. if (separatorPosition == notFound)
  219. separatorPosition = colonPosition;
  220. String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
  221. // Null string for value indicates key without value.
  222. String value;
  223. if (separatorPosition != notFound) {
  224. value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
  225. value = value.left(value.find(' '));
  226. }
  227. map.set(key, value);
  228. }
  229. }
  230. } // namespace WebCore