Merge lp:~timo-jyrinki/ubuntu/raring/qtwebkit-source/raring_231 into lp:ubuntu/saucy/qtwebkit-source

Proposed by Timo Jyrinki
Status: Merged
Merge reported by: Sebastien Bacher
Merged at revision: not available
Proposed branch: lp:~timo-jyrinki/ubuntu/raring/qtwebkit-source/raring_231
Merge into: lp:ubuntu/saucy/qtwebkit-source
Diff against target: 16806 lines (+1220/-14071)
85 files modified
.pc/05_sparc_unaligned_access.diff/Source/WTF/wtf/ListHashSet.h (+0/-872)
.pc/applied-patches (+0/-9)
.pc/devicePixelResolution.patch/Source/WebCore/page/Page.cpp (+0/-1346)
.pc/disable_geolocation_501.diff/Source/WebKit/qt/Api/qwebpage.cpp (+0/-4103)
.pc/hurd.diff/Source/WTF/wtf/FastMalloc.cpp (+0/-4734)
.pc/kubuntu_fix_for_powerpc.diff/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp (+0/-545)
.pc/kubuntu_fix_for_powerpc.diff/Source/JavaScriptCore/offlineasm/cloop.rb (+0/-1131)
.pc/no_gc_sections.diff/Source/WebCore/WebCore.pri (+0/-361)
.pc/save_memory.diff/Source/WebCore/WebCore.pri (+0/-361)
.pc/stabs_format_debug_info.diff/Source/WebKit/WebKit1.pri (+0/-60)
.pc/stabs_format_debug_info.diff/Source/WebKit2/WebKit2.pri (+0/-81)
.pc/webkit_qt_hide_symbols.diff/Source/QtWebKit.pro (+0/-38)
ChangeLog (+16/-0)
Source/JavaScriptCore/ChangeLog (+403/-0)
Source/JavaScriptCore/JSCTypedArrayStubs.h (+4/-1)
Source/JavaScriptCore/assembler/ARMv7Assembler.h (+42/-3)
Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h (+6/-1)
Source/JavaScriptCore/bytecode/CodeBlock.cpp (+2/-2)
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (+30/-2)
Source/JavaScriptCore/bytecompiler/Label.h (+6/-0)
Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp (+9/-8)
Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp (+8/-3)
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (+11/-3)
Source/JavaScriptCore/dfg/DFGGraph.h (+19/-8)
Source/JavaScriptCore/dfg/DFGNodeFlags.h (+1/-1)
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (+29/-4)
Source/JavaScriptCore/dfg/DFGRepatch.cpp (+6/-6)
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (+3/-4)
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (+1/-1)
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp (+1/-1)
Source/JavaScriptCore/heap/MarkStack.cpp (+4/-8)
Source/JavaScriptCore/heap/MarkStack.h (+5/-11)
Source/JavaScriptCore/heap/MarkStackInlines.h (+5/-5)
Source/JavaScriptCore/heap/WeakSet.cpp (+1/-1)
Source/JavaScriptCore/interpreter/Interpreter.cpp (+6/-3)
Source/JavaScriptCore/jit/JIT.h (+1/-1)
Source/JavaScriptCore/jit/JITStubs.cpp (+18/-2)
Source/JavaScriptCore/llint/LLIntExceptions.cpp (+3/-3)
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (+3/-4)
Source/JavaScriptCore/offlineasm/ast.rb (+1/-1)
Source/JavaScriptCore/runtime/Executable.cpp (+2/-2)
Source/JavaScriptCore/runtime/JSArray.h (+4/-0)
Source/JavaScriptCore/runtime/JSTypeInfo.h (+2/-1)
Source/JavaScriptCore/runtime/Operations.h (+6/-3)
Source/JavaScriptCore/runtime/Options.h (+0/-1)
Source/JavaScriptCore/yarr/YarrJIT.cpp (+12/-0)
Source/QtWebKit.pro (+1/-6)
Source/WTF/ChangeLog (+75/-0)
Source/WTF/wtf/Compiler.h (+3/-0)
Source/WTF/wtf/FastMalloc.cpp (+0/-4)
Source/WTF/wtf/HashMap.h (+30/-24)
Source/WTF/wtf/ListHashSet.h (+6/-3)
Source/WTF/wtf/Platform.h (+2/-2)
Source/WebCore/ChangeLog (+193/-11)
Source/WebCore/Target.pri (+10/-7)
Source/WebCore/WebCore.pri (+1/-3)
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (+10/-3)
Source/WebCore/css/mediaControlsQt.css (+98/-197)
Source/WebCore/page/EventHandler.cpp (+1/-1)
Source/WebCore/page/Page.cpp (+2/-2)
Source/WebCore/platform/graphics/GraphicsContext.cpp (+1/-1)
Source/WebCore/platform/graphics/ShadowBlur.cpp (+2/-2)
Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp (+6/-3)
Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp (+31/-0)
Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp (+2/-0)
Source/WebCore/platform/text/TextEncodingRegistry.cpp (+9/-0)
Source/WebCore/rendering/RenderBox.cpp (+1/-0)
Source/WebCore/rendering/RenderFrameSet.cpp (+4/-4)
Source/WebCore/rendering/RenderLayer.cpp (+1/-2)
Source/WebCore/rendering/RenderLayer.h (+0/-4)
Source/WebCore/rendering/RenderTableSection.cpp (+6/-1)
Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp (+1/-1)
Source/WebKit/WebKit1.pri (+0/-6)
Source/WebKit/qt/Api/qwebkitglobal.h (+2/-2)
Source/WebKit/qt/Api/qwebpage.cpp (+10/-1)
Source/WebKit/qt/Api/qwebpage.h (+1/-0)
Source/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp (+2/-1)
Source/WebKit2/WebKit2.pri (+0/-6)
Source/api.pri (+13/-0)
Tools/Scripts/webkitdirs.pm (+3/-0)
Tools/qmake/qt_webkit.pri (+2/-2)
debian/changelog (+18/-0)
debian/patches/kubuntu_fix_for_powerpc.diff (+0/-35)
debian/patches/series (+0/-1)
debian/rules (+3/-1)
To merge this branch: bzr merge lp:~timo-jyrinki/ubuntu/raring/qtwebkit-source/raring_231
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+165031@code.launchpad.net

This proposal supersedes a proposal from 2013-04-22.

Commit message

This new 2.3.1 release with the correct build parameter (http://blogs.kde.org/2013/03/15/qtwebkit-230-out) fixes qtwebkit on non-SSE2 computers (mentioned in bug #1131636), and has other fixes http://comments.gmane.org/gmane.os.opendarwin.webkit.qt/3665

It does not however fix the Skype issue NVIDIA users have (bug #1155327).

Description of the change

This new 2.3.1 release with the correct build parameter (http://blogs.kde.org/2013/03/15/qtwebkit-230-out) fixes qtwebkit on non-SSE2 computers (mentioned in bug #1131636), and has other fixes http://comments.gmane.org/gmane.os.opendarwin.webkit.qt/3665

It does not however fix the Skype issue NVIDIA users have (bug #1155327).

To post a comment you must log in.
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal
Revision history for this message
Dmitry Shachnev (mitya57) wrote : Posted in a previous version of this proposal

Thanks Timo for working on it, I have a couple of comments:

- I've unlinked bugs that are not fixed by your update;
- Now this should go to Saucy, the diff looks to big for a SRU.
- We may want to cherry-pick some fixes to Raring, but I would like to wait for fix for https://bugs.webkit.org/show_bug.cgi?id=114618 (marked as a blocker currently). We'll also need a SRU bug in that case.

Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal

Yeah certainly this is for saucy at this point.

Revision history for this message
Sebastien Bacher (seb128) wrote : Posted in a previous version of this proposal

Timo, could you retarget that one for saucy?

Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

Resubmitted to saucy, thanks.

Revision history for this message
Dmitry Shachnev (mitya57) wrote :

Note that it is not rebased on top of 2.3.0-0ubuntu3 in Saucy, so one will need to at least merge changelog entries before uploading.

Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

Right, it does not show up in any bzr, so merging manually the changelog entry and checking if the patch still applies.

35. By Timo Jyrinki

Manual merge of 2.3.0-0ubuntu3 in saucy. Changelog only, patch is included in 2.3.1.

* debian/patches/108991-jsval-32bit-fix.patch:
  - Drop, merged upstream
* Add patch 108991-jsval-32bit-fix.patch fixes
  QtWebKit JS crash on 32-bit systems LP: #1180731

Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, I'm sponsoring that one

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== renamed file '.dir-locals.el' => '.dir-locals.el'
=== renamed directory '.pc' => '.pc'
=== removed directory '.pc/05_sparc_unaligned_access.diff'
=== removed directory '.pc/05_sparc_unaligned_access.diff/Source'
=== removed directory '.pc/05_sparc_unaligned_access.diff/Source/WTF'
=== removed directory '.pc/05_sparc_unaligned_access.diff/Source/WTF/wtf'
=== removed file '.pc/05_sparc_unaligned_access.diff/Source/WTF/wtf/ListHashSet.h'
--- .pc/05_sparc_unaligned_access.diff/Source/WTF/wtf/ListHashSet.h 2013-02-18 14:24:18 +0000
+++ .pc/05_sparc_unaligned_access.diff/Source/WTF/wtf/ListHashSet.h 1970-01-01 00:00:00 +0000
@@ -1,872 +0,0 @@
1/*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#ifndef WTF_ListHashSet_h
23#define WTF_ListHashSet_h
24
25#include <wtf/HashSet.h>
26#include <wtf/OwnPtr.h>
27#include <wtf/PassOwnPtr.h>
28
29namespace WTF {
30
31 // ListHashSet: Just like HashSet, this class provides a Set
32 // interface - a collection of unique objects with O(1) insertion,
33 // removal and test for containership. However, it also has an
34 // order - iterating it will always give back values in the order
35 // in which they are added.
36
37 // Unlike iteration of most WTF Hash data structures, iteration is
38 // guaranteed safe against mutation of the ListHashSet, except for
39 // removal of the item currently pointed to by a given iterator.
40
41 // In theory it would be possible to add prepend, insertAfter
42 // and an append that moves the element to the end even if already present,
43 // but unclear yet if these are needed.
44
45 template<typename Value, size_t inlineCapacity, typename HashFunctions> class ListHashSet;
46
47 template<typename Value, size_t inlineCapacity, typename HashFunctions>
48 void deleteAllValues(const ListHashSet<Value, inlineCapacity, HashFunctions>&);
49
50 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator;
51 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator;
52 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator;
53 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator;
54
55 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode;
56 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator;
57
58 template<typename HashArg> struct ListHashSetNodeHashFunctions;
59 template<typename HashArg> struct ListHashSetTranslator;
60
61 template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet {
62 WTF_MAKE_FAST_ALLOCATED;
63 private:
64 typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
65 typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
66
67 typedef HashTraits<Node*> NodeTraits;
68 typedef ListHashSetNodeHashFunctions<HashArg> NodeHash;
69 typedef ListHashSetTranslator<HashArg> BaseTranslator;
70
71 typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplType;
72 typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator;
73 typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator;
74
75 typedef HashArg HashFunctions;
76
77 public:
78 typedef ValueArg ValueType;
79
80 typedef ListHashSetIterator<ValueType, inlineCapacity, HashArg> iterator;
81 typedef ListHashSetConstIterator<ValueType, inlineCapacity, HashArg> const_iterator;
82 friend class ListHashSetConstIterator<ValueType, inlineCapacity, HashArg>;
83
84 typedef ListHashSetReverseIterator<ValueType, inlineCapacity, HashArg> reverse_iterator;
85 typedef ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg> const_reverse_iterator;
86 friend class ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg>;
87
88 typedef HashTableAddResult<iterator> AddResult;
89
90 ListHashSet();
91 ListHashSet(const ListHashSet&);
92 ListHashSet& operator=(const ListHashSet&);
93 ~ListHashSet();
94
95 void swap(ListHashSet&);
96
97 int size() const;
98 int capacity() const;
99 bool isEmpty() const;
100
101 size_t sizeInBytes() const;
102
103 iterator begin();
104 iterator end();
105 const_iterator begin() const;
106 const_iterator end() const;
107
108 reverse_iterator rbegin();
109 reverse_iterator rend();
110 const_reverse_iterator rbegin() const;
111 const_reverse_iterator rend() const;
112
113 ValueType& first();
114 const ValueType& first() const;
115
116 ValueType& last();
117 const ValueType& last() const;
118 void removeLast();
119
120 iterator find(const ValueType&);
121 const_iterator find(const ValueType&) const;
122 bool contains(const ValueType&) const;
123
124 // An alternate version of find() that finds the object by hashing and comparing
125 // with some other type, to avoid the cost of type conversion.
126 // The HashTranslator interface is defined in HashSet.
127 // FIXME: We should reverse the order of the template arguments so that callers
128 // can just pass the translator let the compiler deduce T.
129 template<typename T, typename HashTranslator> iterator find(const T&);
130 template<typename T, typename HashTranslator> const_iterator find(const T&) const;
131 template<typename T, typename HashTranslator> bool contains(const T&) const;
132
133 // The return value of add is a pair of an iterator to the new value's location,
134 // and a bool that is true if an new entry was added.
135 AddResult add(const ValueType&);
136
137 AddResult insertBefore(const ValueType& beforeValue, const ValueType& newValue);
138 AddResult insertBefore(iterator, const ValueType&);
139
140 void remove(const ValueType&);
141 void remove(iterator);
142 void clear();
143
144 private:
145 void unlinkAndDelete(Node*);
146 void appendNode(Node*);
147 void insertNodeBefore(Node* beforeNode, Node* newNode);
148 void deleteAllNodes();
149
150 iterator makeIterator(Node*);
151 const_iterator makeConstIterator(Node*) const;
152 reverse_iterator makeReverseIterator(Node*);
153 const_reverse_iterator makeConstReverseIterator(Node*) const;
154
155 friend void deleteAllValues<>(const ListHashSet&);
156
157 ImplType m_impl;
158 Node* m_head;
159 Node* m_tail;
160 OwnPtr<NodeAllocator> m_allocator;
161 };
162
163 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator {
164 typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
165 typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
166
167 ListHashSetNodeAllocator()
168 : m_freeList(pool())
169 , m_isDoneWithInitialFreeList(false)
170 {
171 memset(m_pool.pool, 0, sizeof(m_pool.pool));
172 }
173
174 Node* allocate()
175 {
176 Node* result = m_freeList;
177
178 if (!result)
179 return static_cast<Node*>(fastMalloc(sizeof(Node)));
180
181 ASSERT(!result->m_isAllocated);
182
183 Node* next = result->m_next;
184 ASSERT(!next || !next->m_isAllocated);
185 if (!next && !m_isDoneWithInitialFreeList) {
186 next = result + 1;
187 if (next == pastPool()) {
188 m_isDoneWithInitialFreeList = true;
189 next = 0;
190 } else {
191 ASSERT(inPool(next));
192 ASSERT(!next->m_isAllocated);
193 }
194 }
195 m_freeList = next;
196
197 return result;
198 }
199
200 void deallocate(Node* node)
201 {
202 if (inPool(node)) {
203#ifndef NDEBUG
204 node->m_isAllocated = false;
205#endif
206 node->m_next = m_freeList;
207 m_freeList = node;
208 return;
209 }
210
211 fastFree(node);
212 }
213
214 bool inPool(Node* node)
215 {
216 return node >= pool() && node < pastPool();
217 }
218
219 private:
220 Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); }
221 Node* pastPool() { return pool() + m_poolSize; }
222
223 Node* m_freeList;
224 bool m_isDoneWithInitialFreeList;
225 static const size_t m_poolSize = inlineCapacity;
226 union {
227 char pool[sizeof(Node) * m_poolSize];
228 double forAlignment;
229 } m_pool;
230 };
231
232 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode {
233 typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
234
235 ListHashSetNode(ValueArg value)
236 : m_value(value)
237 , m_prev(0)
238 , m_next(0)
239#ifndef NDEBUG
240 , m_isAllocated(true)
241#endif
242 {
243 }
244
245 void* operator new(size_t, NodeAllocator* allocator)
246 {
247 return allocator->allocate();
248 }
249 void destroy(NodeAllocator* allocator)
250 {
251 this->~ListHashSetNode();
252 allocator->deallocate(this);
253 }
254
255 ValueArg m_value;
256 ListHashSetNode* m_prev;
257 ListHashSetNode* m_next;
258
259#ifndef NDEBUG
260 bool m_isAllocated;
261#endif
262 };
263
264 template<typename HashArg> struct ListHashSetNodeHashFunctions {
265 template<typename T> static unsigned hash(const T& key) { return HashArg::hash(key->m_value); }
266 template<typename T> static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); }
267 static const bool safeToCompareToEmptyOrDeleted = false;
268 };
269
270 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator {
271 private:
272 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType;
273 typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator;
274 typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator;
275 typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
276 typedef ValueArg ValueType;
277 typedef ValueType& ReferenceType;
278 typedef ValueType* PointerType;
279
280 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>;
281
282 ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { }
283
284 public:
285 ListHashSetIterator() { }
286
287 // default copy, assignment and destructor are OK
288
289 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
290 ReferenceType operator*() const { return *get(); }
291 PointerType operator->() const { return get(); }
292
293 iterator& operator++() { ++m_iterator; return *this; }
294
295 // postfix ++ intentionally omitted
296
297 iterator& operator--() { --m_iterator; return *this; }
298
299 // postfix -- intentionally omitted
300
301 // Comparison.
302 bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
303 bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
304
305 operator const_iterator() const { return m_iterator; }
306
307 private:
308 Node* node() { return m_iterator.node(); }
309
310 const_iterator m_iterator;
311 };
312
313 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator {
314 private:
315 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType;
316 typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator;
317 typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator;
318 typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
319 typedef ValueArg ValueType;
320 typedef const ValueType& ReferenceType;
321 typedef const ValueType* PointerType;
322
323 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>;
324 friend class ListHashSetIterator<ValueArg, inlineCapacity, HashArg>;
325
326 ListHashSetConstIterator(const ListHashSetType* set, Node* position)
327 : m_set(set)
328 , m_position(position)
329 {
330 }
331
332 public:
333 ListHashSetConstIterator()
334 {
335 }
336
337 PointerType get() const
338 {
339 return &m_position->m_value;
340 }
341 ReferenceType operator*() const { return *get(); }
342 PointerType operator->() const { return get(); }
343
344 const_iterator& operator++()
345 {
346 ASSERT(m_position != 0);
347 m_position = m_position->m_next;
348 return *this;
349 }
350
351 // postfix ++ intentionally omitted
352
353 const_iterator& operator--()
354 {
355 ASSERT(m_position != m_set->m_head);
356 if (!m_position)
357 m_position = m_set->m_tail;
358 else
359 m_position = m_position->m_prev;
360 return *this;
361 }
362
363 // postfix -- intentionally omitted
364
365 // Comparison.
366 bool operator==(const const_iterator& other) const
367 {
368 return m_position == other.m_position;
369 }
370 bool operator!=(const const_iterator& other) const
371 {
372 return m_position != other.m_position;
373 }
374
375 private:
376 Node* node() { return m_position; }
377
378 const ListHashSetType* m_set;
379 Node* m_position;
380 };
381
382 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator {
383 private:
384 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType;
385 typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator;
386 typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator;
387 typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
388 typedef ValueArg ValueType;
389 typedef ValueType& ReferenceType;
390 typedef ValueType* PointerType;
391
392 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>;
393
394 ListHashSetReverseIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { }
395
396 public:
397 ListHashSetReverseIterator() { }
398
399 // default copy, assignment and destructor are OK
400
401 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
402 ReferenceType operator*() const { return *get(); }
403 PointerType operator->() const { return get(); }
404
405 reverse_iterator& operator++() { ++m_iterator; return *this; }
406
407 // postfix ++ intentionally omitted
408
409 reverse_iterator& operator--() { --m_iterator; return *this; }
410
411 // postfix -- intentionally omitted
412
413 // Comparison.
414 bool operator==(const reverse_iterator& other) const { return m_iterator == other.m_iterator; }
415 bool operator!=(const reverse_iterator& other) const { return m_iterator != other.m_iterator; }
416
417 operator const_reverse_iterator() const { return m_iterator; }
418
419 private:
420 Node* node() { return m_iterator.node(); }
421
422 const_reverse_iterator m_iterator;
423 };
424
425 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator {
426 private:
427 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType;
428 typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator;
429 typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator;
430 typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
431 typedef ValueArg ValueType;
432 typedef const ValueType& ReferenceType;
433 typedef const ValueType* PointerType;
434
435 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>;
436 friend class ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg>;
437
438 ListHashSetConstReverseIterator(const ListHashSetType* set, Node* position)
439 : m_set(set)
440 , m_position(position)
441 {
442 }
443
444 public:
445 ListHashSetConstReverseIterator()
446 {
447 }
448
449 PointerType get() const
450 {
451 return &m_position->m_value;
452 }
453 ReferenceType operator*() const { return *get(); }
454 PointerType operator->() const { return get(); }
455
456 const_reverse_iterator& operator++()
457 {
458 ASSERT(m_position != 0);
459 m_position = m_position->m_prev;
460 return *this;
461 }
462
463 // postfix ++ intentionally omitted
464
465 const_reverse_iterator& operator--()
466 {
467 ASSERT(m_position != m_set->m_tail);
468 if (!m_position)
469 m_position = m_set->m_head;
470 else
471 m_position = m_position->m_next;
472 return *this;
473 }
474
475 // postfix -- intentionally omitted
476
477 // Comparison.
478 bool operator==(const const_reverse_iterator& other) const
479 {
480 return m_position == other.m_position;
481 }
482 bool operator!=(const const_reverse_iterator& other) const
483 {
484 return m_position != other.m_position;
485 }
486
487 private:
488 Node* node() { return m_position; }
489
490 const ListHashSetType* m_set;
491 Node* m_position;
492 };
493
494 template<typename HashFunctions>
495 struct ListHashSetTranslator {
496 template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
497 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); }
498 template<typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator)
499 {
500 location = new (allocator) T(key);
501 }
502 };
503
504 template<typename T, size_t inlineCapacity, typename U>
505 inline ListHashSet<T, inlineCapacity, U>::ListHashSet()
506 : m_head(0)
507 , m_tail(0)
508 , m_allocator(adoptPtr(new NodeAllocator))
509 {
510 }
511
512 template<typename T, size_t inlineCapacity, typename U>
513 inline ListHashSet<T, inlineCapacity, U>::ListHashSet(const ListHashSet& other)
514 : m_head(0)
515 , m_tail(0)
516 , m_allocator(adoptPtr(new NodeAllocator))
517 {
518 const_iterator end = other.end();
519 for (const_iterator it = other.begin(); it != end; ++it)
520 add(*it);
521 }
522
523 template<typename T, size_t inlineCapacity, typename U>
524 inline ListHashSet<T, inlineCapacity, U>& ListHashSet<T, inlineCapacity, U>::operator=(const ListHashSet& other)
525 {
526 ListHashSet tmp(other);
527 swap(tmp);
528 return *this;
529 }
530
531 template<typename T, size_t inlineCapacity, typename U>
532 inline void ListHashSet<T, inlineCapacity, U>::swap(ListHashSet& other)
533 {
534 m_impl.swap(other.m_impl);
535 std::swap(m_head, other.m_head);
536 std::swap(m_tail, other.m_tail);
537 m_allocator.swap(other.m_allocator);
538 }
539
540 template<typename T, size_t inlineCapacity, typename U>
541 inline ListHashSet<T, inlineCapacity, U>::~ListHashSet()
542 {
543 deleteAllNodes();
544 }
545
546 template<typename T, size_t inlineCapacity, typename U>
547 inline int ListHashSet<T, inlineCapacity, U>::size() const
548 {
549 return m_impl.size();
550 }
551
552 template<typename T, size_t inlineCapacity, typename U>
553 inline int ListHashSet<T, inlineCapacity, U>::capacity() const
554 {
555 return m_impl.capacity();
556 }
557
558 template<typename T, size_t inlineCapacity, typename U>
559 inline bool ListHashSet<T, inlineCapacity, U>::isEmpty() const
560 {
561 return m_impl.isEmpty();
562 }
563
564 template<typename T, size_t inlineCapacity, typename U>
565 size_t ListHashSet<T, inlineCapacity, U>::sizeInBytes() const
566 {
567 size_t result = sizeof(*this) + sizeof(*m_allocator);
568 result += sizeof(typename ImplType::ValueType) * m_impl.capacity();
569 for (Node* node = m_head; node; node = node->m_next) {
570 if (!m_allocator->inPool(node))
571 result += sizeof(Node);
572 }
573 return result;
574 }
575
576 template<typename T, size_t inlineCapacity, typename U>
577 inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::begin()
578 {
579 return makeIterator(m_head);
580 }
581
582 template<typename T, size_t inlineCapacity, typename U>
583 inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::end()
584 {
585 return makeIterator(0);
586 }
587
588 template<typename T, size_t inlineCapacity, typename U>
589 inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::begin() const
590 {
591 return makeConstIterator(m_head);
592 }
593
594 template<typename T, size_t inlineCapacity, typename U>
595 inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::end() const
596 {
597 return makeConstIterator(0);
598 }
599
600 template<typename T, size_t inlineCapacity, typename U>
601 inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin()
602 {
603 return makeReverseIterator(m_tail);
604 }
605
606 template<typename T, size_t inlineCapacity, typename U>
607 inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rend()
608 {
609 return makeReverseIterator(0);
610 }
611
612 template<typename T, size_t inlineCapacity, typename U>
613 inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() const
614 {
615 return makeConstReverseIterator(m_tail);
616 }
617
618 template<typename T, size_t inlineCapacity, typename U>
619 inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() const
620 {
621 return makeConstReverseIterator(0);
622 }
623
624 template<typename T, size_t inlineCapacity, typename U>
625 inline T& ListHashSet<T, inlineCapacity, U>::first()
626 {
627 ASSERT(!isEmpty());
628 return m_head->m_value;
629 }
630
631 template<typename T, size_t inlineCapacity, typename U>
632 inline const T& ListHashSet<T, inlineCapacity, U>::first() const
633 {
634 ASSERT(!isEmpty());
635 return m_head->m_value;
636 }
637
638 template<typename T, size_t inlineCapacity, typename U>
639 inline T& ListHashSet<T, inlineCapacity, U>::last()
640 {
641 ASSERT(!isEmpty());
642 return m_tail->m_value;
643 }
644
645 template<typename T, size_t inlineCapacity, typename U>
646 inline const T& ListHashSet<T, inlineCapacity, U>::last() const
647 {
648 ASSERT(!isEmpty());
649 return m_tail->m_value;
650 }
651
652 template<typename T, size_t inlineCapacity, typename U>
653 inline void ListHashSet<T, inlineCapacity, U>::removeLast()
654 {
655 ASSERT(!isEmpty());
656 m_impl.remove(m_tail);
657 unlinkAndDelete(m_tail);
658 }
659
660 template<typename T, size_t inlineCapacity, typename U>
661 inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value)
662 {
663 ImplTypeIterator it = m_impl.template find<BaseTranslator>(value);
664 if (it == m_impl.end())
665 return end();
666 return makeIterator(*it);
667 }
668
669 template<typename T, size_t inlineCapacity, typename U>
670 inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) const
671 {
672 ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value);
673 if (it == m_impl.end())
674 return end();
675 return makeConstIterator(*it);
676 }
677
678 template<typename Translator>
679 struct ListHashSetTranslatorAdapter {
680 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
681 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); }
682 };
683
684 template<typename ValueType, size_t inlineCapacity, typename U>
685 template<typename T, typename HashTranslator>
686 inline typename ListHashSet<ValueType, inlineCapacity, U>::iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value)
687 {
688 ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value);
689 if (it == m_impl.end())
690 return end();
691 return makeIterator(*it);
692 }
693
694 template<typename ValueType, size_t inlineCapacity, typename U>
695 template<typename T, typename HashTranslator>
696 inline typename ListHashSet<ValueType, inlineCapacity, U>::const_iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) const
697 {
698 ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value);
699 if (it == m_impl.end())
700 return end();
701 return makeConstIterator(*it);
702 }
703
704 template<typename ValueType, size_t inlineCapacity, typename U>
705 template<typename T, typename HashTranslator>
706 inline bool ListHashSet<ValueType, inlineCapacity, U>::contains(const T& value) const
707 {
708 return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator> >(value);
709 }
710
711 template<typename T, size_t inlineCapacity, typename U>
712 inline bool ListHashSet<T, inlineCapacity, U>::contains(const ValueType& value) const
713 {
714 return m_impl.template contains<BaseTranslator>(value);
715 }
716
717 template<typename T, size_t inlineCapacity, typename U>
718 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::add(const ValueType &value)
719 {
720 typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get());
721 if (result.isNewEntry)
722 appendNode(*result.iterator);
723 return AddResult(makeIterator(*result.iterator), result.isNewEntry);
724 }
725
726 template<typename T, size_t inlineCapacity, typename U>
727 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(iterator it, const ValueType& newValue)
728 {
729 typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(newValue, m_allocator.get());
730 if (result.isNewEntry)
731 insertNodeBefore(it.node(), *result.iterator);
732 return AddResult(makeIterator(*result.iterator), result.isNewEntry);
733 }
734
735 template<typename T, size_t inlineCapacity, typename U>
736 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue)
737 {
738 return insertBefore(find(beforeValue), newValue);
739 }
740
741 template<typename T, size_t inlineCapacity, typename U>
742 inline void ListHashSet<T, inlineCapacity, U>::remove(iterator it)
743 {
744 if (it == end())
745 return;
746 m_impl.remove(it.node());
747 unlinkAndDelete(it.node());
748 }
749
750 template<typename T, size_t inlineCapacity, typename U>
751 inline void ListHashSet<T, inlineCapacity, U>::remove(const ValueType& value)
752 {
753 remove(find(value));
754 }
755
756 template<typename T, size_t inlineCapacity, typename U>
757 inline void ListHashSet<T, inlineCapacity, U>::clear()
758 {
759 deleteAllNodes();
760 m_impl.clear();
761 m_head = 0;
762 m_tail = 0;
763 }
764
765 template<typename T, size_t inlineCapacity, typename U>
766 void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node)
767 {
768 if (!node->m_prev) {
769 ASSERT(node == m_head);
770 m_head = node->m_next;
771 } else {
772 ASSERT(node != m_head);
773 node->m_prev->m_next = node->m_next;
774 }
775
776 if (!node->m_next) {
777 ASSERT(node == m_tail);
778 m_tail = node->m_prev;
779 } else {
780 ASSERT(node != m_tail);
781 node->m_next->m_prev = node->m_prev;
782 }
783
784 node->destroy(m_allocator.get());
785 }
786
787 template<typename T, size_t inlineCapacity, typename U>
788 void ListHashSet<T, inlineCapacity, U>::appendNode(Node* node)
789 {
790 node->m_prev = m_tail;
791 node->m_next = 0;
792
793 if (m_tail) {
794 ASSERT(m_head);
795 m_tail->m_next = node;
796 } else {
797 ASSERT(!m_head);
798 m_head = node;
799 }
800
801 m_tail = node;
802 }
803
804 template<typename T, size_t inlineCapacity, typename U>
805 void ListHashSet<T, inlineCapacity, U>::insertNodeBefore(Node* beforeNode, Node* newNode)
806 {
807 if (!beforeNode)
808 return appendNode(newNode);
809
810 newNode->m_next = beforeNode;
811 newNode->m_prev = beforeNode->m_prev;
812 if (beforeNode->m_prev)
813 beforeNode->m_prev->m_next = newNode;
814 beforeNode->m_prev = newNode;
815
816 if (!newNode->m_prev)
817 m_head = newNode;
818 }
819
820 template<typename T, size_t inlineCapacity, typename U>
821 void ListHashSet<T, inlineCapacity, U>::deleteAllNodes()
822 {
823 if (!m_head)
824 return;
825
826 for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0)
827 node->destroy(m_allocator.get());
828 }
829
830 template<typename T, size_t inlineCapacity, typename U>
831 inline ListHashSetReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeReverseIterator(Node* position)
832 {
833 return ListHashSetReverseIterator<T, inlineCapacity, U>(this, position);
834 }
835
836 template<typename T, size_t inlineCapacity, typename U>
837 inline ListHashSetConstReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstReverseIterator(Node* position) const
838 {
839 return ListHashSetConstReverseIterator<T, inlineCapacity, U>(this, position);
840 }
841
842 template<typename T, size_t inlineCapacity, typename U>
843 inline ListHashSetIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeIterator(Node* position)
844 {
845 return ListHashSetIterator<T, inlineCapacity, U>(this, position);
846 }
847
848 template<typename T, size_t inlineCapacity, typename U>
849 inline ListHashSetConstIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstIterator(Node* position) const
850 {
851 return ListHashSetConstIterator<T, inlineCapacity, U>(this, position);
852 }
853 template<bool, typename ValueType, typename HashTableType>
854 void deleteAllValues(HashTableType& collection)
855 {
856 typedef typename HashTableType::const_iterator iterator;
857 iterator end = collection.end();
858 for (iterator it = collection.begin(); it != end; ++it)
859 delete (*it)->m_value;
860 }
861
862 template<typename T, size_t inlineCapacity, typename U>
863 inline void deleteAllValues(const ListHashSet<T, inlineCapacity, U>& collection)
864 {
865 deleteAllValues<true, typename ListHashSet<T, inlineCapacity, U>::ValueType>(collection.m_impl);
866 }
867
868} // namespace WTF
869
870using WTF::ListHashSet;
871
872#endif /* WTF_ListHashSet_h */
8730
=== removed file '.pc/applied-patches'
--- .pc/applied-patches 2013-03-28 15:37:15 +0000
+++ .pc/applied-patches 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
105_sparc_unaligned_access.diff
2stabs_format_debug_info.diff
3no_gc_sections.diff
4hurd.diff
5webkit_qt_hide_symbols.diff
6save_memory.diff
7devicePixelResolution.patch
8disable_geolocation_501.diff
9kubuntu_fix_for_powerpc.diff
100
=== removed directory '.pc/devicePixelResolution.patch'
=== removed directory '.pc/devicePixelResolution.patch/Source'
=== removed directory '.pc/devicePixelResolution.patch/Source/WebCore'
=== removed directory '.pc/devicePixelResolution.patch/Source/WebCore/page'
=== removed file '.pc/devicePixelResolution.patch/Source/WebCore/page/Page.cpp'
--- .pc/devicePixelResolution.patch/Source/WebCore/page/Page.cpp 2013-02-18 14:24:18 +0000
+++ .pc/devicePixelResolution.patch/Source/WebCore/page/Page.cpp 1970-01-01 00:00:00 +0000
@@ -1,1346 +0,0 @@
1/*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "Page.h"
22
23#include "AlternativeTextClient.h"
24#include "BackForwardController.h"
25#include "BackForwardList.h"
26#include "Chrome.h"
27#include "ChromeClient.h"
28#include "ContextMenuClient.h"
29#include "ContextMenuController.h"
30#include "DOMWindow.h"
31#include "DocumentMarkerController.h"
32#include "DocumentStyleSheetCollection.h"
33#include "DragController.h"
34#include "EditorClient.h"
35#include "Event.h"
36#include "EventNames.h"
37#include "ExceptionCode.h"
38#include "FileSystem.h"
39#include "FocusController.h"
40#include "Frame.h"
41#include "FrameLoader.h"
42#include "FrameLoaderClient.h"
43#include "FrameSelection.h"
44#include "FrameTree.h"
45#include "FrameView.h"
46#include "HTMLElement.h"
47#include "HistoryItem.h"
48#include "InspectorController.h"
49#include "InspectorInstrumentation.h"
50#include "Logging.h"
51#include "MediaCanStartListener.h"
52#include "Navigator.h"
53#include "NetworkStateNotifier.h"
54#include "PageCache.h"
55#include "PageGroup.h"
56#include "PluginData.h"
57#include "PluginView.h"
58#include "PointerLockController.h"
59#include "ProgressTracker.h"
60#include "RenderArena.h"
61#include "RenderTheme.h"
62#include "RenderView.h"
63#include "RenderWidget.h"
64#include "RuntimeEnabledFeatures.h"
65#include "SchemeRegistry.h"
66#include "ScrollingCoordinator.h"
67#include "Settings.h"
68#include "SharedBuffer.h"
69#include "StorageArea.h"
70#include "StorageNamespace.h"
71#include "StyleResolver.h"
72#include "TextResourceDecoder.h"
73#include "VoidCallback.h"
74#include "WebCoreMemoryInstrumentation.h"
75#include "Widget.h"
76#include <wtf/HashMap.h>
77#include <wtf/RefCountedLeakCounter.h>
78#include <wtf/StdLibExtras.h>
79#include <wtf/text/Base64.h>
80#include <wtf/text/StringHash.h>
81
82namespace WebCore {
83
84static HashSet<Page*>* allPages;
85static const double hiddenPageTimerAlignmentInterval = 1.0; // once a second
86
87DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
88
89static void networkStateChanged()
90{
91 Vector<RefPtr<Frame> > frames;
92
93 // Get all the frames of all the pages in all the page groups
94 HashSet<Page*>::iterator end = allPages->end();
95 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
96 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
97 frames.append(frame);
98 InspectorInstrumentation::networkStateChanged(*it);
99 }
100
101 AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent;
102 for (unsigned i = 0; i < frames.size(); i++)
103 frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false));
104}
105
106float deviceScaleFactor(Frame* frame)
107{
108 if (!frame)
109 return 1;
110 Page* page = frame->page();
111 if (!page)
112 return 1;
113 return page->deviceScaleFactor();
114}
115
116Page::Page(PageClients& pageClients)
117 : m_chrome(Chrome::create(this, pageClients.chromeClient))
118 , m_dragCaretController(DragCaretController::create())
119#if ENABLE(DRAG_SUPPORT)
120 , m_dragController(DragController::create(this, pageClients.dragClient))
121#endif
122 , m_focusController(FocusController::create(this))
123#if ENABLE(CONTEXT_MENUS)
124 , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
125#endif
126#if ENABLE(INSPECTOR)
127 , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
128#endif
129#if ENABLE(POINTER_LOCK)
130 , m_pointerLockController(PointerLockController::create(this))
131#endif
132 , m_settings(Settings::create(this))
133 , m_progress(ProgressTracker::create())
134 , m_backForwardController(BackForwardController::create(this, pageClients.backForwardClient))
135 , m_theme(RenderTheme::themeForPage(this))
136 , m_editorClient(pageClients.editorClient)
137 , m_validationMessageClient(pageClients.validationMessageClient)
138 , m_subframeCount(0)
139 , m_openedByDOM(false)
140 , m_tabKeyCyclesThroughElements(true)
141 , m_defersLoading(false)
142 , m_defersLoadingCallCount(0)
143 , m_inLowQualityInterpolationMode(false)
144 , m_cookieEnabled(true)
145 , m_areMemoryCacheClientCallsEnabled(true)
146 , m_mediaVolume(1)
147 , m_pageScaleFactor(1)
148 , m_deviceScaleFactor(1)
149 , m_suppressScrollbarAnimations(false)
150 , m_didLoadUserStyleSheet(false)
151 , m_userStyleSheetModificationTime(0)
152 , m_group(0)
153 , m_debugger(0)
154 , m_customHTMLTokenizerTimeDelay(-1)
155 , m_customHTMLTokenizerChunkSize(-1)
156 , m_canStartMedia(true)
157 , m_viewMode(ViewModeWindowed)
158 , m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval())
159 , m_timerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval())
160 , m_isEditable(false)
161 , m_isOnscreen(true)
162#if ENABLE(PAGE_VISIBILITY_API)
163 , m_visibilityState(PageVisibilityStateVisible)
164#endif
165 , m_displayID(0)
166 , m_layoutMilestones(0)
167 , m_isCountingRelevantRepaintedObjects(false)
168#ifndef NDEBUG
169 , m_isPainting(false)
170#endif
171 , m_alternativeTextClient(pageClients.alternativeTextClient)
172 , m_scriptedAnimationsSuspended(false)
173{
174 ASSERT(m_editorClient);
175
176 if (!allPages) {
177 allPages = new HashSet<Page*>;
178
179 networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);
180 }
181
182 ASSERT(!allPages->contains(this));
183 allPages->add(this);
184
185#ifndef NDEBUG
186 pageCounter.increment();
187#endif
188}
189
190Page::~Page()
191{
192 m_mainFrame->setView(0);
193 setGroupName(String());
194 allPages->remove(this);
195
196 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
197 frame->willDetachPage();
198 frame->detachFromPage();
199 }
200
201 m_editorClient->pageDestroyed();
202 if (m_alternativeTextClient)
203 m_alternativeTextClient->pageDestroyed();
204
205#if ENABLE(INSPECTOR)
206 m_inspectorController->inspectedPageDestroyed();
207#endif
208
209 if (m_scrollingCoordinator)
210 m_scrollingCoordinator->pageDestroyed();
211
212 backForward()->close();
213
214#ifndef NDEBUG
215 pageCounter.decrement();
216#endif
217
218}
219
220ArenaSize Page::renderTreeSize() const
221{
222 ArenaSize total(0, 0);
223 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
224 if (!frame->document())
225 continue;
226 if (RenderArena* arena = frame->document()->renderArena()) {
227 total.treeSize += arena->totalRenderArenaSize();
228 total.allocated += arena->totalRenderArenaAllocatedBytes();
229 }
230 }
231 return total;
232}
233
234ViewportArguments Page::viewportArguments() const
235{
236 return mainFrame() && mainFrame()->document() ? mainFrame()->document()->viewportArguments() : ViewportArguments();
237}
238
239ScrollingCoordinator* Page::scrollingCoordinator()
240{
241 if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled())
242 m_scrollingCoordinator = ScrollingCoordinator::create(this);
243
244 return m_scrollingCoordinator.get();
245}
246
247String Page::scrollingStateTreeAsText()
248{
249 if (Document* document = m_mainFrame->document())
250 document->updateLayout();
251
252 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
253 return scrollingCoordinator->scrollingStateTreeAsText();
254
255 return String();
256}
257
258struct ViewModeInfo {
259 const char* name;
260 Page::ViewMode type;
261};
262static const int viewModeMapSize = 5;
263static ViewModeInfo viewModeMap[viewModeMapSize] = {
264 {"windowed", Page::ViewModeWindowed},
265 {"floating", Page::ViewModeFloating},
266 {"fullscreen", Page::ViewModeFullscreen},
267 {"maximized", Page::ViewModeMaximized},
268 {"minimized", Page::ViewModeMinimized}
269};
270
271Page::ViewMode Page::stringToViewMode(const String& text)
272{
273 for (int i = 0; i < viewModeMapSize; ++i) {
274 if (text == viewModeMap[i].name)
275 return viewModeMap[i].type;
276 }
277 return Page::ViewModeInvalid;
278}
279
280void Page::setViewMode(ViewMode viewMode)
281{
282 if (viewMode == m_viewMode || viewMode == ViewModeInvalid)
283 return;
284
285 m_viewMode = viewMode;
286
287 if (!m_mainFrame)
288 return;
289
290 if (m_mainFrame->view())
291 m_mainFrame->view()->forceLayout();
292
293 if (m_mainFrame->document())
294 m_mainFrame->document()->styleResolverChanged(RecalcStyleImmediately);
295}
296
297void Page::setMainFrame(PassRefPtr<Frame> mainFrame)
298{
299 ASSERT(!m_mainFrame); // Should only be called during initialization
300 m_mainFrame = mainFrame;
301}
302
303bool Page::openedByDOM() const
304{
305 return m_openedByDOM;
306}
307
308void Page::setOpenedByDOM()
309{
310 m_openedByDOM = true;
311}
312
313BackForwardList* Page::backForwardList() const
314{
315 return m_backForwardController->client();
316}
317
318bool Page::goBack()
319{
320 HistoryItem* item = backForward()->backItem();
321
322 if (item) {
323 goToItem(item, FrameLoadTypeBack);
324 return true;
325 }
326 return false;
327}
328
329bool Page::goForward()
330{
331 HistoryItem* item = backForward()->forwardItem();
332
333 if (item) {
334 goToItem(item, FrameLoadTypeForward);
335 return true;
336 }
337 return false;
338}
339
340bool Page::canGoBackOrForward(int distance) const
341{
342 if (distance == 0)
343 return true;
344 if (distance > 0 && distance <= backForward()->forwardCount())
345 return true;
346 if (distance < 0 && -distance <= backForward()->backCount())
347 return true;
348 return false;
349}
350
351void Page::goBackOrForward(int distance)
352{
353 if (distance == 0)
354 return;
355
356 HistoryItem* item = backForward()->itemAtIndex(distance);
357 if (!item) {
358 if (distance > 0) {
359 if (int forwardCount = backForward()->forwardCount())
360 item = backForward()->itemAtIndex(forwardCount);
361 } else {
362 if (int backCount = backForward()->backCount())
363 item = backForward()->itemAtIndex(-backCount);
364 }
365 }
366
367 if (!item)
368 return;
369
370 goToItem(item, FrameLoadTypeIndexedBackForward);
371}
372
373void Page::goToItem(HistoryItem* item, FrameLoadType type)
374{
375 // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
376 // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
377 RefPtr<HistoryItem> protector(item);
378
379 if (m_mainFrame->loader()->history()->shouldStopLoadingForHistoryItem(item))
380 m_mainFrame->loader()->stopAllLoaders();
381
382 m_mainFrame->loader()->history()->goToItem(item, type);
383}
384
385int Page::getHistoryLength()
386{
387 return backForward()->backCount() + 1 + backForward()->forwardCount();
388}
389
390void Page::setGroupName(const String& name)
391{
392 if (m_group && !m_group->name().isEmpty()) {
393 ASSERT(m_group != m_singlePageGroup.get());
394 ASSERT(!m_singlePageGroup);
395 m_group->removePage(this);
396 }
397
398 if (name.isEmpty())
399 m_group = m_singlePageGroup.get();
400 else {
401 m_singlePageGroup.clear();
402 m_group = PageGroup::pageGroup(name);
403 m_group->addPage(this);
404 }
405}
406
407const String& Page::groupName() const
408{
409 DEFINE_STATIC_LOCAL(String, nullString, ());
410 // FIXME: Why not just return String()?
411 return m_group ? m_group->name() : nullString;
412}
413
414void Page::initGroup()
415{
416 ASSERT(!m_singlePageGroup);
417 ASSERT(!m_group);
418 m_singlePageGroup = PageGroup::create(this);
419 m_group = m_singlePageGroup.get();
420}
421
422void Page::scheduleForcedStyleRecalcForAllPages()
423{
424 if (!allPages)
425 return;
426 HashSet<Page*>::iterator end = allPages->end();
427 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
428 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
429 frame->document()->scheduleForcedStyleRecalc();
430}
431
432void Page::setNeedsRecalcStyleInAllFrames()
433{
434 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
435 frame->document()->styleResolverChanged(DeferRecalcStyle);
436}
437
438void Page::refreshPlugins(bool reload)
439{
440 if (!allPages)
441 return;
442
443 PluginData::refresh();
444
445 Vector<RefPtr<Frame> > framesNeedingReload;
446
447 HashSet<Page*>::iterator end = allPages->end();
448 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
449 Page* page = *it;
450
451 // Clear out the page's plug-in data.
452 if (page->m_pluginData)
453 page->m_pluginData = 0;
454
455 if (!reload)
456 continue;
457
458 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
459 if (frame->loader()->subframeLoader()->containsPlugins())
460 framesNeedingReload.append(frame);
461 }
462 }
463
464 for (size_t i = 0; i < framesNeedingReload.size(); ++i)
465 framesNeedingReload[i]->loader()->reload();
466}
467
468PluginData* Page::pluginData() const
469{
470 if (!mainFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
471 return 0;
472 if (!m_pluginData)
473 m_pluginData = PluginData::create(this);
474 return m_pluginData.get();
475}
476
477inline MediaCanStartListener* Page::takeAnyMediaCanStartListener()
478{
479 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
480 if (MediaCanStartListener* listener = frame->document()->takeAnyMediaCanStartListener())
481 return listener;
482 }
483 return 0;
484}
485
486void Page::setCanStartMedia(bool canStartMedia)
487{
488 if (m_canStartMedia == canStartMedia)
489 return;
490
491 m_canStartMedia = canStartMedia;
492
493 while (m_canStartMedia) {
494 MediaCanStartListener* listener = takeAnyMediaCanStartListener();
495 if (!listener)
496 break;
497 listener->mediaCanStart();
498 }
499}
500
501static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
502{
503 return forward
504 ? curr->tree()->traverseNextWithWrap(wrapFlag)
505 : curr->tree()->traversePreviousWithWrap(wrapFlag);
506}
507
508bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity, FindDirection direction, bool shouldWrap)
509{
510 return findString(target, (caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0) | (direction == FindDirectionBackward ? Backwards : 0) | (shouldWrap ? WrapAround : 0));
511}
512
513bool Page::findString(const String& target, FindOptions options)
514{
515 if (target.isEmpty() || !mainFrame())
516 return false;
517
518 bool shouldWrap = options & WrapAround;
519 Frame* frame = focusController()->focusedOrMainFrame();
520 Frame* startFrame = frame;
521 do {
522 if (frame->editor()->findString(target, (options & ~WrapAround) | StartInSelection)) {
523 if (frame != startFrame)
524 startFrame->selection()->clear();
525 focusController()->setFocusedFrame(frame);
526 return true;
527 }
528 frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
529 } while (frame && frame != startFrame);
530
531 // Search contents of startFrame, on the other side of the selection that we did earlier.
532 // We cheat a bit and just research with wrap on
533 if (shouldWrap && !startFrame->selection()->isNone()) {
534 bool found = startFrame->editor()->findString(target, options | WrapAround | StartInSelection);
535 focusController()->setFocusedFrame(frame);
536 return found;
537 }
538
539 return false;
540}
541
542PassRefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
543{
544 if (target.isEmpty() || !mainFrame())
545 return 0;
546
547 if (referenceRange && referenceRange->ownerDocument()->page() != this)
548 return 0;
549
550 bool shouldWrap = options & WrapAround;
551 Frame* frame = referenceRange ? referenceRange->ownerDocument()->frame() : mainFrame();
552 Frame* startFrame = frame;
553 do {
554 if (RefPtr<Range> resultRange = frame->editor()->rangeOfString(target, frame == startFrame ? referenceRange : 0, options & ~WrapAround))
555 return resultRange.release();
556
557 frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
558 } while (frame && frame != startFrame);
559
560 // Search contents of startFrame, on the other side of the reference range that we did earlier.
561 // We cheat a bit and just search again with wrap on.
562 if (shouldWrap && referenceRange) {
563 if (RefPtr<Range> resultRange = startFrame->editor()->rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
564 return resultRange.release();
565 }
566
567 return 0;
568}
569
570unsigned int Page::markAllMatchesForText(const String& target, TextCaseSensitivity caseSensitivity, bool shouldHighlight, unsigned limit)
571{
572 return markAllMatchesForText(target, caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0, shouldHighlight, limit);
573}
574
575unsigned int Page::markAllMatchesForText(const String& target, FindOptions options, bool shouldHighlight, unsigned limit)
576{
577 if (target.isEmpty() || !mainFrame())
578 return 0;
579
580 unsigned matches = 0;
581
582 Frame* frame = mainFrame();
583 do {
584 frame->editor()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
585 matches += frame->editor()->countMatchesForText(target, options, limit ? (limit - matches) : 0, true);
586 frame = incrementFrame(frame, true, false);
587 } while (frame);
588
589 return matches;
590}
591
592void Page::unmarkAllTextMatches()
593{
594 if (!mainFrame())
595 return;
596
597 Frame* frame = mainFrame();
598 do {
599 frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
600 frame = incrementFrame(frame, true, false);
601 } while (frame);
602}
603
604const VisibleSelection& Page::selection() const
605{
606 return focusController()->focusedOrMainFrame()->selection()->selection();
607}
608
609void Page::setDefersLoading(bool defers)
610{
611 if (!m_settings->loadDeferringEnabled())
612 return;
613
614 if (m_settings->wantsBalancedSetDefersLoadingBehavior()) {
615 ASSERT(defers || m_defersLoadingCallCount);
616 if (defers && ++m_defersLoadingCallCount > 1)
617 return;
618 if (!defers && --m_defersLoadingCallCount)
619 return;
620 } else {
621 ASSERT(!m_defersLoadingCallCount);
622 if (defers == m_defersLoading)
623 return;
624 }
625
626 m_defersLoading = defers;
627 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
628 frame->loader()->setDefersLoading(defers);
629}
630
631void Page::clearUndoRedoOperations()
632{
633 m_editorClient->clearUndoRedoOperations();
634}
635
636bool Page::inLowQualityImageInterpolationMode() const
637{
638 return m_inLowQualityInterpolationMode;
639}
640
641void Page::setInLowQualityImageInterpolationMode(bool mode)
642{
643 m_inLowQualityInterpolationMode = mode;
644}
645
646void Page::setMediaVolume(float volume)
647{
648 if (volume < 0 || volume > 1)
649 return;
650
651 if (m_mediaVolume == volume)
652 return;
653
654 m_mediaVolume = volume;
655 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
656 frame->document()->mediaVolumeDidChange();
657 }
658}
659
660void Page::setPageScaleFactor(float scale, const IntPoint& origin)
661{
662 Document* document = mainFrame()->document();
663 FrameView* view = document->view();
664
665 if (scale == m_pageScaleFactor) {
666 if (view && (view->scrollPosition() != origin || view->delegatesScrolling())) {
667 document->updateLayoutIgnorePendingStylesheets();
668 view->setScrollPosition(origin);
669 }
670 return;
671 }
672
673 m_pageScaleFactor = scale;
674
675 if (document->renderer())
676 document->renderer()->setNeedsLayout(true);
677
678 document->recalcStyle(Node::Force);
679
680 // Transform change on RenderView doesn't trigger repaint on non-composited contents.
681 mainFrame()->view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
682
683#if USE(ACCELERATED_COMPOSITING)
684 mainFrame()->deviceOrPageScaleFactorChanged();
685#endif
686
687 if (view && view->scrollPosition() != origin) {
688 if (document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
689 view->layout();
690 view->setScrollPosition(origin);
691 }
692}
693
694
695void Page::setDeviceScaleFactor(float scaleFactor)
696{
697 if (m_deviceScaleFactor == scaleFactor)
698 return;
699
700 m_deviceScaleFactor = scaleFactor;
701 setNeedsRecalcStyleInAllFrames();
702
703#if USE(ACCELERATED_COMPOSITING)
704 if (mainFrame())
705 mainFrame()->deviceOrPageScaleFactorChanged();
706#endif
707
708 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
709 frame->editor()->deviceScaleFactorChanged();
710
711 pageCache()->markPagesForFullStyleRecalc(this);
712}
713
714void Page::setShouldSuppressScrollbarAnimations(bool suppressAnimations)
715{
716 if (suppressAnimations == m_suppressScrollbarAnimations)
717 return;
718
719 if (!suppressAnimations) {
720 // If animations are not going to be suppressed anymore, then there is nothing to do here but
721 // change the cached value.
722 m_suppressScrollbarAnimations = suppressAnimations;
723 return;
724 }
725
726 // On the other hand, if we are going to start suppressing animations, then we need to make sure we
727 // finish any current scroll animations first.
728 FrameView* view = mainFrame()->view();
729 if (!view)
730 return;
731
732 view->finishCurrentScrollAnimations();
733
734 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
735 FrameView* frameView = frame->view();
736 if (!frameView)
737 continue;
738
739 const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
740 if (!scrollableAreas)
741 continue;
742
743 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
744 ScrollableArea* scrollableArea = *it;
745 ASSERT(scrollableArea->scrollbarsCanBeActive());
746
747 scrollableArea->finishCurrentScrollAnimations();
748 }
749 }
750
751 m_suppressScrollbarAnimations = suppressAnimations;
752}
753
754void Page::setPagination(const Pagination& pagination)
755{
756 if (m_pagination == pagination)
757 return;
758
759 m_pagination = pagination;
760
761 setNeedsRecalcStyleInAllFrames();
762 pageCache()->markPagesForFullStyleRecalc(this);
763}
764
765unsigned Page::pageCount() const
766{
767 if (m_pagination.mode == Pagination::Unpaginated)
768 return 0;
769
770 FrameView* frameView = mainFrame()->view();
771 if (frameView->needsLayout())
772 frameView->layout();
773
774 RenderView* contentRenderer = mainFrame()->contentRenderer();
775 return contentRenderer ? contentRenderer->columnCount(contentRenderer->columnInfo()) : 0;
776}
777
778void Page::didMoveOnscreen()
779{
780 m_isOnscreen = true;
781
782 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
783 if (FrameView* frameView = frame->view())
784 frameView->didMoveOnscreen();
785 }
786
787 resumeScriptedAnimations();
788}
789
790void Page::willMoveOffscreen()
791{
792 m_isOnscreen = false;
793
794 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
795 if (FrameView* frameView = frame->view())
796 frameView->willMoveOffscreen();
797 }
798
799 suspendScriptedAnimations();
800}
801
802void Page::windowScreenDidChange(PlatformDisplayID displayID)
803{
804 m_displayID = displayID;
805
806 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
807 if (frame->document())
808 frame->document()->windowScreenDidChange(displayID);
809 }
810}
811
812void Page::suspendScriptedAnimations()
813{
814 m_scriptedAnimationsSuspended = true;
815 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
816 if (frame->document())
817 frame->document()->suspendScriptedAnimationControllerCallbacks();
818 }
819}
820
821void Page::resumeScriptedAnimations()
822{
823 m_scriptedAnimationsSuspended = false;
824 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
825 if (frame->document())
826 frame->document()->resumeScriptedAnimationControllerCallbacks();
827 }
828}
829
830void Page::userStyleSheetLocationChanged()
831{
832 // FIXME: Eventually we will move to a model of just being handed the sheet
833 // text instead of loading the URL ourselves.
834 KURL url = m_settings->userStyleSheetLocation();
835
836 // Allow any local file URL scheme to be loaded.
837 if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()))
838 m_userStyleSheetPath = url.fileSystemPath();
839 else
840 m_userStyleSheetPath = String();
841
842 m_didLoadUserStyleSheet = false;
843 m_userStyleSheet = String();
844 m_userStyleSheetModificationTime = 0;
845
846 // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
847 // synchronously and avoid using a loader.
848 if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
849 m_didLoadUserStyleSheet = true;
850
851 Vector<char> styleSheetAsUTF8;
852 if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreWhitespace))
853 m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
854 }
855
856 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
857 if (frame->document())
858 frame->document()->styleSheetCollection()->updatePageUserStyleSheet();
859 }
860}
861
862const String& Page::userStyleSheet() const
863{
864 if (m_userStyleSheetPath.isEmpty())
865 return m_userStyleSheet;
866
867 time_t modTime;
868 if (!getFileModificationTime(m_userStyleSheetPath, modTime)) {
869 // The stylesheet either doesn't exist, was just deleted, or is
870 // otherwise unreadable. If we've read the stylesheet before, we should
871 // throw away that data now as it no longer represents what's on disk.
872 m_userStyleSheet = String();
873 return m_userStyleSheet;
874 }
875
876 // If the stylesheet hasn't changed since the last time we read it, we can
877 // just return the old data.
878 if (m_didLoadUserStyleSheet && modTime <= m_userStyleSheetModificationTime)
879 return m_userStyleSheet;
880
881 m_didLoadUserStyleSheet = true;
882 m_userStyleSheet = String();
883 m_userStyleSheetModificationTime = modTime;
884
885 // FIXME: It would be better to load this asynchronously to avoid blocking
886 // the process, but we will first need to create an asynchronous loading
887 // mechanism that is not tied to a particular Frame. We will also have to
888 // determine what our behavior should be before the stylesheet is loaded
889 // and what should happen when it finishes loading, especially with respect
890 // to when the load event fires, when Document::close is called, and when
891 // layout/paint are allowed to happen.
892 RefPtr<SharedBuffer> data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath);
893 if (!data)
894 return m_userStyleSheet;
895
896 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/css");
897 m_userStyleSheet = decoder->decode(data->data(), data->size());
898 m_userStyleSheet.append(decoder->flush());
899
900 return m_userStyleSheet;
901}
902
903void Page::removeAllVisitedLinks()
904{
905 if (!allPages)
906 return;
907 HashSet<PageGroup*> groups;
908 HashSet<Page*>::iterator pagesEnd = allPages->end();
909 for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
910 if (PageGroup* group = (*it)->groupPtr())
911 groups.add(group);
912 }
913 HashSet<PageGroup*>::iterator groupsEnd = groups.end();
914 for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it)
915 (*it)->removeVisitedLinks();
916}
917
918void Page::allVisitedStateChanged(PageGroup* group)
919{
920 ASSERT(group);
921 if (!allPages)
922 return;
923
924 HashSet<Page*>::iterator pagesEnd = allPages->end();
925 for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
926 Page* page = *it;
927 if (page->m_group != group)
928 continue;
929 for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
930 if (StyleResolver* styleResolver = frame->document()->styleResolver())
931 styleResolver->allVisitedStateChanged();
932 }
933 }
934}
935
936void Page::visitedStateChanged(PageGroup* group, LinkHash visitedLinkHash)
937{
938 ASSERT(group);
939 if (!allPages)
940 return;
941
942 HashSet<Page*>::iterator pagesEnd = allPages->end();
943 for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
944 Page* page = *it;
945 if (page->m_group != group)
946 continue;
947 for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
948 if (StyleResolver* styleResolver = frame->document()->styleResolver())
949 styleResolver->visitedStateChanged(visitedLinkHash);
950 }
951 }
952}
953
954void Page::setDebuggerForAllPages(JSC::Debugger* debugger)
955{
956 ASSERT(allPages);
957
958 HashSet<Page*>::iterator end = allPages->end();
959 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
960 (*it)->setDebugger(debugger);
961}
962
963void Page::setDebugger(JSC::Debugger* debugger)
964{
965 if (m_debugger == debugger)
966 return;
967
968 m_debugger = debugger;
969
970 for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext())
971 frame->script()->attachDebugger(m_debugger);
972}
973
974StorageNamespace* Page::sessionStorage(bool optionalCreate)
975{
976 if (!m_sessionStorage && optionalCreate)
977 m_sessionStorage = StorageNamespace::sessionStorageNamespace(this, m_settings->sessionStorageQuota());
978
979 return m_sessionStorage.get();
980}
981
982void Page::setSessionStorage(PassRefPtr<StorageNamespace> newStorage)
983{
984 m_sessionStorage = newStorage;
985}
986
987void Page::setCustomHTMLTokenizerTimeDelay(double customHTMLTokenizerTimeDelay)
988{
989 if (customHTMLTokenizerTimeDelay < 0) {
990 m_customHTMLTokenizerTimeDelay = -1;
991 return;
992 }
993 m_customHTMLTokenizerTimeDelay = customHTMLTokenizerTimeDelay;
994}
995
996void Page::setCustomHTMLTokenizerChunkSize(int customHTMLTokenizerChunkSize)
997{
998 if (customHTMLTokenizerChunkSize < 0) {
999 m_customHTMLTokenizerChunkSize = -1;
1000 return;
1001 }
1002 m_customHTMLTokenizerChunkSize = customHTMLTokenizerChunkSize;
1003}
1004
1005void Page::setMemoryCacheClientCallsEnabled(bool enabled)
1006{
1007 if (m_areMemoryCacheClientCallsEnabled == enabled)
1008 return;
1009
1010 m_areMemoryCacheClientCallsEnabled = enabled;
1011 if (!enabled)
1012 return;
1013
1014 for (RefPtr<Frame> frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1015 frame->loader()->tellClientAboutPastMemoryCacheLoads();
1016}
1017
1018void Page::setMinimumTimerInterval(double minimumTimerInterval)
1019{
1020 double oldTimerInterval = m_minimumTimerInterval;
1021 m_minimumTimerInterval = minimumTimerInterval;
1022 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNextWithWrap(false)) {
1023 if (frame->document())
1024 frame->document()->adjustMinimumTimerInterval(oldTimerInterval);
1025 }
1026}
1027
1028double Page::minimumTimerInterval() const
1029{
1030 return m_minimumTimerInterval;
1031}
1032
1033void Page::setTimerAlignmentInterval(double interval)
1034{
1035 if (interval == m_timerAlignmentInterval)
1036 return;
1037
1038 m_timerAlignmentInterval = interval;
1039 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNextWithWrap(false)) {
1040 if (frame->document())
1041 frame->document()->didChangeTimerAlignmentInterval();
1042 }
1043}
1044
1045double Page::timerAlignmentInterval() const
1046{
1047 return m_timerAlignmentInterval;
1048}
1049
1050void Page::dnsPrefetchingStateChanged()
1051{
1052 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1053 frame->document()->initDNSPrefetch();
1054}
1055
1056void Page::collectPluginViews(Vector<RefPtr<PluginViewBase>, 32>& pluginViewBases)
1057{
1058 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1059 FrameView* view = frame->view();
1060 if (!view)
1061 return;
1062
1063 const HashSet<RefPtr<Widget> >* children = view->children();
1064 ASSERT(children);
1065
1066 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1067 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1068 Widget* widget = (*it).get();
1069 if (widget->isPluginViewBase())
1070 pluginViewBases.append(static_cast<PluginViewBase*>(widget));
1071 }
1072 }
1073}
1074
1075void Page::storageBlockingStateChanged()
1076{
1077 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1078 frame->document()->storageBlockingStateDidChange();
1079
1080 // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1081 // from below storageBlockingStateChanged does not affect their lifetime.
1082 Vector<RefPtr<PluginViewBase>, 32> pluginViewBases;
1083 collectPluginViews(pluginViewBases);
1084
1085 for (size_t i = 0; i < pluginViewBases.size(); ++i)
1086 pluginViewBases[i]->storageBlockingStateChanged();
1087}
1088
1089void Page::privateBrowsingStateChanged()
1090{
1091 bool privateBrowsingEnabled = m_settings->privateBrowsingEnabled();
1092
1093 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1094 frame->document()->privateBrowsingStateDidChange();
1095
1096 // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1097 // from below privateBrowsingStateChanged does not affect their lifetime.
1098 Vector<RefPtr<PluginViewBase>, 32> pluginViewBases;
1099 collectPluginViews(pluginViewBases);
1100
1101 for (size_t i = 0; i < pluginViewBases.size(); ++i)
1102 pluginViewBases[i]->privateBrowsingStateChanged(privateBrowsingEnabled);
1103}
1104
1105#if !ASSERT_DISABLED
1106void Page::checkSubframeCountConsistency() const
1107{
1108 ASSERT(m_subframeCount >= 0);
1109
1110 int subframeCount = 0;
1111 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1112 ++subframeCount;
1113
1114 ASSERT(m_subframeCount + 1 == subframeCount);
1115}
1116#endif
1117
1118#if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1119void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
1120{
1121#if ENABLE(PAGE_VISIBILITY_API)
1122 if (m_visibilityState == visibilityState)
1123 return;
1124 m_visibilityState = visibilityState;
1125
1126 if (!isInitialState && m_mainFrame)
1127 m_mainFrame->dispatchVisibilityStateChangeEvent();
1128#endif
1129
1130#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1131 if (visibilityState == WebCore::PageVisibilityStateHidden)
1132 setTimerAlignmentInterval(hiddenPageTimerAlignmentInterval);
1133 else
1134 setTimerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval());
1135#if !ENABLE(PAGE_VISIBILITY_API)
1136 UNUSED_PARAM(isInitialState);
1137#endif
1138#endif
1139}
1140#endif // ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1141
1142#if ENABLE(PAGE_VISIBILITY_API)
1143PageVisibilityState Page::visibilityState() const
1144{
1145 return m_visibilityState;
1146}
1147#endif
1148
1149void Page::addLayoutMilestones(LayoutMilestones milestones)
1150{
1151 // In the future, we may want a function that replaces m_layoutMilestones instead of just adding to it.
1152 m_layoutMilestones |= milestones;
1153}
1154
1155// These are magical constants that might be tweaked over time.
1156static double gMinimumPaintedAreaRatio = 0.1;
1157static double gMaximumUnpaintedAreaRatio = 0.04;
1158
1159bool Page::isCountingRelevantRepaintedObjects() const
1160{
1161 return m_isCountingRelevantRepaintedObjects && (m_layoutMilestones & DidHitRelevantRepaintedObjectsAreaThreshold);
1162}
1163
1164void Page::startCountingRelevantRepaintedObjects()
1165{
1166 // Reset everything in case we didn't hit the threshold last time.
1167 resetRelevantPaintedObjectCounter();
1168
1169 m_isCountingRelevantRepaintedObjects = true;
1170}
1171
1172void Page::resetRelevantPaintedObjectCounter()
1173{
1174 m_isCountingRelevantRepaintedObjects = false;
1175 m_relevantUnpaintedRenderObjects.clear();
1176 m_relevantPaintedRegion = Region();
1177 m_relevantUnpaintedRegion = Region();
1178}
1179
1180void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1181{
1182 if (!isCountingRelevantRepaintedObjects())
1183 return;
1184
1185 // The objects are only relevant if they are being painted within the viewRect().
1186 if (RenderView* view = object->view()) {
1187 if (!objectPaintRect.intersects(pixelSnappedIntRect(view->viewRect())))
1188 return;
1189 }
1190
1191 IntRect snappedPaintRect = pixelSnappedIntRect(objectPaintRect);
1192
1193 // If this object was previously counted as an unpainted object, remove it from that HashSet
1194 // and corresponding Region. FIXME: This doesn't do the right thing if the objects overlap.
1195 HashSet<RenderObject*>::iterator it = m_relevantUnpaintedRenderObjects.find(object);
1196 if (it != m_relevantUnpaintedRenderObjects.end()) {
1197 m_relevantUnpaintedRenderObjects.remove(it);
1198 m_relevantUnpaintedRegion.subtract(snappedPaintRect);
1199 }
1200
1201 m_relevantPaintedRegion.unite(snappedPaintRect);
1202
1203 RenderView* view = object->view();
1204 if (!view)
1205 return;
1206
1207 float viewArea = view->viewRect().width() * view->viewRect().height();
1208 float ratioOfViewThatIsPainted = m_relevantPaintedRegion.totalArea() / viewArea;
1209 float ratioOfViewThatIsUnpainted = m_relevantUnpaintedRegion.totalArea() / viewArea;
1210
1211 if (ratioOfViewThatIsPainted > gMinimumPaintedAreaRatio && ratioOfViewThatIsUnpainted < gMaximumUnpaintedAreaRatio) {
1212 m_isCountingRelevantRepaintedObjects = false;
1213 resetRelevantPaintedObjectCounter();
1214 if (Frame* frame = mainFrame())
1215 frame->loader()->didLayout(DidHitRelevantRepaintedObjectsAreaThreshold);
1216 }
1217}
1218
1219void Page::addRelevantUnpaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1220{
1221 if (!isCountingRelevantRepaintedObjects())
1222 return;
1223
1224 // The objects are only relevant if they are being painted within the viewRect().
1225 if (RenderView* view = object->view()) {
1226 if (!objectPaintRect.intersects(pixelSnappedIntRect(view->viewRect())))
1227 return;
1228 }
1229
1230 m_relevantUnpaintedRenderObjects.add(object);
1231 m_relevantUnpaintedRegion.unite(pixelSnappedIntRect(objectPaintRect));
1232}
1233
1234void Page::suspendActiveDOMObjectsAndAnimations()
1235{
1236 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1237 frame->suspendActiveDOMObjectsAndAnimations();
1238}
1239
1240void Page::resumeActiveDOMObjectsAndAnimations()
1241{
1242 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1243 frame->resumeActiveDOMObjectsAndAnimations();
1244}
1245
1246bool Page::hasSeenAnyPlugin() const
1247{
1248 return !m_seenPlugins.isEmpty();
1249}
1250
1251bool Page::hasSeenPlugin(const String& serviceType) const
1252{
1253 return m_seenPlugins.contains(serviceType);
1254}
1255
1256void Page::sawPlugin(const String& serviceType)
1257{
1258 m_seenPlugins.add(serviceType);
1259}
1260
1261void Page::resetSeenPlugins()
1262{
1263 m_seenPlugins.clear();
1264}
1265
1266bool Page::hasSeenAnyMediaEngine() const
1267{
1268 return !m_seenMediaEngines.isEmpty();
1269}
1270
1271bool Page::hasSeenMediaEngine(const String& engineDescription) const
1272{
1273 return m_seenMediaEngines.contains(engineDescription);
1274}
1275
1276void Page::sawMediaEngine(const String& engineDescription)
1277{
1278 m_seenMediaEngines.add(engineDescription);
1279}
1280
1281void Page::resetSeenMediaEngines()
1282{
1283 m_seenMediaEngines.clear();
1284}
1285
1286void Page::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
1287{
1288 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Page);
1289 info.addMember(m_chrome);
1290 info.addMember(m_dragCaretController);
1291
1292#if ENABLE(DRAG_SUPPORT)
1293 info.addMember(m_dragController);
1294#endif
1295 info.addMember(m_focusController);
1296#if ENABLE(CONTEXT_MENUS)
1297 info.addMember(m_contextMenuController);
1298#endif
1299#if ENABLE(INSPECTOR)
1300 info.addMember(m_inspectorController);
1301#endif
1302#if ENABLE(POINTER_LOCK)
1303 info.addMember(m_pointerLockController);
1304#endif
1305 info.addMember(m_scrollingCoordinator);
1306 info.addMember(m_settings);
1307 info.addMember(m_progress);
1308 info.addMember(m_backForwardController);
1309 info.addMember(m_mainFrame);
1310 info.addMember(m_pluginData);
1311 info.addMember(m_theme);
1312 info.addWeakPointer(m_editorClient);
1313 info.addMember(m_featureObserver);
1314 info.addMember(m_groupName);
1315 info.addMember(m_pagination);
1316 info.addMember(m_userStyleSheetPath);
1317 info.addMember(m_userStyleSheet);
1318 info.addMember(m_singlePageGroup);
1319 info.addMember(m_group);
1320 info.addWeakPointer(m_debugger);
1321 info.addMember(m_sessionStorage);
1322 info.addMember(m_relevantUnpaintedRenderObjects);
1323 info.addMember(m_relevantPaintedRegion);
1324 info.addMember(m_relevantUnpaintedRegion);
1325 info.addWeakPointer(m_alternativeTextClient);
1326 info.addMember(m_seenPlugins);
1327}
1328
1329Page::PageClients::PageClients()
1330 : alternativeTextClient(0)
1331 , chromeClient(0)
1332#if ENABLE(CONTEXT_MENUS)
1333 , contextMenuClient(0)
1334#endif
1335 , editorClient(0)
1336 , dragClient(0)
1337 , inspectorClient(0)
1338 , validationMessageClient(0)
1339{
1340}
1341
1342Page::PageClients::~PageClients()
1343{
1344}
1345
1346} // namespace WebCore
13470
=== removed directory '.pc/disable_geolocation_501.diff'
=== removed directory '.pc/disable_geolocation_501.diff/Source'
=== removed directory '.pc/disable_geolocation_501.diff/Source/WebKit'
=== removed directory '.pc/disable_geolocation_501.diff/Source/WebKit/qt'
=== removed directory '.pc/disable_geolocation_501.diff/Source/WebKit/qt/Api'
=== removed file '.pc/disable_geolocation_501.diff/Source/WebKit/qt/Api/qwebpage.cpp'
--- .pc/disable_geolocation_501.diff/Source/WebKit/qt/Api/qwebpage.cpp 2013-02-18 14:24:18 +0000
+++ .pc/disable_geolocation_501.diff/Source/WebKit/qt/Api/qwebpage.cpp 1970-01-01 00:00:00 +0000
@@ -1,4103 +0,0 @@
1/*
2 Copyright (C) 2008, 2009, 2012 Nokia Corporation and/or its subsidiary(-ies)
3 Copyright (C) 2007 Staikos Computing Services Inc.
4 Copyright (C) 2007 Apple Inc.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "config.h"
23#include "qwebpage.h"
24
25#include "qwebview.h"
26#include "qwebframe.h"
27#include "qwebpage_p.h"
28#include "qwebframe_p.h"
29#include "qwebhistory.h"
30#include "qwebhistory_p.h"
31#include "qwebinspector.h"
32#include "qwebinspector_p.h"
33#include "qwebsettings.h"
34#include "qwebkitplatformplugin.h"
35#include "qwebkitversion.h"
36
37#include "CSSComputedStyleDeclaration.h"
38#include "CSSParser.h"
39#include "ApplicationCacheStorage.h"
40#include "BackForwardListImpl.h"
41#include "MemoryCache.h"
42#include "Chrome.h"
43#include "ChromeClientQt.h"
44#include "ClientRect.h"
45#include "ContextMenu.h"
46#include "ContextMenuClientQt.h"
47#include "ContextMenuController.h"
48#if ENABLE(DEVICE_ORIENTATION)
49#include "DeviceMotionClientQt.h"
50#include "DeviceOrientationClientMock.h"
51#include "DeviceOrientationClientQt.h"
52#endif
53#include "DocumentLoader.h"
54#include "DragClientQt.h"
55#include "DragController.h"
56#include "DragData.h"
57#include "DragSession.h"
58#include "Editor.h"
59#include "EditorClientQt.h"
60#include "FocusController.h"
61#include "FormState.h"
62#include "Frame.h"
63#include "FrameLoadRequest.h"
64#include "FrameLoader.h"
65#include "FrameLoader.h"
66#include "FrameLoaderClientQt.h"
67#include "FrameTree.h"
68#include "FrameView.h"
69#if ENABLE(GEOLOCATION)
70#include "GeolocationClientMock.h"
71#include "GeolocationClientQt.h"
72#include "GeolocationController.h"
73#endif
74#include "GeolocationPermissionClientQt.h"
75#include "HTMLFormElement.h"
76#include "HTMLFrameOwnerElement.h"
77#include "HTMLInputElement.h"
78#include "HTMLNames.h"
79#include "HitTestResult.h"
80#include "Image.h"
81#include "InitWebCoreQt.h"
82#include "InspectorClientQt.h"
83#include "InspectorController.h"
84#include "InspectorServerQt.h"
85#include "KURL.h"
86#include "LocalizedStrings.h"
87#include "MIMETypeRegistry.h"
88#include "NavigationAction.h"
89#include "NetworkingContext.h"
90#include "NodeList.h"
91#include "NotificationPresenterClientQt.h"
92#include "NotImplemented.h"
93#include "Page.h"
94#include "PageClientQt.h"
95#include "PageGroup.h"
96#include "Pasteboard.h"
97#include "PlatformGestureEvent.h"
98#include "PlatformKeyboardEvent.h"
99#include "PlatformTouchEvent.h"
100#include "PlatformWheelEvent.h"
101#include "PluginDatabase.h"
102#include "PluginDatabase.h"
103#include "PluginPackage.h"
104#include "ProgressTracker.h"
105#include "QtPlatformPlugin.h"
106#include "RenderTextControl.h"
107#include "RenderThemeQt.h"
108#include "SchemeRegistry.h"
109#include "Scrollbar.h"
110#include "ScrollbarTheme.h"
111#include "SecurityOrigin.h"
112#include "Settings.h"
113#if defined Q_OS_WIN32
114#include "SystemInfo.h"
115#endif // Q_OS_WIN32
116#include "TextIterator.h"
117#include "UtilsQt.h"
118#include "UserAgentQt.h"
119#include "WebEventConversion.h"
120#include "WebKitVersion.h"
121#include "WindowFeatures.h"
122#include "WorkerThread.h"
123
124#include <QAction>
125#include <QApplication>
126#include <QBasicTimer>
127#include <QBitArray>
128#include <QColorDialog>
129#include <QDebug>
130#include <QDesktopWidget>
131#include <QDragEnterEvent>
132#include <QDragLeaveEvent>
133#include <QDragMoveEvent>
134#include <QDropEvent>
135#include <QFileDialog>
136#include <QGestureEvent>
137#include <QInputDialog>
138#include <QLabel>
139#include <QMenu>
140#include <QMessageBox>
141#include <QNetworkProxy>
142#include <QUndoStack>
143#include <QUrl>
144#include <QPainter>
145#include <QClipboard>
146#include <QSslSocket>
147#include <QStyle>
148#include <QSysInfo>
149#include <QTextCharFormat>
150#include <QTouchEvent>
151#include <QNetworkAccessManager>
152#include <QNetworkRequest>
153#if defined(Q_WS_X11)
154#include <QX11Info>
155#endif
156#if USE(QT_MOBILITY_SYSTEMINFO)
157#include <qsysteminfo.h>
158#endif
159
160using namespace WebCore;
161
162// from text/qfont.cpp
163QT_BEGIN_NAMESPACE
164extern Q_GUI_EXPORT int qt_defaultDpi();
165QT_END_NAMESPACE
166
167bool QWebPagePrivate::drtRun = false;
168
169// Lookup table mapping QWebPage::WebActions to the associated Editor commands
170static const char* editorCommandWebActions[] =
171{
172 0, // OpenLink,
173
174 0, // OpenLinkInNewWindow,
175 0, // OpenFrameInNewWindow,
176
177 0, // DownloadLinkToDisk,
178 0, // CopyLinkToClipboard,
179
180 0, // OpenImageInNewWindow,
181 0, // DownloadImageToDisk,
182 0, // CopyImageToClipboard,
183
184 0, // Back,
185 0, // Forward,
186 0, // Stop,
187 0, // Reload,
188
189 "Cut", // Cut,
190 "Copy", // Copy,
191 "Paste", // Paste,
192
193 "Undo", // Undo,
194 "Redo", // Redo,
195 "MoveForward", // MoveToNextChar,
196 "MoveBackward", // MoveToPreviousChar,
197 "MoveWordForward", // MoveToNextWord,
198 "MoveWordBackward", // MoveToPreviousWord,
199 "MoveDown", // MoveToNextLine,
200 "MoveUp", // MoveToPreviousLine,
201 "MoveToBeginningOfLine", // MoveToStartOfLine,
202 "MoveToEndOfLine", // MoveToEndOfLine,
203 "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
204 "MoveToEndOfParagraph", // MoveToEndOfBlock,
205 "MoveToBeginningOfDocument", // MoveToStartOfDocument,
206 "MoveToEndOfDocument", // MoveToEndOfDocument,
207 "MoveForwardAndModifySelection", // SelectNextChar,
208 "MoveBackwardAndModifySelection", // SelectPreviousChar,
209 "MoveWordForwardAndModifySelection", // SelectNextWord,
210 "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
211 "MoveDownAndModifySelection", // SelectNextLine,
212 "MoveUpAndModifySelection", // SelectPreviousLine,
213 "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
214 "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
215 "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
216 "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
217 "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
218 "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
219 "DeleteWordBackward", // DeleteStartOfWord,
220 "DeleteWordForward", // DeleteEndOfWord,
221
222 0, // SetTextDirectionDefault,
223 0, // SetTextDirectionLeftToRight,
224 0, // SetTextDirectionRightToLeft,
225
226 "ToggleBold", // ToggleBold,
227 "ToggleItalic", // ToggleItalic,
228 "ToggleUnderline", // ToggleUnderline,
229
230 0, // InspectElement,
231
232 "InsertNewline", // InsertParagraphSeparator
233 "InsertLineBreak", // InsertLineSeparator
234
235 "SelectAll", // SelectAll
236 0, // ReloadAndBypassCache,
237
238 "PasteAndMatchStyle", // PasteAndMatchStyle
239 "RemoveFormat", // RemoveFormat
240 "Strikethrough", // ToggleStrikethrough,
241 "Subscript", // ToggleSubscript
242 "Superscript", // ToggleSuperscript
243 "InsertUnorderedList", // InsertUnorderedList
244 "InsertOrderedList", // InsertOrderedList
245 "Indent", // Indent
246 "Outdent", // Outdent,
247
248 "AlignCenter", // AlignCenter,
249 "AlignJustified", // AlignJustified,
250 "AlignLeft", // AlignLeft,
251 "AlignRight", // AlignRight,
252
253 0, // StopScheduledPageRefresh,
254
255 0, // CopyImageUrlToClipboard,
256
257 0, // OpenLinkInThisWindow,
258
259 0 // WebActionCount
260};
261
262// Lookup the appropriate editor command to use for WebAction \a action
263const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
264{
265 if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
266 return editorCommandWebActions[action];
267 return 0;
268}
269
270static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
271{
272 unsigned result = 0;
273 if (actions & Qt::CopyAction)
274 result |= DragOperationCopy;
275 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
276 // hence it should be considered as "move"
277 if (actions & Qt::MoveAction)
278 result |= (DragOperationMove | DragOperationGeneric);
279 if (actions & Qt::LinkAction)
280 result |= DragOperationLink;
281 if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
282 result = DragOperationEvery;
283 return (DragOperation)result;
284}
285
286static inline Qt::DropAction dragOpToDropAction(unsigned actions)
287{
288 Qt::DropAction result = Qt::IgnoreAction;
289 if (actions & DragOperationCopy)
290 result = Qt::CopyAction;
291 else if (actions & DragOperationMove)
292 result = Qt::MoveAction;
293 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
294 // hence it should be considered as "move"
295 else if (actions & DragOperationGeneric)
296 result = Qt::MoveAction;
297 else if (actions & DragOperationLink)
298 result = Qt::LinkAction;
299 return result;
300}
301
302QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
303 : q(qq)
304 , page(0)
305#ifndef QT_NO_UNDOSTACK
306 , undoStack(0)
307#endif
308 , insideOpenCall(false)
309 , m_totalBytes(0)
310 , m_bytesReceived()
311 , clickCausedFocus(false)
312 , networkManager(0)
313 , forwardUnsupportedContent(false)
314 , smartInsertDeleteEnabled(true)
315 , selectTrailingWhitespaceEnabled(false)
316 , linkPolicy(QWebPage::DontDelegateLinks)
317 , viewportSize(QSize(0, 0))
318 , settings(0)
319 , useFixedLayout(false)
320 , pluginFactory(0)
321 , inspectorFrontend(0)
322 , inspector(0)
323 , inspectorIsInternalOnly(false)
324 , m_lastDropAction(Qt::IgnoreAction)
325{
326#if ENABLE(GEOLOCATION) || ENABLE(DEVICE_ORIENTATION)
327 bool useMock = QWebPagePrivate::drtRun;
328#endif
329
330 WebCore::initializeWebCoreQt();
331
332 Page::PageClients pageClients;
333 pageClients.chromeClient = new ChromeClientQt(q);
334 pageClients.contextMenuClient = new ContextMenuClientQt();
335 pageClients.editorClient = new EditorClientQt(q);
336 pageClients.dragClient = new DragClientQt(q);
337 pageClients.inspectorClient = new InspectorClientQt(q);
338 page = new Page(pageClients);
339#if ENABLE(GEOLOCATION)
340 if (useMock) {
341 // In case running in DumpRenderTree mode set the controller to mock provider.
342 GeolocationClientMock* mock = new GeolocationClientMock;
343 WebCore::provideGeolocationTo(page, mock);
344 mock->setController(WebCore::GeolocationController::from(page));
345 } else
346 WebCore::provideGeolocationTo(page, new GeolocationClientQt(q));
347#endif
348#if ENABLE(DEVICE_ORIENTATION)
349 if (useMock)
350 WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientMock);
351 else
352 WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientQt);
353 WebCore::provideDeviceMotionTo(page, new DeviceMotionClientQt);
354#endif
355#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
356 WebCore::provideNotification(page, NotificationPresenterClientQt::notificationPresenter());
357#endif
358
359 // By default each page is put into their own unique page group, which affects popup windows
360 // and visited links. Page groups (per process only) is a feature making it possible to use
361 // separate settings for each group, so that for instance an integrated browser/email reader
362 // can use different settings for displaying HTML pages and HTML email. To make QtWebKit work
363 // as expected out of the box, we use a default group similar to what other ports are doing.
364 page->setGroupName("Default Group");
365
366 page->addLayoutMilestones(DidFirstVisuallyNonEmptyLayout);
367
368 settings = new QWebSettings(page->settings());
369
370 history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList()));
371 memset(actions, 0, sizeof(actions));
372
373 PageGroup::setShouldTrackVisitedLinks(true);
374
375#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
376 NotificationPresenterClientQt::notificationPresenter()->addClient();
377#endif
378}
379
380QWebPagePrivate::~QWebPagePrivate()
381{
382#ifndef QT_NO_CONTEXTMENU
383 delete currentContextMenu.data();
384#endif
385#ifndef QT_NO_UNDOSTACK
386 delete undoStack;
387#endif
388 delete settings;
389 delete page;
390
391 if (inspector) {
392 // If the inspector is ours, delete it, otherwise just detach from it.
393 if (inspectorIsInternalOnly)
394 delete inspector;
395 else
396 inspector->setPage(0);
397 }
398
399#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
400 NotificationPresenterClientQt::notificationPresenter()->removeClient();
401#endif
402}
403
404WebCore::ViewportArguments QWebPagePrivate::viewportArguments()
405{
406 return page ? page->viewportArguments() : WebCore::ViewportArguments();
407}
408
409WebCore::Page* QWebPagePrivate::core(const QWebPage* page)
410{
411 return page->d->page;
412}
413
414QWebPagePrivate* QWebPagePrivate::priv(QWebPage* page)
415{
416 return page->d;
417}
418
419bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
420{
421 if (insideOpenCall
422 && frame == mainFrame.data())
423 return true;
424 return q->acceptNavigationRequest(frame, request, type);
425}
426
427void QWebPagePrivate::createMainFrame()
428{
429 if (!mainFrame) {
430 QWebFrameData frameData(page);
431 mainFrame = new QWebFrame(q, &frameData);
432
433 emit q->frameCreated(mainFrame.data());
434 }
435}
436
437static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
438{
439 switch (action) {
440 case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
441 case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
442 case WebCore::ContextMenuItemTagOpenLinkInThisWindow: return QWebPage::OpenLinkInThisWindow;
443 case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
444 case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
445 case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
446 case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
447 case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
448 case WebCore::ContextMenuItemTagCopyImageUrlToClipboard: return QWebPage::CopyImageUrlToClipboard;
449 case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
450 case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
451 case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
452 case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
453 case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
454 case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
455 case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
456 case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
457 case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
458 case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
459 case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
460 case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
461 case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
462 case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
463 case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll;
464#if ENABLE(INSPECTOR)
465 case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
466#endif
467 default: break;
468 }
469 return QWebPage::NoWebAction;
470}
471
472#ifndef QT_NO_CONTEXTMENU
473QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
474 const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
475{
476 if (!client || !webcoreMenu)
477 return 0;
478
479 QMenu* menu = new QMenu(client->ownerWidget());
480 for (int i = 0; i < items->count(); ++i) {
481 const ContextMenuItem &item = items->at(i);
482 switch (item.type()) {
483 case WebCore::CheckableActionType: /* fall through */
484 case WebCore::ActionType: {
485 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
486 QAction *a = q->action(action);
487 if (a) {
488 ContextMenuItem it(item);
489 page->contextMenuController()->checkOrEnableIfNeeded(it);
490 PlatformMenuItemDescription desc = it.releasePlatformDescription();
491 a->setEnabled(desc.enabled);
492 a->setChecked(desc.checked);
493 a->setCheckable(item.type() == WebCore::CheckableActionType);
494
495 menu->addAction(a);
496 visitedWebActions->setBit(action);
497 }
498 break;
499 }
500 case WebCore::SeparatorType:
501 menu->addSeparator();
502 break;
503 case WebCore::SubmenuType: {
504 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
505
506 bool anyEnabledAction = false;
507
508 QList<QAction *> actions = subMenu->actions();
509 for (int i = 0; i < actions.count(); ++i) {
510 if (actions.at(i)->isVisible())
511 anyEnabledAction |= actions.at(i)->isEnabled();
512 }
513
514 // don't show sub-menus with just disabled actions
515 if (anyEnabledAction) {
516 subMenu->setTitle(item.title());
517 menu->addAction(subMenu->menuAction());
518 } else
519 delete subMenu;
520 break;
521 }
522 }
523 }
524 return menu;
525}
526#endif // QT_NO_CONTEXTMENU
527
528#ifndef QT_NO_ACTION
529void QWebPagePrivate::_q_webActionTriggered(bool checked)
530{
531 QAction *a = qobject_cast<QAction *>(q->sender());
532 if (!a)
533 return;
534 QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
535 q->triggerAction(action, checked);
536}
537#endif // QT_NO_ACTION
538
539void QWebPagePrivate::_q_cleanupLeakMessages()
540{
541#ifndef NDEBUG
542 // Need this to make leak messages accurate.
543 memoryCache()->setCapacities(0, 0, 0);
544#endif
545}
546
547void QWebPagePrivate::updateAction(QWebPage::WebAction action)
548{
549#ifdef QT_NO_ACTION
550 Q_UNUSED(action)
551#else
552 QAction *a = actions[action];
553 if (!a || !mainFrame)
554 return;
555
556 WebCore::FrameLoader *loader = mainFrame.data()->d->frame->loader();
557 WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
558
559 bool enabled = a->isEnabled();
560 bool checked = a->isChecked();
561
562 switch (action) {
563 case QWebPage::Back:
564 enabled = page->canGoBackOrForward(-1);
565 break;
566 case QWebPage::Forward:
567 enabled = page->canGoBackOrForward(1);
568 break;
569 case QWebPage::Stop:
570 enabled = loader->isLoading();
571 break;
572 case QWebPage::Reload:
573 case QWebPage::ReloadAndBypassCache:
574 enabled = !loader->isLoading();
575 break;
576#ifndef QT_NO_UNDOSTACK
577 case QWebPage::Undo:
578 case QWebPage::Redo:
579 // those two are handled by QUndoStack
580 break;
581#endif // QT_NO_UNDOSTACK
582 case QWebPage::SelectAll: // editor command is always enabled
583 break;
584 case QWebPage::SetTextDirectionDefault:
585 case QWebPage::SetTextDirectionLeftToRight:
586 case QWebPage::SetTextDirectionRightToLeft:
587 enabled = editor->canEdit();
588 checked = false;
589 break;
590 default: {
591 // see if it's an editor command
592 const char* commandName = editorCommandForWebActions(action);
593
594 // if it's an editor command, let it's logic determine state
595 if (commandName) {
596 Editor::Command command = editor->command(commandName);
597 enabled = command.isEnabled();
598 if (enabled)
599 checked = command.state() != FalseTriState;
600 else
601 checked = false;
602 }
603 break;
604 }
605 }
606
607 a->setEnabled(enabled);
608
609 if (a->isCheckable())
610 a->setChecked(checked);
611#endif // QT_NO_ACTION
612}
613
614void QWebPagePrivate::updateNavigationActions()
615{
616 updateAction(QWebPage::Back);
617 updateAction(QWebPage::Forward);
618 updateAction(QWebPage::Stop);
619 updateAction(QWebPage::Reload);
620 updateAction(QWebPage::ReloadAndBypassCache);
621}
622
623void QWebPagePrivate::updateEditorActions()
624{
625 updateAction(QWebPage::Cut);
626 updateAction(QWebPage::Copy);
627 updateAction(QWebPage::Paste);
628 updateAction(QWebPage::MoveToNextChar);
629 updateAction(QWebPage::MoveToPreviousChar);
630 updateAction(QWebPage::MoveToNextWord);
631 updateAction(QWebPage::MoveToPreviousWord);
632 updateAction(QWebPage::MoveToNextLine);
633 updateAction(QWebPage::MoveToPreviousLine);
634 updateAction(QWebPage::MoveToStartOfLine);
635 updateAction(QWebPage::MoveToEndOfLine);
636 updateAction(QWebPage::MoveToStartOfBlock);
637 updateAction(QWebPage::MoveToEndOfBlock);
638 updateAction(QWebPage::MoveToStartOfDocument);
639 updateAction(QWebPage::MoveToEndOfDocument);
640 updateAction(QWebPage::SelectNextChar);
641 updateAction(QWebPage::SelectPreviousChar);
642 updateAction(QWebPage::SelectNextWord);
643 updateAction(QWebPage::SelectPreviousWord);
644 updateAction(QWebPage::SelectNextLine);
645 updateAction(QWebPage::SelectPreviousLine);
646 updateAction(QWebPage::SelectStartOfLine);
647 updateAction(QWebPage::SelectEndOfLine);
648 updateAction(QWebPage::SelectStartOfBlock);
649 updateAction(QWebPage::SelectEndOfBlock);
650 updateAction(QWebPage::SelectStartOfDocument);
651 updateAction(QWebPage::SelectEndOfDocument);
652 updateAction(QWebPage::DeleteStartOfWord);
653 updateAction(QWebPage::DeleteEndOfWord);
654 updateAction(QWebPage::SetTextDirectionDefault);
655 updateAction(QWebPage::SetTextDirectionLeftToRight);
656 updateAction(QWebPage::SetTextDirectionRightToLeft);
657 updateAction(QWebPage::ToggleBold);
658 updateAction(QWebPage::ToggleItalic);
659 updateAction(QWebPage::ToggleUnderline);
660 updateAction(QWebPage::InsertParagraphSeparator);
661 updateAction(QWebPage::InsertLineSeparator);
662 updateAction(QWebPage::PasteAndMatchStyle);
663 updateAction(QWebPage::RemoveFormat);
664 updateAction(QWebPage::ToggleStrikethrough);
665 updateAction(QWebPage::ToggleSubscript);
666 updateAction(QWebPage::ToggleSuperscript);
667 updateAction(QWebPage::InsertUnorderedList);
668 updateAction(QWebPage::InsertOrderedList);
669 updateAction(QWebPage::Indent);
670 updateAction(QWebPage::Outdent);
671 updateAction(QWebPage::AlignCenter);
672 updateAction(QWebPage::AlignJustified);
673 updateAction(QWebPage::AlignLeft);
674 updateAction(QWebPage::AlignRight);
675}
676
677void QWebPagePrivate::timerEvent(QTimerEvent *ev)
678{
679 int timerId = ev->timerId();
680 if (timerId == tripleClickTimer.timerId())
681 tripleClickTimer.stop();
682 else
683 q->timerEvent(ev);
684}
685
686template<class T>
687void QWebPagePrivate::mouseMoveEvent(T* ev)
688{
689 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
690 if (!frame->view())
691 return;
692
693 bool accepted = frame->eventHandler()->mouseMoved(convertMouseEvent(ev, 0));
694 ev->setAccepted(accepted);
695}
696
697template<class T>
698void QWebPagePrivate::mousePressEvent(T* ev)
699{
700 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
701 if (!frame->view())
702 return;
703
704 RefPtr<WebCore::Node> oldNode;
705 Frame* focusedFrame = page->focusController()->focusedFrame();
706 if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
707 oldNode = focusedDocument->focusedNode();
708
709 if (tripleClickTimer.isActive()
710 && (ev->pos() - tripleClick).manhattanLength()
711 < QApplication::startDragDistance()) {
712 mouseTripleClickEvent(ev);
713 return;
714 }
715
716 bool accepted = false;
717 adjustPointForClicking(ev);
718 PlatformMouseEvent mev = convertMouseEvent(ev, 1);
719 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
720 if (mev.button() != NoButton)
721 accepted = frame->eventHandler()->handleMousePressEvent(mev);
722 ev->setAccepted(accepted);
723
724 RefPtr<WebCore::Node> newNode;
725 focusedFrame = page->focusController()->focusedFrame();
726 if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
727 newNode = focusedDocument->focusedNode();
728
729 if (newNode && oldNode != newNode)
730 clickCausedFocus = true;
731}
732
733template<class T>
734void QWebPagePrivate::mouseDoubleClickEvent(T *ev)
735{
736 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
737 if (!frame->view())
738 return;
739
740 bool accepted = false;
741 PlatformMouseEvent mev = convertMouseEvent(ev, 2);
742 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
743 if (mev.button() != NoButton)
744 accepted = frame->eventHandler()->handleMousePressEvent(mev);
745 ev->setAccepted(accepted);
746
747 tripleClickTimer.start(QApplication::doubleClickInterval(), q);
748 tripleClick = QPointF(ev->pos()).toPoint();
749}
750
751template<class T>
752void QWebPagePrivate::mouseTripleClickEvent(T *ev)
753{
754 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
755 if (!frame->view())
756 return;
757
758 bool accepted = false;
759 PlatformMouseEvent mev = convertMouseEvent(ev, 3);
760 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
761 if (mev.button() != NoButton)
762 accepted = frame->eventHandler()->handleMousePressEvent(mev);
763 ev->setAccepted(accepted);
764}
765
766template<class T>
767void QWebPagePrivate::mouseReleaseEvent(T *ev)
768{
769 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
770 if (!frame->view())
771 return;
772
773 bool accepted = false;
774 adjustPointForClicking(ev);
775 PlatformMouseEvent mev = convertMouseEvent(ev, 0);
776 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
777 if (mev.button() != NoButton)
778 accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
779 ev->setAccepted(accepted);
780
781 handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint());
782}
783
784void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos)
785{
786 Frame* frame = page->focusController()->focusedFrame();
787 if (!frame)
788 return;
789
790 if (client && client->inputMethodEnabled()
791 && frame->document()->focusedNode()
792 && button == Qt::LeftButton && qApp->autoSipEnabled()) {
793 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
794 client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
795 if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
796 HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false);
797 if (result.isContentEditable()) {
798 QEvent event(QEvent::RequestSoftwareInputPanel);
799 QApplication::sendEvent(client->ownerWidget(), &event);
800 }
801 }
802 }
803
804 clickCausedFocus = false;
805}
806
807#ifndef QT_NO_CONTEXTMENU
808void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
809{
810 QMenu *menu = q->createStandardContextMenu();
811 if (menu) {
812 menu->exec(globalPos);
813 delete menu;
814 }
815}
816#endif // QT_NO_CONTEXTMENU
817
818/*!
819 \since 4.5
820 This function creates the standard context menu which is shown when
821 the user clicks on the web page with the right mouse button. It is
822 called from the default contextMenuEvent() handler. The popup menu's
823 ownership is transferred to the caller.
824 */
825QMenu *QWebPage::createStandardContextMenu()
826{
827#ifndef QT_NO_CONTEXTMENU
828 QMenu* menu = d->currentContextMenu.data();
829 d->currentContextMenu = 0;
830 return menu;
831#else
832 return 0;
833#endif
834}
835
836#ifndef QT_NO_WHEELEVENT
837template<class T>
838void QWebPagePrivate::wheelEvent(T *ev)
839{
840 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
841 if (!frame->view())
842 return;
843
844 PlatformWheelEvent pev = convertWheelEvent(ev);
845 bool accepted = frame->eventHandler()->handleWheelEvent(pev);
846 ev->setAccepted(accepted);
847}
848#endif // QT_NO_WHEELEVENT
849
850#ifndef QT_NO_SHORTCUT
851QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
852{
853 static struct {
854 QKeySequence::StandardKey standardKey;
855 QWebPage::WebAction action;
856 } editorActions[] = {
857 { QKeySequence::Cut, QWebPage::Cut },
858 { QKeySequence::Copy, QWebPage::Copy },
859 { QKeySequence::Paste, QWebPage::Paste },
860 { QKeySequence::Undo, QWebPage::Undo },
861 { QKeySequence::Redo, QWebPage::Redo },
862 { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
863 { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
864 { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
865 { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
866 { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
867 { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
868 { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
869 { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
870 { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
871 { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
872 { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
873 { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
874 { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
875 { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
876 { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
877 { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
878 { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
879 { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
880 { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
881 { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
882 { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
883 { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock },
884 { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
885 { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
886 { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
887 { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
888 { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
889 { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
890 { QKeySequence::SelectAll, QWebPage::SelectAll },
891 { QKeySequence::UnknownKey, QWebPage::NoWebAction }
892 };
893
894 for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
895 if (event == editorActions[i].standardKey)
896 return editorActions[i].action;
897
898 return QWebPage::NoWebAction;
899}
900#endif // QT_NO_SHORTCUT
901
902void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
903{
904 bool handled = false;
905 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
906 // we forward the key event to WebCore first to handle potential DOM
907 // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
908 // to trigger editor commands via triggerAction().
909 if (!handled)
910 handled = frame->eventHandler()->keyEvent(ev);
911 if (!handled) {
912 handled = true;
913 if (!handleScrolling(ev, frame)) {
914 switch (ev->key()) {
915 case Qt::Key_Back:
916 q->triggerAction(QWebPage::Back);
917 break;
918 case Qt::Key_Forward:
919 q->triggerAction(QWebPage::Forward);
920 break;
921 case Qt::Key_Stop:
922 q->triggerAction(QWebPage::Stop);
923 break;
924 case Qt::Key_Refresh:
925 q->triggerAction(QWebPage::Reload);
926 break;
927 case Qt::Key_Backspace:
928 if (ev->modifiers() == Qt::ShiftModifier)
929 q->triggerAction(QWebPage::Forward);
930 else
931 q->triggerAction(QWebPage::Back);
932 break;
933 default:
934 handled = false;
935 break;
936 }
937 }
938 }
939
940 ev->setAccepted(handled);
941}
942
943void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
944{
945 if (ev->isAutoRepeat()) {
946 ev->setAccepted(true);
947 return;
948 }
949
950 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
951 bool handled = frame->eventHandler()->keyEvent(ev);
952 ev->setAccepted(handled);
953}
954
955void QWebPagePrivate::focusInEvent(QFocusEvent*)
956{
957 FocusController *focusController = page->focusController();
958 focusController->setActive(true);
959 focusController->setFocused(true);
960 if (!focusController->focusedFrame())
961 focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame.data()));
962}
963
964void QWebPagePrivate::focusOutEvent(QFocusEvent*)
965{
966 // only set the focused frame inactive so that we stop painting the caret
967 // and the focus frame. But don't tell the focus controller so that upon
968 // focusInEvent() we can re-activate the frame.
969 FocusController *focusController = page->focusController();
970 // Call setFocused first so that window.onblur doesn't get called twice
971 focusController->setFocused(false);
972 focusController->setActive(false);
973}
974
975template<class T>
976void QWebPagePrivate::dragEnterEvent(T* ev)
977{
978#ifndef QT_NO_DRAGANDDROP
979 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
980 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
981 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData).operation);
982 ev->setDropAction(action);
983 ev->acceptProposedAction();
984#endif
985}
986
987template<class T>
988void QWebPagePrivate::dragLeaveEvent(T *ev)
989{
990#ifndef QT_NO_DRAGANDDROP
991 DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
992 page->dragController()->dragExited(&dragData);
993 ev->accept();
994#endif
995}
996
997template<class T>
998void QWebPagePrivate::dragMoveEvent(T *ev)
999{
1000#ifndef QT_NO_DRAGANDDROP
1001 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1002 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1003 m_lastDropAction = dragOpToDropAction(page->dragController()->dragUpdated(&dragData).operation);
1004 ev->setDropAction(m_lastDropAction);
1005 if (m_lastDropAction != Qt::IgnoreAction)
1006 ev->accept();
1007#endif
1008}
1009
1010template<class T>
1011void QWebPagePrivate::dropEvent(T *ev)
1012{
1013#ifndef QT_NO_DRAGANDDROP
1014 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1015 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1016 if (page->dragController()->performDrag(&dragData)) {
1017 ev->setDropAction(m_lastDropAction);
1018 ev->accept();
1019 }
1020#endif
1021}
1022
1023void QWebPagePrivate::leaveEvent(QEvent*)
1024{
1025 // Fake a mouse move event just outside of the widget, since all
1026 // the interesting mouse-out behavior like invalidating scrollbars
1027 // is handled by the WebKit event handler's mouseMoved function.
1028 QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1029 mouseMoveEvent(&fakeEvent);
1030}
1031
1032/*!
1033 \property QWebPage::palette
1034 \brief the page's palette
1035
1036 The base brush of the palette is used to draw the background of the main frame.
1037
1038 By default, this property contains the application's default palette.
1039*/
1040void QWebPage::setPalette(const QPalette &pal)
1041{
1042 d->palette = pal;
1043 if (!d->mainFrame || !d->mainFrame.data()->d->frame->view())
1044 return;
1045
1046 QBrush brush = pal.brush(QPalette::Base);
1047 QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1048 QWebFramePrivate::core(d->mainFrame.data())->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1049}
1050
1051QPalette QWebPage::palette() const
1052{
1053 return d->palette;
1054}
1055
1056void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1057{
1058 WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1059 WebCore::Editor *editor = frame->editor();
1060
1061 if (!editor->canEdit()) {
1062 ev->ignore();
1063 return;
1064 }
1065
1066 Node* node = 0;
1067 if (frame->selection()->rootEditableElement())
1068 node = frame->selection()->rootEditableElement()->shadowAncestorNode();
1069
1070 Vector<CompositionUnderline> underlines;
1071 bool hasSelection = false;
1072
1073 for (int i = 0; i < ev->attributes().size(); ++i) {
1074 const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1075 switch (a.type) {
1076 case QInputMethodEvent::TextFormat: {
1077 QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1078 QColor qcolor = textCharFormat.underlineColor();
1079 underlines.append(CompositionUnderline(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)), Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1080 break;
1081 }
1082 case QInputMethodEvent::Cursor: {
1083 frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1084 if (a.length > 0) {
1085 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1086 if (caretRenderer) {
1087 QColor qcolor = a.value.value<QColor>();
1088 caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1089 }
1090 }
1091 break;
1092 }
1093 case QInputMethodEvent::Selection: {
1094 hasSelection = true;
1095 // A selection in the inputMethodEvent is always reflected in the visible text
1096 if (node) {
1097 if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
1098 textControl->setSelectionRange(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1099 }
1100
1101 if (!ev->preeditString().isEmpty())
1102 editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1103 else {
1104 // If we are in the middle of a composition, an empty pre-edit string and a selection of zero
1105 // cancels the current composition
1106 if (editor->hasComposition() && (a.start + a.length == 0))
1107 editor->setComposition(QString(), underlines, 0, 0);
1108 }
1109 break;
1110 }
1111 default:
1112 break;
1113 }
1114 }
1115
1116 if (node && ev->replacementLength() > 0) {
1117 int cursorPos = frame->selection()->extent().offsetInContainerNode();
1118 int start = cursorPos + ev->replacementStart();
1119 if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
1120 textControl->setSelectionRange(start, start + ev->replacementLength());
1121 // Commit regardless of whether commitString is empty, to get rid of selection.
1122 editor->confirmComposition(ev->commitString());
1123 } else if (!ev->commitString().isEmpty()) {
1124 if (editor->hasComposition())
1125 editor->confirmComposition(ev->commitString());
1126 else
1127 editor->insertText(ev->commitString(), 0);
1128 } else if (!hasSelection && !ev->preeditString().isEmpty())
1129 editor->setComposition(ev->preeditString(), underlines, 0, 0);
1130 else if (ev->preeditString().isEmpty() && editor->hasComposition())
1131 editor->confirmComposition(String());
1132
1133 ev->accept();
1134}
1135
1136#ifndef QT_NO_PROPERTIES
1137typedef struct {
1138 const char* name;
1139 double deferredRepaintDelay;
1140 double initialDeferredRepaintDelayDuringLoading;
1141 double maxDeferredRepaintDelayDuringLoading;
1142 double deferredRepaintDelayIncrementDuringLoading;
1143} QRepaintThrottlingPreset;
1144
1145void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event)
1146{
1147 if (event->propertyName() == "_q_viewMode") {
1148 page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString()));
1149 } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") {
1150 int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt();
1151 q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize);
1152 } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") {
1153 double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble();
1154 q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
1155 } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") {
1156 double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble();
1157 FrameView::setRepaintThrottlingDeferredRepaintDelay(p);
1158 } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") {
1159 double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble();
1160 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p);
1161 } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") {
1162 double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble();
1163 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p);
1164 } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") {
1165 double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble();
1166 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p);
1167 } else if (event->propertyName() == "_q_RepaintThrottlingPreset") {
1168 static const QRepaintThrottlingPreset presets[] = {
1169 { "NoThrottling", 0, 0, 0, 0 },
1170 { "Legacy", 0.025, 0, 2.5, 0.5 },
1171 { "Minimal", 0.01, 0, 1, 0.2 },
1172 { "Medium", 0.025, 1, 5, 0.5 },
1173 { "Heavy", 0.1, 2, 10, 1 }
1174 };
1175
1176 QString p = q->property("_q_RepaintThrottlingPreset").toString();
1177 for (size_t i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) {
1178 if (p == QLatin1String(presets[i].name)) {
1179 FrameView::setRepaintThrottlingDeferredRepaintDelay(
1180 presets[i].deferredRepaintDelay);
1181 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(
1182 presets[i].initialDeferredRepaintDelayDuringLoading);
1183 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(
1184 presets[i].maxDeferredRepaintDelayDuringLoading);
1185 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(
1186 presets[i].deferredRepaintDelayIncrementDuringLoading);
1187 break;
1188 }
1189 }
1190 }
1191 else if (event->propertyName() == "_q_webInspectorServerPort") {
1192 InspectorServerQt* inspectorServer = InspectorServerQt::server();
1193 inspectorServer->listen(inspectorServerPort());
1194 } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") {
1195 double interval = q->property("_q_deadDecodedDataDeletionInterval").toDouble();
1196 memoryCache()->setDeadDecodedDataDeletionInterval(interval);
1197 }
1198}
1199#endif
1200
1201void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1202{
1203 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1204 WebCore::Editor* editor = frame->editor();
1205 if (editor->canEdit()) {
1206 if (event->modifiers() == Qt::NoModifier
1207 || event->modifiers() == Qt::ShiftModifier
1208 || event->modifiers() == Qt::KeypadModifier) {
1209 if (event->key() < Qt::Key_Escape) {
1210 event->accept();
1211 } else {
1212 switch (event->key()) {
1213 case Qt::Key_Return:
1214 case Qt::Key_Enter:
1215 case Qt::Key_Delete:
1216 case Qt::Key_Home:
1217 case Qt::Key_End:
1218 case Qt::Key_Backspace:
1219 case Qt::Key_Left:
1220 case Qt::Key_Right:
1221 case Qt::Key_Up:
1222 case Qt::Key_Down:
1223 case Qt::Key_Tab:
1224 event->accept();
1225 default:
1226 break;
1227 }
1228 }
1229 }
1230#ifndef QT_NO_SHORTCUT
1231 else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1232 event->accept();
1233#endif
1234 }
1235}
1236
1237bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1238{
1239 ScrollDirection direction;
1240 ScrollGranularity granularity;
1241
1242#ifndef QT_NO_SHORTCUT
1243 if (ev == QKeySequence::MoveToNextPage
1244 || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1245 granularity = ScrollByPage;
1246 direction = ScrollDown;
1247 } else if (ev == QKeySequence::MoveToPreviousPage
1248 || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1249 granularity = ScrollByPage;
1250 direction = ScrollUp;
1251 } else
1252#endif // QT_NO_SHORTCUT
1253 if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1254 || ev->key() == Qt::Key_Home) {
1255 granularity = ScrollByDocument;
1256 direction = ScrollUp;
1257 } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1258 || ev->key() == Qt::Key_End) {
1259 granularity = ScrollByDocument;
1260 direction = ScrollDown;
1261 } else {
1262 switch (ev->key()) {
1263 case Qt::Key_Up:
1264 granularity = ScrollByLine;
1265 direction = ScrollUp;
1266 break;
1267 case Qt::Key_Down:
1268 granularity = ScrollByLine;
1269 direction = ScrollDown;
1270 break;
1271 case Qt::Key_Left:
1272 granularity = ScrollByLine;
1273 direction = ScrollLeft;
1274 break;
1275 case Qt::Key_Right:
1276 granularity = ScrollByLine;
1277 direction = ScrollRight;
1278 break;
1279 default:
1280 return false;
1281 }
1282 }
1283
1284 return frame->eventHandler()->scrollRecursively(direction, granularity);
1285}
1286
1287void QWebPagePrivate::adjustPointForClicking(QMouseEvent*)
1288{
1289 notImplemented();
1290}
1291
1292#if !defined(QT_NO_GRAPHICSVIEW)
1293void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev)
1294{
1295 QtPlatformPlugin platformPlugin;
1296 OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier();
1297 if (!touchModifier)
1298 return;
1299
1300 unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up);
1301 unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right);
1302 unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down);
1303 unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left);
1304
1305 touchModifier = nullptr;
1306
1307 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding)
1308 return;
1309
1310 Document* startingDocument = page->mainFrame()->document();
1311 if (!startingDocument)
1312 return;
1313
1314 IntPoint originalPoint(QPointF(ev->pos()).toPoint());
1315 TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding);
1316 IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument);
1317 if (adjustedPoint == IntPoint::zero())
1318 return;
1319
1320 ev->setPos(QPointF(adjustedPoint));
1321}
1322#endif
1323
1324bool QWebPagePrivate::touchEvent(QTouchEvent* event)
1325{
1326#if ENABLE(TOUCH_EVENTS)
1327 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
1328 if (!frame->view())
1329 return false;
1330
1331 // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events
1332 event->setAccepted(true);
1333
1334 // Return whether the default action was cancelled in the JS event handler
1335 return frame->eventHandler()->handleTouchEvent(convertTouchEvent(event));
1336#else
1337 event->ignore();
1338 return false;
1339#endif
1340}
1341
1342bool QWebPagePrivate::gestureEvent(QGestureEvent* event)
1343{
1344#if ENABLE(GESTURE_EVENTS)
1345 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
1346 if (!frame->view())
1347 return false;
1348
1349 // QGestureEvents can contain updates for multiple gestures.
1350 bool handled = false;
1351 QGesture* gesture = event->gesture(Qt::TapGesture);
1352 // Beware that gestures send by DumpRenderTree will have state Qt::NoGesture,
1353 // due to not originating from a GestureRecognizer.
1354 if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
1355 frame->eventHandler()->handleGestureEvent(convertGesture(event, gesture));
1356 event->setAccepted(true);
1357 handled = true;
1358 }
1359 gesture = event->gesture(Qt::TapAndHoldGesture);
1360 if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
1361 frame->eventHandler()->sendContextMenuEventForGesture(convertGesture(event, gesture));
1362 event->setAccepted(true);
1363 handled = true;
1364 }
1365
1366 return handled;
1367#else
1368 event->ignore();
1369 return false;
1370#endif
1371}
1372
1373/*!
1374 This method is used by the input method to query a set of properties of the page
1375 to be able to support complex input method operations as support for surrounding
1376 text and reconversions.
1377
1378 \a property specifies which property is queried.
1379
1380 \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1381*/
1382QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1383{
1384 Frame* frame = d->page->focusController()->focusedFrame();
1385 if (!frame)
1386 return QVariant();
1387
1388 WebCore::Editor* editor = frame->editor();
1389
1390 RenderObject* renderer = 0;
1391 RenderTextControl* renderTextControl = 0;
1392
1393 if (frame->selection()->rootEditableElement())
1394 renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1395
1396 if (renderer && renderer->isTextControl())
1397 renderTextControl = toRenderTextControl(renderer);
1398
1399 switch (property) {
1400 case Qt::ImMicroFocus: {
1401 WebCore::FrameView* view = frame->view();
1402 if (view && view->needsLayout()) {
1403 // We can't access absoluteCaretBounds() while the view needs to layout.
1404 return QVariant();
1405 }
1406 return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds()));
1407 }
1408 case Qt::ImFont: {
1409 if (renderTextControl) {
1410 RenderStyle* renderStyle = renderTextControl->style();
1411 return QVariant(QFont(renderStyle->font().syntheticFont()));
1412 }
1413 return QVariant(QFont());
1414 }
1415 case Qt::ImCursorPosition: {
1416 if (editor->hasComposition())
1417 return QVariant(frame->selection()->end().offsetInContainerNode());
1418 return QVariant(frame->selection()->extent().offsetInContainerNode());
1419 }
1420 case Qt::ImSurroundingText: {
1421 if (renderTextControl && renderTextControl->textFormControlElement()) {
1422 QString text = renderTextControl->textFormControlElement()->value();
1423 RefPtr<Range> range = editor->compositionRange();
1424 if (range)
1425 text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1426 return QVariant(text);
1427 }
1428 return QVariant();
1429 }
1430 case Qt::ImCurrentSelection: {
1431 if (!editor->hasComposition() && renderTextControl && renderTextControl->textFormControlElement()) {
1432 int start = frame->selection()->start().offsetInContainerNode();
1433 int end = frame->selection()->end().offsetInContainerNode();
1434 if (end > start)
1435 return QVariant(QString(renderTextControl->textFormControlElement()->value()).mid(start, end - start));
1436 }
1437 return QVariant();
1438
1439 }
1440 case Qt::ImAnchorPosition: {
1441 if (editor->hasComposition())
1442 return QVariant(frame->selection()->start().offsetInContainerNode());
1443 return QVariant(frame->selection()->base().offsetInContainerNode());
1444 }
1445 case Qt::ImMaximumTextLength: {
1446 if (frame->selection()->isContentEditable()) {
1447 if (frame->document() && frame->document()->focusedNode()) {
1448 if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1449 HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1450 return QVariant(inputElement->maxLength());
1451 }
1452 }
1453 return QVariant(HTMLInputElement::maximumLength);
1454 }
1455 return QVariant(0);
1456 }
1457 default:
1458 return QVariant();
1459 }
1460}
1461
1462/*!
1463 \internal
1464*/
1465void QWebPagePrivate::setInspector(QWebInspector* insp)
1466{
1467 if (inspector)
1468 inspector->d->setFrontend(0);
1469
1470 inspector = insp;
1471
1472 // Give inspector frontend web view if previously created
1473 if (inspector && inspectorFrontend)
1474 inspector->d->setFrontend(inspectorFrontend);
1475}
1476
1477/*!
1478 \internal
1479 Returns the inspector and creates it if it wasn't created yet.
1480 The instance created here will not be available through QWebPage's API.
1481*/
1482QWebInspector* QWebPagePrivate::getOrCreateInspector()
1483{
1484#if ENABLE(INSPECTOR)
1485 if (!inspector) {
1486 QWebInspector* insp = new QWebInspector;
1487 insp->setPage(q);
1488 inspectorIsInternalOnly = true;
1489
1490 Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1491 }
1492#endif
1493 return inspector;
1494}
1495
1496/*! \internal */
1497InspectorController* QWebPagePrivate::inspectorController()
1498{
1499#if ENABLE(INSPECTOR)
1500 return page->inspectorController();
1501#else
1502 return 0;
1503#endif
1504}
1505
1506quint16 QWebPagePrivate::inspectorServerPort()
1507{
1508#if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES)
1509 if (q && q->property("_q_webInspectorServerPort").isValid())
1510 return q->property("_q_webInspectorServerPort").toInt();
1511#endif
1512 return 0;
1513}
1514
1515static bool hasMouseListener(Element* element)
1516{
1517 ASSERT(element);
1518 return element->hasEventListeners(eventNames().clickEvent)
1519 || element->hasEventListeners(eventNames().mousedownEvent)
1520 || element->hasEventListeners(eventNames().mouseupEvent);
1521}
1522
1523static bool isClickableElement(Element* element, RefPtr<NodeList> list)
1524{
1525 ASSERT(element);
1526 bool isClickable = hasMouseListener(element);
1527 if (!isClickable && list) {
1528 Element* parent = element->parentElement();
1529 unsigned count = list->length();
1530 for (unsigned i = 0; i < count && parent; i++) {
1531 if (list->item(i) != parent)
1532 continue;
1533
1534 isClickable = hasMouseListener(parent);
1535 if (isClickable)
1536 break;
1537
1538 parent = parent->parentElement();
1539 }
1540 }
1541
1542 ExceptionCode ec = 0;
1543 return isClickable
1544 || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec)
1545 || CSSComputedStyleDeclaration::create(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer";
1546}
1547
1548static bool isValidFrameOwner(Element* element)
1549{
1550 ASSERT(element);
1551 return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame();
1552}
1553
1554static Element* nodeToElement(Node* node)
1555{
1556 if (node && node->isElementNode())
1557 return static_cast<Element*>(node);
1558 return 0;
1559}
1560
1561QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
1562 : m_topPadding(topPadding)
1563 , m_rightPadding(rightPadding)
1564 , m_bottomPadding(bottomPadding)
1565 , m_leftPadding(leftPadding)
1566{
1567}
1568
1569IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const
1570{
1571 if (!document)
1572 return IntPoint();
1573
1574 int x = touchPoint.x();
1575 int y = touchPoint.y();
1576
1577 RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false /*ignoreClipping*/, false /*allowShadowContent*/);
1578 if (!intersectedNodes)
1579 return IntPoint();
1580
1581 Element* closestClickableElement = 0;
1582 IntRect largestIntersectionRect;
1583 FrameView* view = document->frame()->view();
1584
1585 // Touch rect in contents coordinates.
1586 IntRect touchRect(HitTestLocation::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding));
1587
1588 // Iterate over the list of nodes hit looking for the one whose bounding area
1589 // has largest intersection with the touch area (point + padding).
1590 for (unsigned i = 0; i < intersectedNodes->length(); i++) {
1591 Node* currentNode = intersectedNodes->item(i);
1592
1593 Element* currentElement = nodeToElement(currentNode);
1594 if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement)))
1595 continue;
1596
1597 IntRect currentElementBoundingRect = currentElement->pixelSnappedBoundingBox();
1598 currentElementBoundingRect.intersect(touchRect);
1599
1600 if (currentElementBoundingRect.isEmpty())
1601 continue;
1602
1603 int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height();
1604 int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height();
1605 if (currentIntersectionRectArea > largestIntersectionRectArea) {
1606 closestClickableElement = currentElement;
1607 largestIntersectionRect = currentElementBoundingRect;
1608 }
1609 }
1610
1611 if (largestIntersectionRect.isEmpty())
1612 return IntPoint();
1613
1614 // Handle the case when user taps a inner frame. It is done in three steps:
1615 // 1) Transform the original touch point to the inner document coordinates;
1616 // 1) Call nodesFromRect for the inner document in case;
1617 // 3) Re-add the inner frame offset (location) before passing the new clicking
1618 // position to WebCore.
1619 if (closestClickableElement->isFrameOwnerElement()) {
1620 // Adjust client coordinates' origin to be top left of inner frame viewport.
1621 PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect();
1622 IntPoint newTouchPoint = touchPoint;
1623 IntSize offset = IntSize(rect->left(), rect->top());
1624 newTouchPoint -= offset;
1625
1626 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement);
1627 Document* childDocument = owner->contentFrame()->document();
1628 return findCandidatePointForTouch(newTouchPoint, childDocument);
1629 }
1630 return view->contentsToWindow(largestIntersectionRect).center();
1631}
1632
1633/*!
1634 \enum QWebPage::FindFlag
1635
1636 This enum describes the options available to the findText() function. The options
1637 can be OR-ed together from the following list:
1638
1639 \value FindBackward Searches backwards instead of forwards.
1640 \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1641 changes the behaviour to a case sensitive find operation.
1642 \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1643 was reached and the text was not found.
1644 \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1645 (This value was introduced in 4.6.)
1646*/
1647
1648/*!
1649 \enum QWebPage::LinkDelegationPolicy
1650
1651 This enum defines the delegation policies a webpage can have when activating links and emitting
1652 the linkClicked() signal.
1653
1654 \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1655 \value DelegateExternalLinks When activating links that point to documents not stored on the
1656 local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1657 \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1658
1659 \sa QWebPage::linkDelegationPolicy
1660*/
1661
1662/*!
1663 \enum QWebPage::NavigationType
1664
1665 This enum describes the types of navigation available when browsing through hyperlinked
1666 documents.
1667
1668 \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1669 \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1670 \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1671 \value NavigationTypeReload The user activated the reload action.
1672 \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1673 \value NavigationTypeOther A navigation to another document using a method not listed above.
1674
1675 \sa acceptNavigationRequest()
1676*/
1677
1678/*!
1679 \enum QWebPage::WebAction
1680
1681 This enum describes the types of action which can be performed on the web page.
1682
1683 Actions only have an effect when they are applicable. The availability of
1684 actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1685 action returned by action().
1686
1687 One method of enabling the text editing, cursor movement, and text selection actions
1688 is by setting \l contentEditable to true.
1689
1690 \value NoWebAction No action is triggered.
1691 \value OpenLink Open the current link.
1692 \value OpenLinkInNewWindow Open the current link in a new window.
1693 \value OpenLinkInThisWindow Open the current link without opening a new window. Used on links that would default to opening in another frame or a new window. (Added in Qt 5.0)
1694 \value OpenFrameInNewWindow Replicate the current frame in a new window.
1695 \value DownloadLinkToDisk Download the current link to the disk.
1696 \value CopyLinkToClipboard Copy the current link to the clipboard.
1697 \value OpenImageInNewWindow Open the highlighted image in a new window.
1698 \value DownloadImageToDisk Download the highlighted image to the disk.
1699 \value CopyImageToClipboard Copy the highlighted image to the clipboard. (Added in Qt 4.8)
1700 \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1701 \value Back Navigate back in the history of navigated links.
1702 \value Forward Navigate forward in the history of navigated links.
1703 \value Stop Stop loading the current page.
1704 \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests. (Added in Qt 4.7)
1705 \value Reload Reload the current page.
1706 \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1707 \value Cut Cut the content currently selected into the clipboard.
1708 \value Copy Copy the content currently selected into the clipboard.
1709 \value Paste Paste content from the clipboard.
1710 \value Undo Undo the last editing action.
1711 \value Redo Redo the last editing action.
1712 \value MoveToNextChar Move the cursor to the next character.
1713 \value MoveToPreviousChar Move the cursor to the previous character.
1714 \value MoveToNextWord Move the cursor to the next word.
1715 \value MoveToPreviousWord Move the cursor to the previous word.
1716 \value MoveToNextLine Move the cursor to the next line.
1717 \value MoveToPreviousLine Move the cursor to the previous line.
1718 \value MoveToStartOfLine Move the cursor to the start of the line.
1719 \value MoveToEndOfLine Move the cursor to the end of the line.
1720 \value MoveToStartOfBlock Move the cursor to the start of the block.
1721 \value MoveToEndOfBlock Move the cursor to the end of the block.
1722 \value MoveToStartOfDocument Move the cursor to the start of the document.
1723 \value MoveToEndOfDocument Move the cursor to the end of the document.
1724 \value SelectNextChar Select to the next character.
1725 \value SelectPreviousChar Select to the previous character.
1726 \value SelectNextWord Select to the next word.
1727 \value SelectPreviousWord Select to the previous word.
1728 \value SelectNextLine Select to the next line.
1729 \value SelectPreviousLine Select to the previous line.
1730 \value SelectStartOfLine Select to the start of the line.
1731 \value SelectEndOfLine Select to the end of the line.
1732 \value SelectStartOfBlock Select to the start of the block.
1733 \value SelectEndOfBlock Select to the end of the block.
1734 \value SelectStartOfDocument Select to the start of the document.
1735 \value SelectEndOfDocument Select to the end of the document.
1736 \value DeleteStartOfWord Delete to the start of the word.
1737 \value DeleteEndOfWord Delete to the end of the word.
1738 \value SetTextDirectionDefault Set the text direction to the default direction.
1739 \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1740 \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1741 \value ToggleBold Toggle the formatting between bold and normal weight.
1742 \value ToggleItalic Toggle the formatting between italic and normal style.
1743 \value ToggleUnderline Toggle underlining.
1744 \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1745 \value InsertParagraphSeparator Insert a new paragraph.
1746 \value InsertLineSeparator Insert a new line.
1747 \value SelectAll Selects all content.
1748 \value PasteAndMatchStyle Paste content from the clipboard with current style. (Added in Qt 4.6)
1749 \value RemoveFormat Removes formatting and style. (Added in Qt 4.6)
1750 \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style. (Added in Qt 4.6)
1751 \value ToggleSubscript Toggle the formatting between subscript and baseline. (Added in Qt 4.6)
1752 \value ToggleSuperscript Toggle the formatting between supercript and baseline. (Added in Qt 4.6)
1753 \value InsertUnorderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1754 \value InsertOrderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1755 \value Indent Increases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1756 \value Outdent Decreases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1757 \value AlignCenter Applies center alignment to content. (Added in Qt 4.6)
1758 \value AlignJustified Applies full justification to content. (Added in Qt 4.6)
1759 \value AlignLeft Applies left justification to content. (Added in Qt 4.6)
1760 \value AlignRight Applies right justification to content. (Added in Qt 4.6)
1761
1762
1763 \omitvalue WebActionCount
1764
1765*/
1766
1767/*!
1768 \enum QWebPage::WebWindowType
1769
1770 This enum describes the types of window that can be created by the createWindow() function.
1771
1772 \value WebBrowserWindow The window is a regular web browser window.
1773 \value WebModalDialog The window acts as modal dialog.
1774*/
1775
1776
1777/*!
1778 \class QWebPage::ViewportAttributes
1779 \since 4.7
1780 \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
1781
1782 QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
1783 initial scale factor with limits, plus information about whether a user should be able
1784 to scale the contents in the viewport or not, ie. by zooming.
1785
1786 ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
1787 at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
1788
1789 All values might not be set, as such when dealing with the hints, the developer needs to
1790 check whether the values are valid. Negative values denote an invalid qreal value.
1791
1792 \inmodule QtWebKit
1793*/
1794
1795/*!
1796 Constructs an empty QWebPage::ViewportAttributes.
1797*/
1798QWebPage::ViewportAttributes::ViewportAttributes()
1799 : d(0)
1800 , m_initialScaleFactor(-1.0)
1801 , m_minimumScaleFactor(-1.0)
1802 , m_maximumScaleFactor(-1.0)
1803 , m_devicePixelRatio(-1.0)
1804 , m_isUserScalable(true)
1805 , m_isValid(false)
1806{
1807
1808}
1809
1810/*!
1811 Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
1812*/
1813QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
1814 : d(other.d)
1815 , m_initialScaleFactor(other.m_initialScaleFactor)
1816 , m_minimumScaleFactor(other.m_minimumScaleFactor)
1817 , m_maximumScaleFactor(other.m_maximumScaleFactor)
1818 , m_devicePixelRatio(other.m_devicePixelRatio)
1819 , m_isUserScalable(other.m_isUserScalable)
1820 , m_isValid(other.m_isValid)
1821 , m_size(other.m_size)
1822{
1823
1824}
1825
1826/*!
1827 Destroys the QWebPage::ViewportAttributes.
1828*/
1829QWebPage::ViewportAttributes::~ViewportAttributes()
1830{
1831
1832}
1833
1834/*!
1835 Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
1836 reference to this.
1837*/
1838QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
1839{
1840 if (this != &other) {
1841 d = other.d;
1842 m_initialScaleFactor = other.m_initialScaleFactor;
1843 m_minimumScaleFactor = other.m_minimumScaleFactor;
1844 m_maximumScaleFactor = other.m_maximumScaleFactor;
1845 m_isUserScalable = other.m_isUserScalable;
1846 m_isValid = other.m_isValid;
1847 m_size = other.m_size;
1848 }
1849
1850 return *this;
1851}
1852
1853/*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
1854 Returns whether this is a valid ViewportAttributes or not.
1855
1856 An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
1857 true for the boolean isUserScalable.
1858*/
1859
1860/*! \fn inline QSize QWebPage::ViewportAttributes::size() const
1861 Returns the size of the viewport.
1862*/
1863
1864/*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
1865 Returns the initial scale of the viewport as a multiplier.
1866*/
1867
1868/*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
1869 Returns the minimum scale value of the viewport as a multiplier.
1870*/
1871
1872/*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
1873 Returns the maximum scale value of the viewport as a multiplier.
1874*/
1875
1876/*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
1877 Determines whether or not the scale can be modified by the user.
1878*/
1879
1880
1881/*!
1882 \class QWebPage
1883 \since 4.4
1884 \brief The QWebPage class provides an object to view and edit web documents.
1885
1886 \inmodule QtWebKit
1887
1888 QWebPage holds a main frame responsible for web content, settings, the history
1889 of navigated links and actions. This class can be used, together with QWebFrame,
1890 to provide functionality like QWebView in a widget-less environment.
1891
1892 QWebPage's API is very similar to QWebView, as you are still provided with
1893 common functions like action() (known as
1894 \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
1895 findText() and settings(). More QWebView-like functions can be found in the
1896 main frame of QWebPage, obtained via the mainFrame() function. For example,
1897 the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
1898 \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
1899 using QWebFrame.
1900
1901 The loadStarted() signal is emitted when the page begins to load.The
1902 loadProgress() signal, on the other hand, is emitted whenever an element
1903 of the web page completes loading, such as an embedded image, a script,
1904 etc. Finally, the loadFinished() signal is emitted when the page contents
1905 are loaded completely, independent of script execution or page rendering.
1906 Its argument, either true or false, indicates whether or not the load
1907 operation succeeded.
1908
1909 \section1 Using QWebPage in a Widget-less Environment
1910
1911 Before you begin painting a QWebPage object, you need to set the size of
1912 the viewport by calling setViewportSize(). Then, you invoke the main
1913 frame's render function (QWebFrame::render()). An example of this
1914 is shown in the code snippet below.
1915
1916 Suppose we have a \c Thumbnail class as follows:
1917
1918 \snippet webkitsnippets/webpage/main.cpp 0
1919
1920 The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1921 object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1922 \c render().
1923
1924 \snippet webkitsnippets/webpage/main.cpp 1
1925
1926 The \c render() function shows how we can paint a thumbnail using a
1927 QWebPage object.
1928
1929 \snippet webkitsnippets/webpage/main.cpp 2
1930
1931 We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1932 then we instantiate a QImage object, \c image, with the same size as our
1933 \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1934 as a parameter to \c painter. Next, we render the contents of the main
1935 frame and its subframes into \c painter. Finally, we save the scaled image.
1936
1937 \sa QWebFrame
1938*/
1939
1940/*!
1941 Constructs an empty QWebPage with parent \a parent.
1942*/
1943QWebPage::QWebPage(QObject *parent)
1944 : QObject(parent)
1945 , d(new QWebPagePrivate(this))
1946{
1947 setView(qobject_cast<QWidget*>(parent));
1948
1949 connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1950#ifndef NDEBUG
1951 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1952#endif
1953}
1954
1955/*!
1956 Destroys the web page.
1957*/
1958QWebPage::~QWebPage()
1959{
1960 d->createMainFrame();
1961 FrameLoader* loader = d->mainFrame.data()->d->frame->loader();
1962 if (loader)
1963 loader->detachFromParent();
1964 delete d;
1965}
1966
1967/*!
1968 Returns the main frame of the page.
1969
1970 The main frame provides access to the hierarchy of sub-frames and is also needed if you
1971 want to explicitly render a web page into a given painter.
1972
1973 \sa currentFrame()
1974*/
1975QWebFrame *QWebPage::mainFrame() const
1976{
1977 d->createMainFrame();
1978 return d->mainFrame.data();
1979}
1980
1981/*!
1982 Returns the frame currently active.
1983
1984 \sa mainFrame(), frameCreated()
1985*/
1986QWebFrame *QWebPage::currentFrame() const
1987{
1988 d->createMainFrame();
1989 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
1990 return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject());
1991}
1992
1993
1994/*!
1995 \since 4.6
1996
1997 Returns the frame at the given point \a pos, or 0 if there is no frame at
1998 that position.
1999
2000 \sa mainFrame(), currentFrame()
2001*/
2002QWebFrame* QWebPage::frameAt(const QPoint& pos) const
2003{
2004 QWebFrame* webFrame = mainFrame();
2005 if (!webFrame->geometry().contains(pos))
2006 return 0;
2007 QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
2008 return hitTestResult.frame();
2009}
2010
2011/*!
2012 Returns a pointer to the view's history of navigated web pages.
2013*/
2014QWebHistory *QWebPage::history() const
2015{
2016 d->createMainFrame();
2017 return &d->history;
2018}
2019
2020/*!
2021 Sets the \a view that is associated with the web page.
2022
2023 \sa view()
2024*/
2025void QWebPage::setView(QWidget* view)
2026{
2027 if (this->view() == view)
2028 return;
2029
2030 d->view = view;
2031 setViewportSize(view ? view->size() : QSize(0, 0));
2032
2033 // If we have no client, we install a special client delegating
2034 // the responsibility to the QWidget. This is the code path
2035 // handling a.o. the "legacy" QWebView.
2036 //
2037 // If such a special delegate already exist, we substitute the view.
2038
2039 if (d->client) {
2040 if (d->client->isQWidgetClient())
2041 static_cast<PageClientQWidget*>(d->client.get())->view = view;
2042 return;
2043 }
2044
2045 if (view)
2046 d->client = adoptPtr(new PageClientQWidget(view, this));
2047}
2048
2049/*!
2050 Returns the view widget that is associated with the web page.
2051
2052 \sa setView()
2053*/
2054QWidget *QWebPage::view() const
2055{
2056 return d->view.data();
2057}
2058
2059/*!
2060 This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
2061
2062 For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
2063
2064 The default implementation prints nothing.
2065*/
2066void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
2067{
2068 Q_UNUSED(sourceID)
2069
2070 // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
2071 // At this point DRT's WebPage has already been destroyed
2072 if (QWebPagePrivate::drtRun) {
2073 if (message == QLatin1String("PLUGIN: NPP_Destroy")) {
2074 fprintf(stdout, "CONSOLE MESSAGE: ");
2075 if (lineNumber)
2076 fprintf(stdout, "line %d: ", lineNumber);
2077 fprintf(stdout, "%s\n", message.toUtf8().constData());
2078 }
2079 }
2080}
2081
2082/*!
2083 This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
2084 the message \a msg.
2085
2086 The default implementation shows the message, \a msg, with QMessageBox::information.
2087*/
2088void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
2089{
2090 Q_UNUSED(frame)
2091#ifndef QT_NO_MESSAGEBOX
2092 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2093 QMessageBox box(parent);
2094 box.setWindowTitle(tr("JavaScript Alert - %1").arg(mainFrame()->url().host()));
2095 box.setTextFormat(Qt::PlainText);
2096 box.setText(msg);
2097 box.setStandardButtons(QMessageBox::Ok);
2098 box.exec();
2099#endif
2100}
2101
2102/*!
2103 This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
2104 with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
2105
2106 The default implementation executes the query using QMessageBox::information with QMessageBox::Ok and QMessageBox::Cancel buttons.
2107*/
2108bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
2109{
2110 Q_UNUSED(frame)
2111#ifdef QT_NO_MESSAGEBOX
2112 return true;
2113#else
2114 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2115 QMessageBox box(parent);
2116 box.setWindowTitle(tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()));
2117 box.setTextFormat(Qt::PlainText);
2118 box.setText(msg);
2119 box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
2120 return QMessageBox::Ok == box.exec();
2121#endif
2122}
2123
2124/*!
2125 This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
2126 The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
2127
2128 If the prompt was cancelled by the user the implementation should return false; otherwise the
2129 result should be written to \a result and true should be returned. If the prompt was not cancelled by the
2130 user, the implementation should return true and the result string must not be null.
2131
2132 The default implementation uses QInputDialog::getText().
2133*/
2134bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
2135{
2136 Q_UNUSED(frame)
2137 bool ok = false;
2138#ifndef QT_NO_INPUTDIALOG
2139
2140 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2141 QInputDialog dlg(parent);
2142 dlg.setWindowTitle(tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()));
2143
2144 // Hack to force the dialog's QLabel into plain text mode
2145 // prevents https://bugs.webkit.org/show_bug.cgi?id=34429
2146 QLabel* label = dlg.findChild<QLabel*>();
2147 if (label)
2148 label->setTextFormat(Qt::PlainText);
2149
2150 // double the &'s because single & will underline the following character
2151 // (Accelerator mnemonics)
2152 QString escMsg(msg);
2153 escMsg.replace(QChar::fromLatin1('&'), QLatin1String("&&"));
2154 dlg.setLabelText(escMsg);
2155
2156 dlg.setTextEchoMode(QLineEdit::Normal);
2157 dlg.setTextValue(defaultValue);
2158
2159 ok = !!dlg.exec();
2160
2161 if (ok && result)
2162 *result = dlg.textValue();
2163#endif
2164 return ok;
2165}
2166
2167/*!
2168 \fn bool QWebPage::shouldInterruptJavaScript()
2169 \since 4.6
2170 This function is called when a JavaScript program is running for a long period of time.
2171
2172 If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
2173
2174 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2175
2176 \warning Because of binary compatibility constraints, this function is not virtual. If you want to
2177 provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
2178 slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
2179*/
2180bool QWebPage::shouldInterruptJavaScript()
2181{
2182#ifdef QT_NO_MESSAGEBOX
2183 return false;
2184#else
2185 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2186 return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No);
2187#endif
2188}
2189
2190void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
2191{
2192#if !ENABLE(NOTIFICATIONS) && !ENABLE(LEGACY_NOTIFICATIONS) && !ENABLE(GEOLOCATION)
2193 Q_UNUSED(frame);
2194 Q_UNUSED(policy);
2195#endif
2196 switch (feature) {
2197 case Notifications:
2198#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
2199 if (policy != PermissionUnknown)
2200 NotificationPresenterClientQt::notificationPresenter()->setNotificationsAllowedForFrame(frame->d->frame, (policy == PermissionGrantedByUser));
2201#endif
2202 break;
2203 case Geolocation:
2204#if ENABLE(GEOLOCATION)
2205 GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, policy);
2206#endif
2207 break;
2208
2209 default:
2210 break;
2211 }
2212}
2213
2214/*!
2215 This function is called whenever WebKit wants to create a new window of the given \a type, for
2216 example when a JavaScript program requests to open a document in a new window.
2217
2218 If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
2219
2220 If the view associated with the web page is a QWebView object, then the default implementation forwards
2221 the request to QWebView's createWindow() function; otherwise it returns a null pointer.
2222
2223 If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
2224
2225 \note In the cases when the window creation is being triggered by JavaScript, apart from
2226 reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
2227 of QWebSettings to true in order for it to get called.
2228
2229 \sa acceptNavigationRequest(), QWebView::createWindow()
2230*/
2231QWebPage *QWebPage::createWindow(WebWindowType type)
2232{
2233 QWebView *webView = qobject_cast<QWebView*>(view());
2234 if (webView) {
2235 QWebView *newView = webView->createWindow(type);
2236 if (newView)
2237 return newView->page();
2238 }
2239 return 0;
2240}
2241
2242/*!
2243 This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
2244 called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
2245 correspond to the HTML object element attributes and child elements to configure the embeddable object.
2246*/
2247QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
2248{
2249 Q_UNUSED(classid)
2250 Q_UNUSED(url)
2251 Q_UNUSED(paramNames)
2252 Q_UNUSED(paramValues)
2253 return 0;
2254}
2255
2256static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list)
2257{
2258 if (!list)
2259 return;
2260
2261 HashSet<String>::const_iterator endIt = types.end();
2262 for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it)
2263 *list << *it;
2264}
2265
2266static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list)
2267{
2268 if (!list)
2269 return;
2270
2271 for (unsigned int i = 0; i < plugins.size(); ++i) {
2272 MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin();
2273 MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end();
2274 for (; map_it != map_end; ++map_it)
2275 *list << map_it->key;
2276 }
2277}
2278
2279/*!
2280 * Returns the list of all content types supported by QWebPage.
2281 */
2282QStringList QWebPage::supportedContentTypes() const
2283{
2284 QStringList mimeTypes;
2285
2286 extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes);
2287 extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes);
2288 if (d->page->settings() && d->page->settings()->arePluginsEnabled())
2289 extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes);
2290
2291 return mimeTypes;
2292}
2293
2294/*!
2295 * Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
2296 */
2297bool QWebPage::supportsContentType(const QString& mimeType) const
2298{
2299 const String type = mimeType.toLower();
2300 if (MIMETypeRegistry::isSupportedImageMIMEType(type))
2301 return true;
2302
2303 if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
2304 return true;
2305
2306 if (d->page->settings() && d->page->settings()->arePluginsEnabled()
2307 && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
2308 return true;
2309
2310 return false;
2311}
2312
2313static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
2314{
2315 return WebCore::FrameLoadRequest(frame->document()->securityOrigin(),
2316 WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer()));
2317}
2318
2319static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
2320{
2321 if (Page* oldPage = frame->page()) {
2322 WindowFeatures features;
2323 NavigationAction action;
2324 FrameLoadRequest request = frameLoadRequest(url, frame);
2325 if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) {
2326 newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, MaybeSendReferrer);
2327 newPage->chrome()->show();
2328 }
2329 }
2330}
2331
2332static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
2333{
2334 list << frame->childFrames();
2335 QListIterator<QWebFrame*> it(frame->childFrames());
2336 while (it.hasNext()) {
2337 collectChildFrames(it.next(), list);
2338 }
2339}
2340
2341/*!
2342 This function can be called to trigger the specified \a action.
2343 It is also called by QtWebKit if the user triggers the action, for example
2344 through a context menu item.
2345
2346 If \a action is a checkable action then \a checked specified whether the action
2347 is toggled or not.
2348
2349 \sa action()
2350*/
2351void QWebPage::triggerAction(WebAction action, bool)
2352{
2353 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2354 if (!frame)
2355 return;
2356 WebCore::Editor *editor = frame->editor();
2357 const char *command = 0;
2358
2359 switch (action) {
2360 case OpenLink:
2361 if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2362 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2363 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2364 /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2365 /*FormState*/ 0, MaybeSendReferrer);
2366 break;
2367 }
2368 // fall through
2369 case OpenLinkInNewWindow:
2370 openNewWindow(d->hitTestResult.linkUrl(), frame);
2371 break;
2372 case OpenLinkInThisWindow:
2373 frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), frame),
2374 /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0, /*FormState*/ 0, MaybeSendReferrer);
2375 break;
2376 case OpenFrameInNewWindow: {
2377 KURL url = frame->loader()->documentLoader()->unreachableURL();
2378 if (url.isEmpty())
2379 url = frame->loader()->documentLoader()->url();
2380 openNewWindow(url, frame);
2381 break;
2382 }
2383 case CopyLinkToClipboard: {
2384#if defined(Q_WS_X11)
2385 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2386 Pasteboard::generalPasteboard()->setSelectionMode(true);
2387 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2388 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2389#endif
2390 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2391 break;
2392 }
2393 case OpenImageInNewWindow:
2394 openNewWindow(d->hitTestResult.imageUrl(), frame);
2395 break;
2396 case DownloadImageToDisk:
2397 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2398 break;
2399 case DownloadLinkToDisk:
2400 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2401 break;
2402#ifndef QT_NO_CLIPBOARD
2403 case CopyImageToClipboard:
2404 QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2405 break;
2406 case CopyImageUrlToClipboard:
2407 QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
2408 break;
2409#endif
2410 case Back:
2411 d->page->goBack();
2412 break;
2413 case Forward:
2414 d->page->goForward();
2415 break;
2416 case Stop:
2417 mainFrame()->d->frame->loader()->stopForUserCancel();
2418 d->updateNavigationActions();
2419 break;
2420 case Reload:
2421 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2422 break;
2423 case ReloadAndBypassCache:
2424 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2425 break;
2426 case SetTextDirectionDefault:
2427 editor->setBaseWritingDirection(NaturalWritingDirection);
2428 break;
2429 case SetTextDirectionLeftToRight:
2430 editor->setBaseWritingDirection(LeftToRightWritingDirection);
2431 break;
2432 case SetTextDirectionRightToLeft:
2433 editor->setBaseWritingDirection(RightToLeftWritingDirection);
2434 break;
2435 case InspectElement: {
2436#if ENABLE(INSPECTOR)
2437 if (!d->hitTestResult.isNull()) {
2438 d->getOrCreateInspector(); // Make sure the inspector is created
2439 d->inspector->show(); // The inspector is expected to be shown on inspection
2440 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2441 }
2442#endif
2443 break;
2444 }
2445 case StopScheduledPageRefresh: {
2446 QWebFrame* topFrame = mainFrame();
2447 topFrame->d->frame->navigationScheduler()->cancel();
2448 QList<QWebFrame*> childFrames;
2449 collectChildFrames(topFrame, childFrames);
2450 QListIterator<QWebFrame*> it(childFrames);
2451 while (it.hasNext())
2452 it.next()->d->frame->navigationScheduler()->cancel();
2453 break;
2454 }
2455 default:
2456 command = QWebPagePrivate::editorCommandForWebActions(action);
2457 break;
2458 }
2459
2460 if (command)
2461 editor->command(command).execute();
2462}
2463
2464
2465QColor QWebPagePrivate::colorSelectionRequested(const QColor &selectedColor)
2466{
2467 QColor ret = selectedColor;
2468#ifndef QT_NO_COLORDIALOG
2469 QWidget* parent = (client) ? client->ownerWidget() : 0;
2470 ret = QColorDialog::getColor(selectedColor, parent);
2471 if (!ret.isValid())
2472 ret = selectedColor;
2473#endif
2474 return ret;
2475}
2476
2477QSize QWebPage::viewportSize() const
2478{
2479 if (d->mainFrame && d->mainFrame.data()->d->frame->view())
2480 return d->mainFrame.data()->d->frame->view()->frameRect().size();
2481
2482 return d->viewportSize;
2483}
2484
2485/*!
2486 \property QWebPage::viewportSize
2487 \brief the size of the viewport
2488
2489 The size affects for example the visibility of scrollbars
2490 if the document is larger than the viewport.
2491
2492 By default, for a newly-created Web page, this property contains a size with
2493 zero width and height.
2494
2495 \sa QWebFrame::render(), preferredContentsSize
2496*/
2497void QWebPage::setViewportSize(const QSize &size) const
2498{
2499 d->viewportSize = size;
2500
2501 QWebFrame *frame = mainFrame();
2502 if (frame->d->frame && frame->d->frame->view()) {
2503 WebCore::FrameView* view = frame->d->frame->view();
2504 view->resize(size);
2505 view->adjustViewSize();
2506 }
2507}
2508
2509static int getintenv(const char* variable)
2510{
2511 bool ok;
2512 int value = qgetenv(variable).toInt(&ok);
2513 return (ok) ? value : -1;
2514}
2515
2516static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
2517{
2518 QDesktopWidget* desktop = QApplication::desktop();
2519 if (!desktop)
2520 return QSize();
2521
2522 QSize size;
2523
2524 if (widget) {
2525 // Returns the available geometry of the screen which contains widget.
2526 // NOTE: this must be the the full screen size including any fixed status areas etc.
2527 size = desktop->availableGeometry(widget).size();
2528 } else
2529 size = desktop->availableGeometry().size();
2530
2531 // This must be in portrait mode, adjust if not.
2532 if (size.width() > size.height()) {
2533 int width = size.width();
2534 size.setWidth(size.height());
2535 size.setHeight(width);
2536 }
2537
2538 return size;
2539}
2540
2541/*!
2542 Computes the optimal viewport configuration given the \a availableSize, when
2543 user interface components are disregarded.
2544
2545 The configuration is also dependent on the device screen size which is obtained
2546 automatically. For testing purposes the size can be overridden by setting two
2547 environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
2548 both needs to be set.
2549
2550 The ViewportAttributes includes a pixel density ratio, which will also be exposed to
2551 the web author though the -webkit-pixel-ratio media feature. This is the ratio
2552 between 1 density-independent pixel (DPI) and physical pixels.
2553
2554 A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
2555 so on our platform assumes that as the baseline density.
2556
2557 The conversion of DIP units to screen pixels is quite simple:
2558
2559 pixels = DIPs * (density / 160).
2560
2561 Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
2562
2563 An invalid instance will be returned in the case an empty size is passed to the
2564 method.
2565
2566 \note The density is automatically obtained from the DPI of the screen where the page
2567 is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
2568 override it using QX11Info::setAppDpiY().
2569*/
2570
2571QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
2572{
2573 static int desktopWidth = 980;
2574
2575 ViewportAttributes result;
2576
2577 if (availableSize.isEmpty())
2578 return result; // Returns an invalid instance.
2579
2580 int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH");
2581 int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT");
2582
2583 // Both environment variables need to be set - or they will be ignored.
2584 if (deviceWidth < 0 && deviceHeight < 0) {
2585 QSize size = queryDeviceSizeForScreenContainingWidget((d->client) ? d->client->ownerWidget() : 0);
2586 deviceWidth = size.width();
2587 deviceHeight = size.height();
2588 }
2589
2590 float devicePixelRatio = qt_defaultDpi() / WebCore::ViewportArguments::deprecatedTargetDPI;
2591
2592 WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, devicePixelRatio, availableSize);
2593 WebCore::restrictMinimumScaleFactorToViewportSize(conf, availableSize, devicePixelRatio);
2594 WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(conf);
2595
2596 result.m_isValid = true;
2597 result.m_size = QSize(conf.layoutSize.width(), conf.layoutSize.height());
2598 result.m_initialScaleFactor = conf.initialScale;
2599 result.m_minimumScaleFactor = conf.minimumScale;
2600 result.m_maximumScaleFactor = conf.maximumScale;
2601 result.m_devicePixelRatio = devicePixelRatio;
2602 result.m_isUserScalable = static_cast<bool>(conf.userScalable);
2603
2604 d->page->setDeviceScaleFactor(devicePixelRatio);
2605
2606 return result;
2607}
2608
2609QSize QWebPage::preferredContentsSize() const
2610{
2611 QWebFrame* frame = d->mainFrame.data();
2612 if (frame) {
2613 WebCore::FrameView* view = frame->d->frame->view();
2614 if (view && view->useFixedLayout())
2615 return d->mainFrame.data()->d->frame->view()->fixedLayoutSize();
2616 }
2617
2618 return d->fixedLayoutSize;
2619}
2620
2621/*!
2622 \property QWebPage::preferredContentsSize
2623 \since 4.6
2624 \brief a custom size used for laying out the page contents.
2625
2626 By default all pages are laid out using the viewport of the page as the base.
2627
2628 As pages mostly are designed for desktop usage, they often do not layout properly
2629 on small devices as the contents require a certain view width. For this reason
2630 it is common to use a different layout size and then scale the contents to fit
2631 within the actual view.
2632
2633 If this property is set to a valid size, this size is used for all layout needs
2634 instead of the size of the viewport.
2635
2636 Setting an invalid size, makes the page fall back to using the viewport size for layout.
2637
2638 \sa viewportSize
2639*/
2640void QWebPage::setPreferredContentsSize(const QSize& size) const
2641{
2642 // FIXME: Rename this method to setCustomLayoutSize
2643
2644 d->fixedLayoutSize = size;
2645
2646 QWebFrame* frame = mainFrame();
2647 if (!frame->d->frame || !frame->d->frame->view())
2648 return;
2649
2650 WebCore::FrameView* view = frame->d->frame->view();
2651
2652 if (size.isValid()) {
2653 view->setUseFixedLayout(true);
2654 view->setFixedLayoutSize(size);
2655 } else if (view->useFixedLayout())
2656 view->setUseFixedLayout(false);
2657
2658 view->layout();
2659}
2660
2661/*
2662 This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
2663 scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
2664 the application to pan the actual view, which then resizes itself to the size of the contents.
2665
2666 \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
2667 again, call this method with an empty rect.
2668
2669 \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
2670*/
2671void QWebPage::setActualVisibleContentRect(const QRect& rect) const
2672{
2673 QWebFrame* frame = mainFrame();
2674 if (!frame->d->frame || !frame->d->frame->view())
2675 return;
2676
2677 WebCore::FrameView* view = frame->d->frame->view();
2678 view->setFixedVisibleContentRect(rect);
2679}
2680
2681/*!
2682 \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2683
2684 This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2685 the specified navigation type \a type.
2686
2687 If \a frame is a null pointer then navigation to a new window is requested. If the request is
2688 accepted createWindow() will be called.
2689
2690 The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2691 to let QWebPage handle the navigation itself.
2692
2693 \sa createWindow()
2694*/
2695bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2696{
2697 Q_UNUSED(frame)
2698 if (type == NavigationTypeLinkClicked) {
2699 switch (d->linkPolicy) {
2700 case DontDelegateLinks:
2701 return true;
2702
2703 case DelegateExternalLinks:
2704 if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2705 return true;
2706 emit linkClicked(request.url());
2707 return false;
2708
2709 case DelegateAllLinks:
2710 emit linkClicked(request.url());
2711 return false;
2712 }
2713 }
2714 return true;
2715}
2716
2717/*!
2718 \property QWebPage::hasSelection
2719 \brief whether this page contains selected content or not.
2720
2721 \sa selectionChanged()
2722*/
2723bool QWebPage::hasSelection() const
2724{
2725 d->createMainFrame();
2726 WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2727 if (frame)
2728 return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection);
2729 return false;
2730}
2731
2732/*!
2733 \property QWebPage::selectedText
2734 \brief the text currently selected
2735
2736 By default, this property contains an empty string.
2737
2738 \sa selectionChanged(), selectedHtml()
2739*/
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches