1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "Settings.h"
28
29 #include "Frame.h"
30 #include "FrameTree.h"
31 #include "HistoryItem.h"
32 #include "Page.h"
33 #include "PageCache.h"
34 #include <limits>
35
36 namespace WebCore {
37
setNeedsReapplyStylesInAllFrames(Page * page)38 static void setNeedsReapplyStylesInAllFrames(Page* page)
39 {
40 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
41 frame->setNeedsReapplyStyles();
42 }
43
44 #if USE(SAFARI_THEME)
45 bool Settings::gShouldPaintNativeControls = false;
46 #endif
47
Settings(Page * page)48 Settings::Settings(Page* page)
49 : m_page(page)
50 #ifdef ANDROID_LAYOUT
51 , m_layoutAlgorithm(kLayoutFitColumnToScreen)
52 #endif
53 , m_editableLinkBehavior(EditableLinkDefaultBehavior)
54 , m_textDirectionSubmenuInclusionBehavior(TextDirectionSubmenuAutomaticallyIncluded)
55 , m_minimumFontSize(0)
56 , m_minimumLogicalFontSize(0)
57 , m_defaultFontSize(0)
58 , m_defaultFixedFontSize(0)
59 #ifdef ANDROID_LAYOUT
60 , m_useWideViewport(false)
61 #endif
62 #ifdef ANDROID_MULTIPLE_WINDOWS
63 , m_supportMultipleWindows(true)
64 #endif
65 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
66 , m_blockNetworkImage(false)
67 #endif
68 , m_isJavaEnabled(false)
69 , m_loadsImagesAutomatically(false)
70 , m_privateBrowsingEnabled(false)
71 , m_arePluginsEnabled(false)
72 , m_databasesEnabled(false)
73 , m_localStorageEnabled(false)
74 , m_isJavaScriptEnabled(false)
75 , m_javaScriptCanOpenWindowsAutomatically(false)
76 , m_shouldPrintBackgrounds(false)
77 , m_textAreasAreResizable(false)
78 #if ENABLE(DASHBOARD_SUPPORT)
79 , m_usesDashboardBackwardCompatibilityMode(false)
80 #endif
81 , m_needsAdobeFrameReloadingQuirk(false)
82 , m_needsKeyboardEventDisambiguationQuirks(false)
83 , m_isDOMPasteAllowed(false)
84 , m_shrinksStandaloneImagesToFit(true)
85 , m_usesPageCache(false)
86 , m_showsURLsInToolTips(false)
87 , m_forceFTPDirectoryListings(false)
88 , m_developerExtrasEnabled(false)
89 , m_authorAndUserStylesEnabled(true)
90 , m_needsSiteSpecificQuirks(false)
91 , m_fontRenderingMode(0)
92 , m_webArchiveDebugModeEnabled(false)
93 , m_inApplicationChromeMode(false)
94 , m_offlineWebApplicationCacheEnabled(false)
95 , m_rangeMutationDisabledForOldAppleMail(false)
96 , m_shouldPaintCustomScrollbars(false)
97 , m_zoomsTextOnly(false)
98 , m_enforceCSSMIMETypeInStrictMode(true)
99 , m_maximumDecodedImageSize(std::numeric_limits<size_t>::max())
100 , m_needsIChatMemoryCacheCallsQuirk(false)
101 {
102 // A Frame may not have been created yet, so we initialize the AtomicString
103 // hash before trying to use it.
104 AtomicString::init();
105 #ifdef ANDROID_META_SUPPORT
106 resetMetadataSettings();
107 #endif
108 }
109
setStandardFontFamily(const AtomicString & standardFontFamily)110 void Settings::setStandardFontFamily(const AtomicString& standardFontFamily)
111 {
112 if (standardFontFamily == m_standardFontFamily)
113 return;
114
115 m_standardFontFamily = standardFontFamily;
116 setNeedsReapplyStylesInAllFrames(m_page);
117 }
118
setFixedFontFamily(const AtomicString & fixedFontFamily)119 void Settings::setFixedFontFamily(const AtomicString& fixedFontFamily)
120 {
121 if (m_fixedFontFamily == fixedFontFamily)
122 return;
123
124 m_fixedFontFamily = fixedFontFamily;
125 setNeedsReapplyStylesInAllFrames(m_page);
126 }
127
setSerifFontFamily(const AtomicString & serifFontFamily)128 void Settings::setSerifFontFamily(const AtomicString& serifFontFamily)
129 {
130 if (m_serifFontFamily == serifFontFamily)
131 return;
132
133 m_serifFontFamily = serifFontFamily;
134 setNeedsReapplyStylesInAllFrames(m_page);
135 }
136
setSansSerifFontFamily(const AtomicString & sansSerifFontFamily)137 void Settings::setSansSerifFontFamily(const AtomicString& sansSerifFontFamily)
138 {
139 if (m_sansSerifFontFamily == sansSerifFontFamily)
140 return;
141
142 m_sansSerifFontFamily = sansSerifFontFamily;
143 setNeedsReapplyStylesInAllFrames(m_page);
144 }
145
setCursiveFontFamily(const AtomicString & cursiveFontFamily)146 void Settings::setCursiveFontFamily(const AtomicString& cursiveFontFamily)
147 {
148 if (m_cursiveFontFamily == cursiveFontFamily)
149 return;
150
151 m_cursiveFontFamily = cursiveFontFamily;
152 setNeedsReapplyStylesInAllFrames(m_page);
153 }
154
setFantasyFontFamily(const AtomicString & fantasyFontFamily)155 void Settings::setFantasyFontFamily(const AtomicString& fantasyFontFamily)
156 {
157 if (m_fantasyFontFamily == fantasyFontFamily)
158 return;
159
160 m_fantasyFontFamily = fantasyFontFamily;
161 setNeedsReapplyStylesInAllFrames(m_page);
162 }
163
setMinimumFontSize(int minimumFontSize)164 void Settings::setMinimumFontSize(int minimumFontSize)
165 {
166 if (m_minimumFontSize == minimumFontSize)
167 return;
168
169 m_minimumFontSize = minimumFontSize;
170 setNeedsReapplyStylesInAllFrames(m_page);
171 }
172
setMinimumLogicalFontSize(int minimumLogicalFontSize)173 void Settings::setMinimumLogicalFontSize(int minimumLogicalFontSize)
174 {
175 if (m_minimumLogicalFontSize == minimumLogicalFontSize)
176 return;
177
178 m_minimumLogicalFontSize = minimumLogicalFontSize;
179 setNeedsReapplyStylesInAllFrames(m_page);
180 }
181
setDefaultFontSize(int defaultFontSize)182 void Settings::setDefaultFontSize(int defaultFontSize)
183 {
184 if (m_defaultFontSize == defaultFontSize)
185 return;
186
187 m_defaultFontSize = defaultFontSize;
188 setNeedsReapplyStylesInAllFrames(m_page);
189 }
190
setDefaultFixedFontSize(int defaultFontSize)191 void Settings::setDefaultFixedFontSize(int defaultFontSize)
192 {
193 if (m_defaultFixedFontSize == defaultFontSize)
194 return;
195
196 m_defaultFixedFontSize = defaultFontSize;
197 setNeedsReapplyStylesInAllFrames(m_page);
198 }
199
200 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
setBlockNetworkImage(bool blockNetworkImage)201 void Settings::setBlockNetworkImage(bool blockNetworkImage)
202 {
203 m_blockNetworkImage = blockNetworkImage;
204 }
205 #endif
206
setLoadsImagesAutomatically(bool loadsImagesAutomatically)207 void Settings::setLoadsImagesAutomatically(bool loadsImagesAutomatically)
208 {
209 m_loadsImagesAutomatically = loadsImagesAutomatically;
210 }
211
setJavaScriptEnabled(bool isJavaScriptEnabled)212 void Settings::setJavaScriptEnabled(bool isJavaScriptEnabled)
213 {
214 m_isJavaScriptEnabled = isJavaScriptEnabled;
215 }
216
setJavaEnabled(bool isJavaEnabled)217 void Settings::setJavaEnabled(bool isJavaEnabled)
218 {
219 m_isJavaEnabled = isJavaEnabled;
220 }
221
setPluginsEnabled(bool arePluginsEnabled)222 void Settings::setPluginsEnabled(bool arePluginsEnabled)
223 {
224 m_arePluginsEnabled = arePluginsEnabled;
225 }
226
227 #ifdef ANDROID_PLUGINS
setPluginsPath(const String & pluginsPath)228 void Settings::setPluginsPath(const String& pluginsPath)
229 {
230 m_pluginsPath = pluginsPath;
231 }
232 #endif
233
setDatabasesEnabled(bool databasesEnabled)234 void Settings::setDatabasesEnabled(bool databasesEnabled)
235 {
236 m_databasesEnabled = databasesEnabled;
237 }
238
setLocalStorageEnabled(bool localStorageEnabled)239 void Settings::setLocalStorageEnabled(bool localStorageEnabled)
240 {
241 m_localStorageEnabled = localStorageEnabled;
242 }
243
setPrivateBrowsingEnabled(bool privateBrowsingEnabled)244 void Settings::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
245 {
246 m_privateBrowsingEnabled = privateBrowsingEnabled;
247 }
248
setJavaScriptCanOpenWindowsAutomatically(bool javaScriptCanOpenWindowsAutomatically)249 void Settings::setJavaScriptCanOpenWindowsAutomatically(bool javaScriptCanOpenWindowsAutomatically)
250 {
251 m_javaScriptCanOpenWindowsAutomatically = javaScriptCanOpenWindowsAutomatically;
252 }
253
setDefaultTextEncodingName(const String & defaultTextEncodingName)254 void Settings::setDefaultTextEncodingName(const String& defaultTextEncodingName)
255 {
256 m_defaultTextEncodingName = defaultTextEncodingName;
257 }
258
setUserStyleSheetLocation(const KURL & userStyleSheetLocation)259 void Settings::setUserStyleSheetLocation(const KURL& userStyleSheetLocation)
260 {
261 if (m_userStyleSheetLocation == userStyleSheetLocation)
262 return;
263
264 m_userStyleSheetLocation = userStyleSheetLocation;
265
266 m_page->userStyleSheetLocationChanged();
267 setNeedsReapplyStylesInAllFrames(m_page);
268 }
269
setShouldPrintBackgrounds(bool shouldPrintBackgrounds)270 void Settings::setShouldPrintBackgrounds(bool shouldPrintBackgrounds)
271 {
272 m_shouldPrintBackgrounds = shouldPrintBackgrounds;
273 }
274
setTextAreasAreResizable(bool textAreasAreResizable)275 void Settings::setTextAreasAreResizable(bool textAreasAreResizable)
276 {
277 if (m_textAreasAreResizable == textAreasAreResizable)
278 return;
279
280 m_textAreasAreResizable = textAreasAreResizable;
281 setNeedsReapplyStylesInAllFrames(m_page);
282 }
283
setEditableLinkBehavior(EditableLinkBehavior editableLinkBehavior)284 void Settings::setEditableLinkBehavior(EditableLinkBehavior editableLinkBehavior)
285 {
286 m_editableLinkBehavior = editableLinkBehavior;
287 }
288
setTextDirectionSubmenuInclusionBehavior(TextDirectionSubmenuInclusionBehavior behavior)289 void Settings::setTextDirectionSubmenuInclusionBehavior(TextDirectionSubmenuInclusionBehavior behavior)
290 {
291 m_textDirectionSubmenuInclusionBehavior = behavior;
292 }
293
294 #if ENABLE(DASHBOARD_SUPPORT)
setUsesDashboardBackwardCompatibilityMode(bool usesDashboardBackwardCompatibilityMode)295 void Settings::setUsesDashboardBackwardCompatibilityMode(bool usesDashboardBackwardCompatibilityMode)
296 {
297 m_usesDashboardBackwardCompatibilityMode = usesDashboardBackwardCompatibilityMode;
298 }
299 #endif
300
301 // FIXME: This quirk is needed because of Radar 4674537 and 5211271. We need to phase it out once Adobe
302 // can fix the bug from their end.
setNeedsAdobeFrameReloadingQuirk(bool shouldNotReloadIFramesForUnchangedSRC)303 void Settings::setNeedsAdobeFrameReloadingQuirk(bool shouldNotReloadIFramesForUnchangedSRC)
304 {
305 m_needsAdobeFrameReloadingQuirk = shouldNotReloadIFramesForUnchangedSRC;
306 }
307
308 // This is a quirk we are pro-actively applying to old applications. It changes keyboard event dispatching,
309 // making keyIdentifier available on keypress events, making charCode available on keydown/keyup events,
310 // and getting keypress dispatched in more cases.
setNeedsKeyboardEventDisambiguationQuirks(bool needsQuirks)311 void Settings::setNeedsKeyboardEventDisambiguationQuirks(bool needsQuirks)
312 {
313 m_needsKeyboardEventDisambiguationQuirks = needsQuirks;
314 }
315
setDOMPasteAllowed(bool DOMPasteAllowed)316 void Settings::setDOMPasteAllowed(bool DOMPasteAllowed)
317 {
318 m_isDOMPasteAllowed = DOMPasteAllowed;
319 }
320
setUsesPageCache(bool usesPageCache)321 void Settings::setUsesPageCache(bool usesPageCache)
322 {
323 if (m_usesPageCache == usesPageCache)
324 return;
325
326 m_usesPageCache = usesPageCache;
327 if (!m_usesPageCache) {
328 HistoryItemVector& historyItems = m_page->backForwardList()->entries();
329 for (unsigned i = 0; i < historyItems.size(); i++)
330 pageCache()->remove(historyItems[i].get());
331 pageCache()->releaseAutoreleasedPagesNow();
332 }
333 }
334
setShrinksStandaloneImagesToFit(bool shrinksStandaloneImagesToFit)335 void Settings::setShrinksStandaloneImagesToFit(bool shrinksStandaloneImagesToFit)
336 {
337 m_shrinksStandaloneImagesToFit = shrinksStandaloneImagesToFit;
338 }
339
setShowsURLsInToolTips(bool showsURLsInToolTips)340 void Settings::setShowsURLsInToolTips(bool showsURLsInToolTips)
341 {
342 m_showsURLsInToolTips = showsURLsInToolTips;
343 }
344
setFTPDirectoryTemplatePath(const String & path)345 void Settings::setFTPDirectoryTemplatePath(const String& path)
346 {
347 m_ftpDirectoryTemplatePath = path;
348 }
349
setForceFTPDirectoryListings(bool force)350 void Settings::setForceFTPDirectoryListings(bool force)
351 {
352 m_forceFTPDirectoryListings = force;
353 }
354
setDeveloperExtrasEnabled(bool developerExtrasEnabled)355 void Settings::setDeveloperExtrasEnabled(bool developerExtrasEnabled)
356 {
357 m_developerExtrasEnabled = developerExtrasEnabled;
358 }
359
360 #ifdef ANDROID_META_SUPPORT
resetMetadataSettings()361 void Settings::resetMetadataSettings()
362 {
363 m_viewport_width = -1;
364 m_viewport_height = -1;
365 m_viewport_initial_scale = 0;
366 m_viewport_minimum_scale = 0;
367 m_viewport_maximum_scale = 0;
368 m_viewport_user_scalable = true;
369 m_format_detection_telephone = true;
370 m_format_detection_address = true;
371 m_format_detection_email = true;
372 }
373
setMetadataSettings(const String & key,const String & value)374 void Settings::setMetadataSettings(const String& key, const String& value)
375 {
376 if (key == "width") {
377 if (value == "device-width") {
378 m_viewport_width = 0;
379 } else {
380 int width = value.toInt();
381 if (width >= 200 && width <= 10000) {
382 if (width == 320) {
383 // This is a hack to accommodate the pages designed for the
384 // original iPhone. The new version, since 10/2007, is to
385 // use device-width which works for both prtrait and
386 // landscape modes.
387 m_viewport_width = 0;
388 } else {
389 m_viewport_width = width;
390 }
391 }
392 }
393 } else if (key == "height") {
394 if (value == "device-height") {
395 m_viewport_height = 0;
396 } else {
397 int height = value.toInt();
398 if (height >= 200 && height <= 10000) {
399 m_viewport_height = height;
400 }
401 }
402 } else if (key == "initial-scale") {
403 int scale = int(value.toFloat() * 100);
404 if (scale >= 1 && scale <= 1000) {
405 m_viewport_initial_scale = scale;
406 }
407 } else if (key == "minimum-scale") {
408 int scale = int(value.toFloat() * 100);
409 if (scale >= 1 && scale <= 1000) {
410 m_viewport_minimum_scale = scale;
411 }
412 } else if (key == "maximum-scale") {
413 int scale = int(value.toFloat() * 100);
414 if (scale >= 1 && scale <= 1000) {
415 m_viewport_maximum_scale = scale;
416 }
417 } else if (key == "user-scalable") {
418 // even Apple doc says using "no", "0" is common in the real world, and
419 // some sites, e.g. gomoviesapp.com, use "false".
420 if (value == "no" || value == "0" || value == "false") {
421 m_viewport_user_scalable = false;
422 }
423 } else if (key == "telephone") {
424 if (value == "no") {
425 m_format_detection_telephone = false;
426 }
427 } else if (key == "address") {
428 if (value == "no") {
429 m_format_detection_address = false;
430 }
431 } else if (key == "email") {
432 if (value == "no") {
433 m_format_detection_email = false;
434 }
435 } else if (key == "format-detection") {
436 // even Apple doc says "format-detection" should be the name of the
437 // <meta> tag. In the real world, e.g. amazon.com, use
438 // "format-detection=no" in the "viewport" <meta> tag to disable all
439 // format detection.
440 if (value == "no") {
441 m_format_detection_telephone = false;
442 m_format_detection_address = false;
443 m_format_detection_email = false;
444 }
445 }
446 }
447 #endif
448
setAuthorAndUserStylesEnabled(bool authorAndUserStylesEnabled)449 void Settings::setAuthorAndUserStylesEnabled(bool authorAndUserStylesEnabled)
450 {
451 if (m_authorAndUserStylesEnabled == authorAndUserStylesEnabled)
452 return;
453
454 m_authorAndUserStylesEnabled = authorAndUserStylesEnabled;
455 setNeedsReapplyStylesInAllFrames(m_page);
456 }
457
setFontRenderingMode(FontRenderingMode mode)458 void Settings::setFontRenderingMode(FontRenderingMode mode)
459 {
460 if (fontRenderingMode() == mode)
461 return;
462 m_fontRenderingMode = mode;
463 setNeedsReapplyStylesInAllFrames(m_page);
464 }
465
fontRenderingMode() const466 FontRenderingMode Settings::fontRenderingMode() const
467 {
468 return static_cast<FontRenderingMode>(m_fontRenderingMode);
469 }
470
setNeedsSiteSpecificQuirks(bool needsQuirks)471 void Settings::setNeedsSiteSpecificQuirks(bool needsQuirks)
472 {
473 m_needsSiteSpecificQuirks = needsQuirks;
474 }
475
setWebArchiveDebugModeEnabled(bool enabled)476 void Settings::setWebArchiveDebugModeEnabled(bool enabled)
477 {
478 m_webArchiveDebugModeEnabled = enabled;
479 }
480
setLocalStorageDatabasePath(const String & path)481 void Settings::setLocalStorageDatabasePath(const String& path)
482 {
483 m_localStorageDatabasePath = path;
484 }
485
disableRangeMutationForOldAppleMail(bool disable)486 void Settings::disableRangeMutationForOldAppleMail(bool disable)
487 {
488 m_rangeMutationDisabledForOldAppleMail = disable;
489 }
490
setApplicationChromeMode(bool mode)491 void Settings::setApplicationChromeMode(bool mode)
492 {
493 m_inApplicationChromeMode = mode;
494 }
495
setOfflineWebApplicationCacheEnabled(bool enabled)496 void Settings::setOfflineWebApplicationCacheEnabled(bool enabled)
497 {
498 m_offlineWebApplicationCacheEnabled = enabled;
499 }
500
setShouldPaintCustomScrollbars(bool shouldPaintCustomScrollbars)501 void Settings::setShouldPaintCustomScrollbars(bool shouldPaintCustomScrollbars)
502 {
503 m_shouldPaintCustomScrollbars = shouldPaintCustomScrollbars;
504 }
505
setZoomsTextOnly(bool zoomsTextOnly)506 void Settings::setZoomsTextOnly(bool zoomsTextOnly)
507 {
508 if (zoomsTextOnly == m_zoomsTextOnly)
509 return;
510
511 m_zoomsTextOnly = zoomsTextOnly;
512 setNeedsReapplyStylesInAllFrames(m_page);
513 }
514
setEnforceCSSMIMETypeInStrictMode(bool enforceCSSMIMETypeInStrictMode)515 void Settings::setEnforceCSSMIMETypeInStrictMode(bool enforceCSSMIMETypeInStrictMode)
516 {
517 m_enforceCSSMIMETypeInStrictMode = enforceCSSMIMETypeInStrictMode;
518 }
519
520 #if USE(SAFARI_THEME)
setShouldPaintNativeControls(bool shouldPaintNativeControls)521 void Settings::setShouldPaintNativeControls(bool shouldPaintNativeControls)
522 {
523 gShouldPaintNativeControls = shouldPaintNativeControls;
524 }
525 #endif
526
setNeedsIChatMemoryCacheCallsQuirk(bool needsIChatMemoryCacheCallsQuirk)527 void Settings::setNeedsIChatMemoryCacheCallsQuirk(bool needsIChatMemoryCacheCallsQuirk)
528 {
529 m_needsIChatMemoryCacheCallsQuirk = needsIChatMemoryCacheCallsQuirk;
530 }
531
532 } // namespace WebCore
533