2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include "web/ValidationMessageClientImpl.h"
29 #include "core/dom/Element.h"
30 #include "core/frame/FrameView.h"
31 #include "core/layout/LayoutObject.h"
32 #include "platform/HostWindow.h"
33 #include "public/platform/WebRect.h"
34 #include "public/platform/WebString.h"
35 #include "public/web/WebTextDirection.h"
36 #include "public/web/WebViewClient.h"
37 #include "web/WebViewImpl.h"
38 #include "wtf/CurrentTime.h"
42 ValidationMessageClientImpl::ValidationMessageClientImpl(WebViewImpl
& webView
)
44 , m_currentAnchor(nullptr)
45 , m_lastPageScaleFactor(1)
47 , m_timer(this, &ValidationMessageClientImpl::checkAnchorStatus
)
51 PassOwnPtrWillBeRawPtr
<ValidationMessageClientImpl
> ValidationMessageClientImpl::create(WebViewImpl
& webView
)
53 return adoptPtrWillBeNoop(new ValidationMessageClientImpl(webView
));
56 ValidationMessageClientImpl::~ValidationMessageClientImpl()
60 FrameView
* ValidationMessageClientImpl::currentView()
62 return m_currentAnchor
->document().view();
65 void ValidationMessageClientImpl::showValidationMessage(const Element
& anchor
, const String
& message
, TextDirection messageDir
, const String
& subMessage
, TextDirection subMessageDir
)
67 if (message
.isEmpty()) {
68 hideValidationMessage(anchor
);
71 if (!anchor
.layoutBox())
74 hideValidationMessage(*m_currentAnchor
);
75 m_currentAnchor
= &anchor
;
76 IntRect anchorInViewport
= currentView()->contentsToViewport(anchor
.pixelSnappedBoundingBox());
77 m_lastAnchorRectInScreen
= currentView()->hostWindow()->viewportToScreen(anchorInViewport
);
78 m_lastPageScaleFactor
= m_webView
.pageScaleFactor();
80 const double minimumSecondToShowValidationMessage
= 5.0;
81 const double secondPerCharacter
= 0.05;
82 const double statusCheckInterval
= 0.1;
84 m_webView
.client()->showValidationMessage(anchorInViewport
, m_message
, toWebTextDirection(messageDir
),
85 subMessage
, toWebTextDirection(subMessageDir
));
87 m_finishTime
= monotonicallyIncreasingTime() + std::max(minimumSecondToShowValidationMessage
, (message
.length() + subMessage
.length()) * secondPerCharacter
);
88 // FIXME: We should invoke checkAnchorStatus actively when layout, scroll,
89 // or page scale change happen.
90 m_timer
.startRepeating(statusCheckInterval
, FROM_HERE
);
93 void ValidationMessageClientImpl::hideValidationMessage(const Element
& anchor
)
95 if (!m_currentAnchor
|| !isValidationMessageVisible(anchor
))
98 m_currentAnchor
= nullptr;
101 m_webView
.client()->hideValidationMessage();
104 bool ValidationMessageClientImpl::isValidationMessageVisible(const Element
& anchor
)
106 return m_currentAnchor
== &anchor
;
109 void ValidationMessageClientImpl::documentDetached(const Document
& document
)
111 if (m_currentAnchor
&& m_currentAnchor
->document() == document
)
112 hideValidationMessage(*m_currentAnchor
);
115 void ValidationMessageClientImpl::checkAnchorStatus(Timer
<ValidationMessageClientImpl
>*)
117 ASSERT(m_currentAnchor
);
118 if (monotonicallyIncreasingTime() >= m_finishTime
|| !currentView()) {
119 hideValidationMessage(*m_currentAnchor
);
123 // Check the visibility of the element.
124 // FIXME: Can we check invisibility by scrollable non-frame elements?
125 IntRect newAnchorRectInViewport
= currentView()->contentsToViewport(m_currentAnchor
->pixelSnappedBoundingBox());
127 // FIXME: This intersection eliminates the part of the rect outside the root view.
128 // If this is meant as a visiblity test, intersecting it against the viewport rect
129 // likely makes more sense.
130 newAnchorRectInViewport
= intersection(currentView()->convertToContainingWindow(currentView()->boundsRect()), newAnchorRectInViewport
);
131 if (newAnchorRectInViewport
.isEmpty()) {
132 hideValidationMessage(*m_currentAnchor
);
136 IntRect newAnchorRectInViewportInScreen
= currentView()->hostWindow()->viewportToScreen(newAnchorRectInViewport
);
137 if (newAnchorRectInViewportInScreen
== m_lastAnchorRectInScreen
&& m_webView
.pageScaleFactor() == m_lastPageScaleFactor
)
139 m_lastAnchorRectInScreen
= newAnchorRectInViewportInScreen
;
140 m_lastPageScaleFactor
= m_webView
.pageScaleFactor();
141 m_webView
.client()->moveValidationMessage(newAnchorRectInViewport
);
144 void ValidationMessageClientImpl::willBeDestroyed()
147 hideValidationMessage(*m_currentAnchor
);
150 DEFINE_TRACE(ValidationMessageClientImpl
)
152 visitor
->trace(m_currentAnchor
);
153 ValidationMessageClient::trace(visitor
);