OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "sky/engine/web/WebViewImpl.h" | |
32 | |
33 #include "gen/sky/core/CSSValueKeywords.h" | |
34 #include "gen/sky/core/HTMLNames.h" | |
35 #include "gen/sky/platform/RuntimeEnabledFeatures.h" | |
36 #include "sky/engine/core/dom/Document.h" | |
37 #include "sky/engine/core/dom/DocumentMarkerController.h" | |
38 #include "sky/engine/core/dom/NodeRenderingTraversal.h" | |
39 #include "sky/engine/core/dom/Text.h" | |
40 #include "sky/engine/core/editing/Editor.h" | |
41 #include "sky/engine/core/editing/FrameSelection.h" | |
42 #include "sky/engine/core/editing/HTMLInterchange.h" | |
43 #include "sky/engine/core/editing/InputMethodController.h" | |
44 #include "sky/engine/core/editing/TextIterator.h" | |
45 #include "sky/engine/core/events/KeyboardEvent.h" | |
46 #include "sky/engine/core/frame/FrameHost.h" | |
47 #include "sky/engine/core/frame/FrameView.h" | |
48 #include "sky/engine/core/frame/LocalFrame.h" | |
49 #include "sky/engine/core/frame/NewEventHandler.h" | |
50 #include "sky/engine/core/frame/Settings.h" | |
51 #include "sky/engine/core/html/HTMLImportElement.h" | |
52 #include "sky/engine/core/loader/FrameLoader.h" | |
53 #include "sky/engine/core/loader/UniqueIdentifier.h" | |
54 #include "sky/engine/core/page/EventHandler.h" | |
55 #include "sky/engine/core/page/FocusController.h" | |
56 #include "sky/engine/core/page/Page.h" | |
57 #include "sky/engine/core/rendering/RenderView.h" | |
58 #include "sky/engine/platform/KeyboardCodes.h" | |
59 #include "sky/engine/platform/Logging.h" | |
60 #include "sky/engine/platform/NotImplemented.h" | |
61 #include "sky/engine/platform/TraceEvent.h" | |
62 #include "sky/engine/platform/fonts/FontCache.h" | |
63 #include "sky/engine/platform/graphics/Color.h" | |
64 #include "sky/engine/platform/graphics/GraphicsContext.h" | |
65 #include "sky/engine/platform/graphics/Image.h" | |
66 #include "sky/engine/platform/graphics/ImageBuffer.h" | |
67 #include "sky/engine/public/platform/Platform.h" | |
68 #include "sky/engine/public/platform/WebFloatPoint.h" | |
69 #include "sky/engine/public/platform/WebImage.h" | |
70 #include "sky/engine/public/platform/WebLayerTreeView.h" | |
71 #include "sky/engine/public/platform/WebURLRequest.h" | |
72 #include "sky/engine/public/platform/WebVector.h" | |
73 #include "sky/engine/public/web/WebBeginFrameArgs.h" | |
74 #include "sky/engine/public/web/WebFrameClient.h" | |
75 #include "sky/engine/public/web/WebNode.h" | |
76 #include "sky/engine/public/web/WebRange.h" | |
77 #include "sky/engine/public/web/WebTextInputInfo.h" | |
78 #include "sky/engine/public/web/WebViewClient.h" | |
79 #include "sky/engine/web/CompositionUnderlineVectorBuilder.h" | |
80 #include "sky/engine/web/WebLocalFrameImpl.h" | |
81 #include "sky/engine/web/WebSettingsImpl.h" | |
82 #include "sky/engine/wtf/CurrentTime.h" | |
83 #include "sky/engine/wtf/RefPtr.h" | |
84 #include "sky/engine/wtf/TemporaryChange.h" | |
85 #include "url/gurl.h" | |
86 | |
87 // Get rid of WTF's pow define so we can use std::pow. | |
88 #undef pow | |
89 #include <cmath> // for std::pow | |
90 | |
91 namespace blink { | |
92 | |
93 // WebView ---------------------------------------------------------------- | |
94 | |
95 WebView* WebView::create(WebViewClient* client) | |
96 { | |
97 CRASH(); // WebView is deprecated. Please use SkyView. | |
98 // Pass the WebViewImpl's self-reference to the caller. | |
99 return WebViewImpl::create(client); | |
100 } | |
101 | |
102 WebViewImpl* WebViewImpl::create(WebViewClient* client) | |
103 { | |
104 // Pass the WebViewImpl's self-reference to the caller. | |
105 return adoptRef(new WebViewImpl(client)).leakRef(); | |
106 } | |
107 | |
108 void WebViewImpl::setMainFrame(WebFrame* frame) | |
109 { | |
110 toWebLocalFrameImpl(frame)->initializeCoreFrame(&page()->frameHost()); | |
111 } | |
112 | |
113 void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient) | |
114 { | |
115 m_spellCheckClient = spellCheckClient; | |
116 } | |
117 | |
118 WebViewImpl::WebViewImpl(WebViewClient* client) | |
119 : m_client(client) | |
120 , m_spellCheckClient(0) | |
121 , m_chromeClientImpl(this) | |
122 , m_editorClientImpl(this) | |
123 , m_spellCheckerClientImpl(this) | |
124 , m_fixedLayoutSizeLock(false) | |
125 , m_rootLayerScale(1) | |
126 , m_suppressNextKeypressEvent(false) | |
127 , m_imeAcceptEvents(true) | |
128 , m_isTransparent(false) | |
129 , m_rootLayer(0) | |
130 , m_matchesHeuristicsForGpuRasterization(false) | |
131 , m_recreatingGraphicsContext(false) | |
132 , m_flingModifier(0) | |
133 , m_flingSourceDevice(false) | |
134 , m_showPaintRects(false) | |
135 , m_showDebugBorders(false) | |
136 , m_baseBackgroundColor(Color::white) | |
137 , m_backgroundColorOverride(Color::transparent) | |
138 { | |
139 Page::PageClients pageClients; | |
140 pageClients.chromeClient = &m_chromeClientImpl; | |
141 pageClients.editorClient = &m_editorClientImpl; | |
142 pageClients.spellCheckerClient = &m_spellCheckerClientImpl; | |
143 | |
144 m_page = adoptPtr(new Page(pageClients, m_client->services())); | |
145 | |
146 setDeviceScaleFactor(m_client->screenInfo().deviceScaleFactor); | |
147 setVisibilityState(m_client->visibilityState(), true); | |
148 | |
149 m_client->initializeLayerTreeView(); | |
150 } | |
151 | |
152 WebViewImpl::~WebViewImpl() | |
153 { | |
154 ASSERT(!m_page); | |
155 } | |
156 | |
157 WebLocalFrameImpl* WebViewImpl::mainFrameImpl() | |
158 { | |
159 return m_page ? WebLocalFrameImpl::fromFrame(m_page->mainFrame()) : 0; | |
160 } | |
161 | |
162 void WebViewImpl::setShowPaintRects(bool show) | |
163 { | |
164 m_showPaintRects = show; | |
165 } | |
166 | |
167 void WebViewImpl::setShowDebugBorders(bool show) | |
168 { | |
169 m_showDebugBorders = show; | |
170 } | |
171 | |
172 void WebViewImpl::acceptLanguagesChanged() | |
173 { | |
174 if (!page()) | |
175 return; | |
176 | |
177 page()->acceptLanguagesChanged(); | |
178 } | |
179 | |
180 LocalFrame* WebViewImpl::focusedCoreFrame() const | |
181 { | |
182 return m_page ? m_page->focusController().focusedOrMainFrame() : 0; | |
183 } | |
184 | |
185 WebViewImpl* WebViewImpl::fromPage(Page* page) | |
186 { | |
187 if (!page) | |
188 return 0; | |
189 return static_cast<WebViewImpl*>(page->webView()); | |
190 } | |
191 | |
192 // WebWidget ------------------------------------------------------------------ | |
193 | |
194 void WebViewImpl::close() | |
195 { | |
196 if (m_page) { | |
197 // Initiate shutdown for the entire frameset. This will cause a lot of | |
198 // notifications to be sent. | |
199 m_page->willBeDestroyed(); | |
200 m_page.clear(); | |
201 } | |
202 | |
203 // Reset the delegate to prevent notifications being sent as we're being | |
204 // deleted. | |
205 m_client = 0; | |
206 | |
207 deref(); // Balances ref() acquired in WebView::create | |
208 } | |
209 | |
210 WebSize WebViewImpl::size() | |
211 { | |
212 return m_size; | |
213 } | |
214 | |
215 void WebViewImpl::performResize() | |
216 { | |
217 updateMainFrameLayoutSize(); | |
218 | |
219 // If the virtual viewport pinch mode is enabled, the main frame will be res
ized | |
220 // after layout so it can be sized to the contentsSize. | |
221 if (FrameView* view = m_page->mainFrame()->view()) | |
222 view->resize(m_size); | |
223 } | |
224 | |
225 void WebViewImpl::resize(const WebSize& newSize) | |
226 { | |
227 if (m_size == newSize) | |
228 return; | |
229 | |
230 FrameView* view = m_page->mainFrame()->view(); | |
231 if (!view) | |
232 return; | |
233 | |
234 m_size = newSize; | |
235 performResize(); | |
236 sendResizeEventAndRepaint(); | |
237 } | |
238 | |
239 void WebViewImpl::beginFrame(const WebBeginFrameArgs& frameTime) | |
240 { | |
241 TRACE_EVENT0("blink", "WebViewImpl::beginFrame"); | |
242 | |
243 WebBeginFrameArgs validFrameTime(frameTime); | |
244 if (!validFrameTime.lastFrameTimeMonotonic) | |
245 validFrameTime.lastFrameTimeMonotonic = monotonicallyIncreasingTime(); | |
246 | |
247 WTF_LOG(ScriptedAnimationController, "WebViewImpl::beginFrame: page = %d", !
m_page ? 0 : 1); | |
248 if (!m_page) | |
249 return; | |
250 | |
251 RefPtr<FrameView> view = m_page->mainFrame()->view(); | |
252 if (!view) | |
253 return; | |
254 m_page->animator().serviceScriptedAnimations(validFrameTime.lastFrameTimeMon
otonic); | |
255 } | |
256 | |
257 void WebViewImpl::layout() | |
258 { | |
259 TRACE_EVENT0("blink", "WebViewImpl::layout"); | |
260 if (!m_page) | |
261 return; | |
262 m_page->animator().updateLayoutAndStyleForPainting(m_page->mainFrame()); | |
263 } | |
264 | |
265 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect) | |
266 { | |
267 if (rect.isEmpty()) | |
268 return; | |
269 GraphicsContext gc(canvas); | |
270 gc.setCertainlyOpaque(!isTransparent()); | |
271 gc.applyDeviceScaleFactor(m_page->deviceScaleFactor()); | |
272 gc.setDeviceScaleFactor(m_page->deviceScaleFactor()); | |
273 IntRect dirtyRect(rect); | |
274 gc.save(); // Needed to save the canvas, not the GraphicsContext. | |
275 FrameView* view = m_page->mainFrame()->view(); | |
276 if (view) { | |
277 gc.clip(dirtyRect); | |
278 view->paint(&gc, dirtyRect); | |
279 } else { | |
280 gc.fillRect(dirtyRect, Color::white); | |
281 } | |
282 gc.restore(); | |
283 } | |
284 | |
285 // FIXME: autogenerate this kind of code, and use it throughout Blink rather tha
n | |
286 // the one-offs for subsets of these values. | |
287 static String inputTypeToName(WebInputEvent::Type type) | |
288 { | |
289 switch (type) { | |
290 case WebInputEvent::KeyDown: | |
291 return EventTypeNames::keydown; | |
292 case WebInputEvent::KeyUp: | |
293 return EventTypeNames::keyup; | |
294 case WebInputEvent::GestureScrollBegin: | |
295 return EventTypeNames::gesturescrollstart; | |
296 case WebInputEvent::GestureScrollEnd: | |
297 return EventTypeNames::gesturescrollend; | |
298 case WebInputEvent::GestureScrollUpdate: | |
299 return EventTypeNames::gesturescrollupdate; | |
300 case WebInputEvent::GestureTapDown: | |
301 return EventTypeNames::gesturetapdown; | |
302 case WebInputEvent::GestureShowPress: | |
303 return EventTypeNames::gestureshowpress; | |
304 case WebInputEvent::GestureTap: | |
305 return EventTypeNames::gesturetap; | |
306 case WebInputEvent::GestureTapUnconfirmed: | |
307 return EventTypeNames::gesturetapunconfirmed; | |
308 default: | |
309 return String("unknown"); | |
310 } | |
311 } | |
312 | |
313 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent) | |
314 { | |
315 TRACE_EVENT1("input", "WebViewImpl::handleInputEvent", "type", | |
316 TRACE_STR_COPY(inputTypeToName(inputEvent.type).ascii().data())
); | |
317 | |
318 if (WebInputEvent::isPointerEventType(inputEvent.type)) { | |
319 const WebPointerEvent& event = static_cast<const WebPointerEvent&>(input
Event); | |
320 return m_page->mainFrame()->newEventHandler().handlePointerEvent(event); | |
321 } | |
322 | |
323 if (WebInputEvent::isGestureEventType(inputEvent.type)) { | |
324 const WebGestureEvent& event = static_cast<const WebGestureEvent&>(input
Event); | |
325 return m_page->mainFrame()->newEventHandler().handleGestureEvent(event); | |
326 } | |
327 | |
328 if (WebInputEvent::isKeyboardEventType(inputEvent.type)) { | |
329 const WebKeyboardEvent& event = static_cast<const WebKeyboardEvent&>(inp
utEvent); | |
330 return m_page->mainFrame()->newEventHandler().handleKeyboardEvent(event)
; | |
331 } | |
332 | |
333 if (WebInputEvent::isWheelEventType(inputEvent.type)) { | |
334 const WebWheelEvent& event = static_cast<const WebWheelEvent&>(inputEven
t); | |
335 return m_page->mainFrame()->newEventHandler().handleWheelEvent(event); | |
336 } | |
337 | |
338 return false; | |
339 } | |
340 | |
341 void WebViewImpl::setFocus(bool enable) | |
342 { | |
343 m_page->focusController().setFocused(enable); | |
344 if (enable) { | |
345 m_page->focusController().setActive(true); | |
346 RefPtr<LocalFrame> focusedFrame = m_page->focusController().focusedFrame
(); | |
347 if (focusedFrame) { | |
348 LocalFrame* localFrame = focusedFrame.get(); | |
349 Element* element = localFrame->document()->focusedElement(); | |
350 if (element && localFrame->selection().selection().isNone()) { | |
351 // If the selection was cleared while the WebView was not | |
352 // focused, then the focus element shows with a focus ring but | |
353 // no caret and does respond to keyboard inputs. | |
354 if (element->isContentEditable()) { | |
355 // updateFocusAppearance() selects all the text of | |
356 // contentseditable DIVs. So we set the selection explicitly | |
357 // instead. Note that this has the side effect of moving the | |
358 // caret back to the beginning of the text. | |
359 Position position(element, 0, Position::PositionIsOffsetInAn
chor); | |
360 localFrame->selection().setSelection(VisibleSelection(positi
on, SEL_DEFAULT_AFFINITY)); | |
361 } | |
362 } | |
363 } | |
364 m_imeAcceptEvents = true; | |
365 } else { | |
366 // Clear focus on the currently focused frame if any. | |
367 if (!m_page) | |
368 return; | |
369 | |
370 RefPtr<LocalFrame> focusedFrame = m_page->focusController().focusedFrame
(); | |
371 if (focusedFrame) { | |
372 // Finish an ongoing composition to delete the composition node. | |
373 if (focusedFrame->inputMethodController().hasComposition()) { | |
374 focusedFrame->inputMethodController().confirmComposition(); | |
375 } | |
376 m_imeAcceptEvents = false; | |
377 } | |
378 } | |
379 } | |
380 | |
381 bool WebViewImpl::setComposition( | |
382 const WebString& text, | |
383 const WebVector<WebCompositionUnderline>& underlines, | |
384 int selectionStart, | |
385 int selectionEnd) | |
386 { | |
387 LocalFrame* focused = focusedCoreFrame(); | |
388 if (!focused || !m_imeAcceptEvents) | |
389 return false; | |
390 | |
391 // The input focus has been moved to another WebWidget object. | |
392 // We should use this |editor| object only to complete the ongoing | |
393 // composition. | |
394 InputMethodController& inputMethodController = focused->inputMethodControlle
r(); | |
395 if (!focused->editor().canEdit() && !inputMethodController.hasComposition()) | |
396 return false; | |
397 | |
398 // We should verify the parent node of this IME composition node are | |
399 // editable because JavaScript may delete a parent node of the composition | |
400 // node. In this case, WebKit crashes while deleting texts from the parent | |
401 // node, which doesn't exist any longer. | |
402 RefPtr<Range> range = inputMethodController.compositionRange(); | |
403 if (range) { | |
404 Node* node = range->startContainer(); | |
405 if (!node || !node->isContentEditable()) | |
406 return false; | |
407 } | |
408 | |
409 // If we're not going to fire a keypress event, then the keydown event was | |
410 // canceled. In that case, cancel any existing composition. | |
411 if (text.isEmpty() || m_suppressNextKeypressEvent) { | |
412 // A browser process sent an IPC message which does not contain a valid | |
413 // string, which means an ongoing composition has been canceled. | |
414 // If the ongoing composition has been canceled, replace the ongoing | |
415 // composition string with an empty string and complete it. | |
416 String emptyString; | |
417 Vector<CompositionUnderline> emptyUnderlines; | |
418 inputMethodController.setComposition(emptyString, emptyUnderlines, 0, 0)
; | |
419 return text.isEmpty(); | |
420 } | |
421 | |
422 // When the range of composition underlines overlap with the range between | |
423 // selectionStart and selectionEnd, WebKit somehow won't paint the selection | |
424 // at all (see InlineTextBox::paint() function in InlineTextBox.cpp). | |
425 // But the selection range actually takes effect. | |
426 inputMethodController.setComposition(String(text), | |
427 CompositionUnderlineVectorBuilder(underlines), | |
428 selectionStart, selectionEnd); | |
429 | |
430 return inputMethodController.hasComposition(); | |
431 } | |
432 | |
433 bool WebViewImpl::confirmComposition() | |
434 { | |
435 return confirmComposition(DoNotKeepSelection); | |
436 } | |
437 | |
438 bool WebViewImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavio
r) | |
439 { | |
440 return confirmComposition(WebString(), selectionBehavior); | |
441 } | |
442 | |
443 bool WebViewImpl::confirmComposition(const WebString& text) | |
444 { | |
445 return confirmComposition(text, DoNotKeepSelection); | |
446 } | |
447 | |
448 bool WebViewImpl::confirmComposition(const WebString& text, ConfirmCompositionBe
havior selectionBehavior) | |
449 { | |
450 LocalFrame* focused = focusedCoreFrame(); | |
451 if (!focused || !m_imeAcceptEvents) | |
452 return false; | |
453 | |
454 return focused->inputMethodController().confirmCompositionOrInsertText(text,
selectionBehavior == KeepSelection ? InputMethodController::KeepSelection : Inp
utMethodController::DoNotKeepSelection); | |
455 } | |
456 | |
457 WebTextInputInfo WebViewImpl::textInputInfo() | |
458 { | |
459 WebTextInputInfo info; | |
460 | |
461 LocalFrame* focused = focusedCoreFrame(); | |
462 if (!focused) | |
463 return info; | |
464 | |
465 FrameSelection& selection = focused->selection(); | |
466 Element* element = selection.selection().rootEditableElement(); | |
467 if (!element) | |
468 return info; | |
469 | |
470 info.inputMode = inputModeOfFocusedElement(); | |
471 | |
472 info.type = textInputType(); | |
473 info.flags = textInputFlags(); | |
474 if (info.type == WebTextInputTypeNone) | |
475 return info; | |
476 | |
477 if (!focused->editor().canEdit()) | |
478 return info; | |
479 | |
480 // Emits an object replacement character for each replaced element so that | |
481 // it is exposed to IME and thus could be deleted by IME on android. | |
482 info.value = plainText(rangeOfContents(element).get(), TextIteratorEmitsObje
ctReplacementCharacter); | |
483 | |
484 if (info.value.isEmpty()) | |
485 return info; | |
486 | |
487 if (RefPtr<Range> range = selection.selection().firstRange()) { | |
488 PlainTextRange plainTextRange(PlainTextRange::create(*element, *range.ge
t())); | |
489 if (plainTextRange.isNotNull()) { | |
490 info.selectionStart = plainTextRange.start(); | |
491 info.selectionEnd = plainTextRange.end(); | |
492 } | |
493 } | |
494 | |
495 if (RefPtr<Range> range = focused->inputMethodController().compositionRange(
)) { | |
496 PlainTextRange plainTextRange(PlainTextRange::create(*element, *range.ge
t())); | |
497 if (plainTextRange.isNotNull()) { | |
498 info.compositionStart = plainTextRange.start(); | |
499 info.compositionEnd = plainTextRange.end(); | |
500 } | |
501 } | |
502 | |
503 return info; | |
504 } | |
505 | |
506 WebTextInputType WebViewImpl::textInputType() | |
507 { | |
508 Element* element = focusedElement(); | |
509 if (!element) | |
510 return WebTextInputTypeNone; | |
511 | |
512 if (element->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) | |
513 return WebTextInputTypeContentEditable; | |
514 | |
515 return WebTextInputTypeNone; | |
516 } | |
517 | |
518 int WebViewImpl::textInputFlags() | |
519 { | |
520 Element* element = focusedElement(); | |
521 if (!element) | |
522 return WebTextInputFlagNone; | |
523 | |
524 int flags = 0; | |
525 | |
526 const AtomicString& autocomplete = element->getAttribute("autocomplete"); | |
527 if (autocomplete == "on") | |
528 flags |= WebTextInputFlagAutocompleteOn; | |
529 else if (autocomplete == "off") | |
530 flags |= WebTextInputFlagAutocompleteOff; | |
531 | |
532 const AtomicString& autocorrect = element->getAttribute("autocorrect"); | |
533 if (autocorrect == "on") | |
534 flags |= WebTextInputFlagAutocorrectOn; | |
535 else if (autocorrect == "off") | |
536 flags |= WebTextInputFlagAutocorrectOff; | |
537 | |
538 const AtomicString& spellcheck = element->getAttribute("spellcheck"); | |
539 if (spellcheck == "on") | |
540 flags |= WebTextInputFlagSpellcheckOn; | |
541 else if (spellcheck == "off") | |
542 flags |= WebTextInputFlagSpellcheckOff; | |
543 | |
544 return flags; | |
545 } | |
546 | |
547 WebString WebViewImpl::inputModeOfFocusedElement() | |
548 { | |
549 return WebString(); | |
550 } | |
551 | |
552 WebVector<WebCompositionUnderline> WebViewImpl::compositionUnderlines() const | |
553 { | |
554 const LocalFrame* focused = focusedCoreFrame(); | |
555 if (!focused) | |
556 return WebVector<WebCompositionUnderline>(); | |
557 const Vector<CompositionUnderline>& underlines = focused->inputMethodControl
ler().customCompositionUnderlines(); | |
558 WebVector<WebCompositionUnderline> results(underlines.size()); | |
559 for (size_t index = 0; index < underlines.size(); ++index) { | |
560 CompositionUnderline underline = underlines[index]; | |
561 results[index] = WebCompositionUnderline(underline.startOffset, underlin
e.endOffset, static_cast<WebColor>(underline.color.rgb()), underline.thick, stat
ic_cast<WebColor>(underline.backgroundColor.rgb())); | |
562 } | |
563 return results; | |
564 } | |
565 | |
566 // WebView -------------------------------------------------------------------- | |
567 | |
568 WebSettingsImpl* WebViewImpl::settingsImpl() | |
569 { | |
570 if (!m_webSettings) | |
571 m_webSettings = adoptPtr(new WebSettingsImpl(&m_page->settings())); | |
572 ASSERT(m_webSettings); | |
573 return m_webSettings.get(); | |
574 } | |
575 | |
576 WebSettings* WebViewImpl::settings() | |
577 { | |
578 return settingsImpl(); | |
579 } | |
580 | |
581 WebFrame* WebViewImpl::mainFrame() | |
582 { | |
583 return WebFrame::fromFrame(m_page ? m_page->mainFrame() : 0); | |
584 } | |
585 | |
586 WebFrame* WebViewImpl::focusedFrame() | |
587 { | |
588 return WebFrame::fromFrame(focusedCoreFrame()); | |
589 } | |
590 | |
591 void WebViewImpl::injectModule(const WebString& path) | |
592 { | |
593 RefPtr<Document> document = m_page->mainFrame()->document(); | |
594 RefPtr<HTMLImportElement> import = HTMLImportElement::create(*document); | |
595 import->setAttribute(HTMLNames::srcAttr, path); | |
596 document->appendChild(import.release()); | |
597 } | |
598 | |
599 void WebViewImpl::setFocusedFrame(WebFrame* frame) | |
600 { | |
601 if (!frame) { | |
602 // Clears the focused frame if any. | |
603 LocalFrame* focusedFrame = focusedCoreFrame(); | |
604 if (focusedFrame) | |
605 focusedFrame->selection().setFocused(false); | |
606 return; | |
607 } | |
608 LocalFrame* coreFrame = toWebLocalFrameImpl(frame)->frame(); | |
609 coreFrame->page()->focusController().setFocusedFrame(coreFrame); | |
610 } | |
611 | |
612 void WebViewImpl::setInitialFocus(bool reverse) | |
613 { | |
614 if (!m_page) | |
615 return; | |
616 LocalFrame* frame = page()->focusController().focusedOrMainFrame(); | |
617 if (Document* document = frame->document()) | |
618 document->setFocusedElement(nullptr); | |
619 page()->focusController().setInitialFocus(reverse ? FocusTypeBackward : Focu
sTypeForward); | |
620 } | |
621 | |
622 void WebViewImpl::clearFocusedElement() | |
623 { | |
624 RefPtr<LocalFrame> localFrame = focusedCoreFrame(); | |
625 if (!localFrame) | |
626 return; | |
627 | |
628 RefPtr<Document> document = localFrame->document(); | |
629 if (!document) | |
630 return; | |
631 | |
632 RefPtr<Element> oldFocusedElement = document->focusedElement(); | |
633 | |
634 // Clear the focused node. | |
635 document->setFocusedElement(nullptr); | |
636 | |
637 if (!oldFocusedElement) | |
638 return; | |
639 | |
640 // If a text field has focus, we need to make sure the selection controller | |
641 // knows to remove selection from it. Otherwise, the text field is still | |
642 // processing keyboard events even though focus has been moved to the page a
nd | |
643 // keystrokes get eaten as a result. | |
644 if (oldFocusedElement->isContentEditable()) | |
645 localFrame->selection().clear(); | |
646 } | |
647 | |
648 void WebViewImpl::advanceFocus(bool reverse) | |
649 { | |
650 page()->focusController().advanceFocus(reverse ? FocusTypeBackward : FocusTy
peForward); | |
651 } | |
652 | |
653 IntPoint WebViewImpl::clampOffsetAtScale(const IntPoint& offset, float scale) | |
654 { | |
655 FrameView* view = mainFrameImpl()->frameView(); | |
656 if (!view) | |
657 return offset; | |
658 | |
659 return view->clampOffsetAtScale(offset, scale); | |
660 } | |
661 | |
662 float WebViewImpl::deviceScaleFactor() const | |
663 { | |
664 if (!page()) | |
665 return 1; | |
666 | |
667 return page()->deviceScaleFactor(); | |
668 } | |
669 | |
670 void WebViewImpl::setDeviceScaleFactor(float scaleFactor) | |
671 { | |
672 if (!page()) | |
673 return; | |
674 | |
675 page()->setDeviceScaleFactor(scaleFactor); | |
676 } | |
677 | |
678 void WebViewImpl::updateMainFrameLayoutSize() | |
679 { | |
680 if (m_fixedLayoutSizeLock || !mainFrameImpl()) | |
681 return; | |
682 | |
683 RefPtr<FrameView> view = mainFrameImpl()->frameView(); | |
684 if (!view) | |
685 return; | |
686 | |
687 WebSize layoutSize = m_size; | |
688 | |
689 if (page()->settings().forceZeroLayoutHeight()) | |
690 layoutSize.height = 0; | |
691 | |
692 view->setLayoutSize(layoutSize); | |
693 } | |
694 | |
695 IntSize WebViewImpl::contentsSize() const | |
696 { | |
697 RenderView* root = page()->mainFrame()->contentRenderer(); | |
698 if (!root) | |
699 return IntSize(); | |
700 return root->documentRect().size(); | |
701 } | |
702 | |
703 void WebViewImpl::spellingMarkers(WebVector<uint32_t>* markers) | |
704 { | |
705 Vector<uint32_t> result; | |
706 LocalFrame* frame = m_page->mainFrame(); | |
707 const DocumentMarkerVector& documentMarkers = frame->document()->markers().m
arkers(); | |
708 for (size_t i = 0; i < documentMarkers.size(); ++i) | |
709 result.append(documentMarkers[i]->hash()); | |
710 markers->assign(result); | |
711 } | |
712 | |
713 void WebViewImpl::removeSpellingMarkersUnderWords(const WebVector<WebString>& wo
rds) | |
714 { | |
715 Vector<String> convertedWords; | |
716 convertedWords.append(words.data(), words.size()); | |
717 | |
718 LocalFrame* frame = m_page->mainFrame(); | |
719 frame->removeSpellingMarkersUnderWords(convertedWords); | |
720 } | |
721 | |
722 void WebViewImpl::sendResizeEventAndRepaint() | |
723 { | |
724 // FIXME: This is wrong. The FrameView is responsible sending a resizeEvent | |
725 // as part of layout. Layout is also responsible for sending invalidations | |
726 // to the embedder. This method and all callers may be wrong. -- eseidel. | |
727 if (m_page->mainFrame()->view()) { | |
728 // Enqueues the resize event. | |
729 m_page->mainFrame()->document()->enqueueResizeEvent(); | |
730 } | |
731 } | |
732 | |
733 void WebViewImpl::setIsTransparent(bool isTransparent) | |
734 { | |
735 // Set any existing frames to be transparent. | |
736 m_page->mainFrame()->view()->setTransparent(isTransparent); | |
737 | |
738 // Future frames check this to know whether to be transparent. | |
739 m_isTransparent = isTransparent; | |
740 } | |
741 | |
742 bool WebViewImpl::isTransparent() const | |
743 { | |
744 return m_isTransparent; | |
745 } | |
746 | |
747 // FIXME(sky): This is an android webview feature. Remove it. | |
748 void WebViewImpl::setBaseBackgroundColor(WebColor color) | |
749 { | |
750 layout(); | |
751 | |
752 if (m_baseBackgroundColor == color) | |
753 return; | |
754 | |
755 m_baseBackgroundColor = color; | |
756 | |
757 if (m_page->mainFrame()) | |
758 m_page->mainFrame()->view()->setBaseBackgroundColor(color); | |
759 } | |
760 | |
761 void WebViewImpl::setIsActive(bool active) | |
762 { | |
763 if (page()) | |
764 page()->focusController().setActive(active); | |
765 } | |
766 | |
767 bool WebViewImpl::isActive() const | |
768 { | |
769 return page() ? page()->focusController().isActive() : false; | |
770 } | |
771 | |
772 void WebViewImpl::didCommitLoad(bool isNewNavigation, bool isNavigationWithinPag
e) | |
773 { | |
774 } | |
775 | |
776 void WebViewImpl::setBackgroundColorOverride(WebColor color) | |
777 { | |
778 m_backgroundColorOverride = color; | |
779 } | |
780 | |
781 Element* WebViewImpl::focusedElement() const | |
782 { | |
783 LocalFrame* frame = m_page->focusController().focusedFrame(); | |
784 if (!frame) | |
785 return 0; | |
786 | |
787 Document* document = frame->document(); | |
788 if (!document) | |
789 return 0; | |
790 | |
791 return document->focusedElement(); | |
792 } | |
793 | |
794 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos) | |
795 { | |
796 IntPoint docPoint(m_page->mainFrame()->view()->windowToContents(pos)); | |
797 HitTestResult result = m_page->mainFrame()->eventHandler().hitTestResultAtPo
int(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active); | |
798 return result; | |
799 } | |
800 | |
801 void WebViewImpl::scheduleVisualUpdate() | |
802 { | |
803 m_client->scheduleVisualUpdate(); | |
804 } | |
805 | |
806 void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState, | |
807 bool isInitialState) { | |
808 if (!page()) | |
809 return; | |
810 | |
811 ASSERT(visibilityState == WebPageVisibilityStateVisible || visibilityState =
= WebPageVisibilityStateHidden); | |
812 m_page->setVisibilityState(static_cast<PageVisibilityState>(static_cast<int>
(visibilityState)), isInitialState); | |
813 } | |
814 | |
815 } // namespace blink | |
OLD | NEW |