summaryrefslogtreecommitdiffstats
path: root/WebCore/page
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebCore/page
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/page')
-rw-r--r--WebCore/page/AbstractView.idl1
-rw-r--r--WebCore/page/BarInfo.cpp28
-rw-r--r--WebCore/page/Chrome.cpp56
-rw-r--r--WebCore/page/ChromeClient.h9
-rw-r--r--WebCore/page/Console.cpp177
-rw-r--r--WebCore/page/Console.h22
-rw-r--r--WebCore/page/Console.idl4
-rw-r--r--WebCore/page/ContextMenuClient.h1
-rw-r--r--WebCore/page/ContextMenuController.cpp397
-rw-r--r--WebCore/page/ContextMenuController.h2
-rw-r--r--WebCore/page/Coordinates.cpp2
-rw-r--r--WebCore/page/DOMSelection.cpp56
-rw-r--r--WebCore/page/DOMSelection.h2
-rw-r--r--WebCore/page/DOMTimer.cpp35
-rw-r--r--WebCore/page/DOMTimer.h60
-rw-r--r--WebCore/page/DOMWindow.cpp64
-rw-r--r--WebCore/page/DOMWindow.h6
-rw-r--r--WebCore/page/DOMWindow.idl18
-rw-r--r--WebCore/page/DragController.cpp338
-rw-r--r--WebCore/page/DragController.h4
-rw-r--r--WebCore/page/EventHandler.cpp169
-rw-r--r--WebCore/page/EventHandler.h19
-rw-r--r--WebCore/page/FocusController.cpp36
-rw-r--r--WebCore/page/FocusController.h4
-rw-r--r--WebCore/page/Frame.cpp208
-rw-r--r--WebCore/page/Frame.h435
-rw-r--r--WebCore/page/FrameTree.h2
-rw-r--r--WebCore/page/FrameView.cpp300
-rw-r--r--WebCore/page/FrameView.h44
-rw-r--r--WebCore/page/Geolocation.cpp56
-rw-r--r--WebCore/page/Geolocation.h3
-rw-r--r--WebCore/page/History.idl4
-rw-r--r--WebCore/page/Location.cpp4
-rw-r--r--WebCore/page/Location.idl6
-rw-r--r--WebCore/page/MouseEventWithHitTestResults.h5
-rw-r--r--WebCore/page/NavigatorBase.cpp14
-rw-r--r--WebCore/page/Page.cpp39
-rw-r--r--WebCore/page/Page.h30
-rw-r--r--WebCore/page/PageGroup.cpp15
-rw-r--r--WebCore/page/PageGroup.h8
-rw-r--r--WebCore/page/PageGroupLoadDeferrer.h2
-rw-r--r--WebCore/page/PrintContext.cpp2
-rw-r--r--WebCore/page/SecurityOrigin.cpp93
-rw-r--r--WebCore/page/SecurityOrigin.h7
-rw-r--r--WebCore/page/Settings.cpp37
-rw-r--r--WebCore/page/Settings.h20
-rw-r--r--WebCore/page/XSSAuditor.cpp267
-rw-r--r--WebCore/page/XSSAuditor.h118
-rw-r--r--WebCore/page/android/DragControllerAndroid.cpp2
-rw-r--r--WebCore/page/android/EventHandlerAndroid.cpp9
-rw-r--r--WebCore/page/animation/AnimationBase.cpp55
-rw-r--r--WebCore/page/animation/AnimationBase.h3
-rw-r--r--WebCore/page/animation/AnimationController.cpp18
-rw-r--r--WebCore/page/animation/CompositeAnimation.cpp316
-rw-r--r--WebCore/page/animation/CompositeAnimation.h2
-rw-r--r--WebCore/page/animation/ImplicitAnimation.cpp5
-rw-r--r--WebCore/page/animation/ImplicitAnimation.h4
-rw-r--r--WebCore/page/animation/KeyframeAnimation.cpp12
-rw-r--r--WebCore/page/chromium/EventHandlerChromium.cpp3
-rw-r--r--WebCore/page/chromium/FrameChromium.cpp2
-rw-r--r--WebCore/page/gtk/DragControllerGtk.cpp2
-rw-r--r--WebCore/page/gtk/EventHandlerGtk.cpp3
-rw-r--r--WebCore/page/haiku/DragControllerHaiku.cpp77
-rw-r--r--WebCore/page/haiku/EventHandlerHaiku.cpp150
-rw-r--r--WebCore/page/haiku/FrameHaiku.cpp43
-rw-r--r--WebCore/page/mac/EventHandlerMac.mm22
-rw-r--r--WebCore/page/mac/FrameMac.mm12
-rw-r--r--WebCore/page/mac/WebCoreViewFactory.h3
-rw-r--r--WebCore/page/qt/DragControllerQt.cpp3
-rw-r--r--WebCore/page/win/DragControllerWin.cpp3
-rw-r--r--WebCore/page/win/EventHandlerWin.cpp5
-rw-r--r--WebCore/page/win/FrameCGWin.cpp3
-rw-r--r--WebCore/page/win/FrameWin.cpp2
-rw-r--r--WebCore/page/win/FrameWin.h2
-rw-r--r--WebCore/page/win/PageWin.cpp24
-rw-r--r--WebCore/page/wince/FrameWince.cpp185
-rw-r--r--WebCore/page/wx/EventHandlerWx.cpp2
77 files changed, 2941 insertions, 1260 deletions
diff --git a/WebCore/page/AbstractView.idl b/WebCore/page/AbstractView.idl
index 5b7ce89..36865de 100644
--- a/WebCore/page/AbstractView.idl
+++ b/WebCore/page/AbstractView.idl
@@ -31,6 +31,7 @@ module views {
ObjCCustomImplementation
] AbstractView {
readonly attribute Document document;
+ readonly attribute Media media;
};
}
diff --git a/WebCore/page/BarInfo.cpp b/WebCore/page/BarInfo.cpp
index f6a1210..0f6cad5 100644
--- a/WebCore/page/BarInfo.cpp
+++ b/WebCore/page/BarInfo.cpp
@@ -62,20 +62,20 @@ bool BarInfo::visible() const
return false;
switch (m_type) {
- case Locationbar:
- return m_frame->page()->chrome()->toolbarsVisible();
- case Toolbar:
- return m_frame->page()->chrome()->toolbarsVisible();
- case Personalbar:
- return m_frame->page()->chrome()->toolbarsVisible();
- case Menubar:
- return m_frame->page()->chrome()->menubarVisible();
- case Scrollbars:
- return m_frame->page()->chrome()->scrollbarsVisible();
- case Statusbar:
- return m_frame->page()->chrome()->statusbarVisible();
- default:
- return false;
+ case Locationbar:
+ return m_frame->page()->chrome()->toolbarsVisible();
+ case Toolbar:
+ return m_frame->page()->chrome()->toolbarsVisible();
+ case Personalbar:
+ return m_frame->page()->chrome()->toolbarsVisible();
+ case Menubar:
+ return m_frame->page()->chrome()->menubarVisible();
+ case Scrollbars:
+ return m_frame->page()->chrome()->scrollbarsVisible();
+ case Statusbar:
+ return m_frame->page()->chrome()->statusbarVisible();
+ default:
+ return false;
}
}
diff --git a/WebCore/page/Chrome.cpp b/WebCore/page/Chrome.cpp
index 86de82e..5a5670e 100644
--- a/WebCore/page/Chrome.cpp
+++ b/WebCore/page/Chrome.cpp
@@ -36,6 +36,7 @@
#include "InspectorController.h"
#include "Page.h"
#include "PageGroupLoadDeferrer.h"
+#include "RenderObject.h"
#include "ResourceHandle.h"
#include "ScriptController.h"
#include "SecurityOrigin.h"
@@ -46,7 +47,7 @@
#include <wtf/Vector.h>
#if ENABLE(DOM_STORAGE)
-#include "SessionStorage.h"
+#include "StorageNamespace.h"
#endif
namespace WebCore {
@@ -115,12 +116,12 @@ FloatRect Chrome::pageRect() const
{
return m_client->pageRect();
}
-
+
float Chrome::scaleFactor()
{
return m_client->scaleFactor();
}
-
+
void Chrome::focus() const
{
m_client->focus();
@@ -140,15 +141,15 @@ void Chrome::takeFocus(FocusDirection direction) const
{
m_client->takeFocus(direction);
}
-
+
Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features) const
{
Page* newPage = m_client->createWindow(frame, request, features);
#if ENABLE(DOM_STORAGE)
if (newPage) {
- if (SessionStorage* oldSessionStorage = m_page->sessionStorage(false))
- newPage->setSessionStorage(oldSessionStorage->copy(newPage));
+ if (StorageNamespace* oldSessionStorage = m_page->sessionStorage(false))
+ newPage->setSessionStorage(oldSessionStorage->copy());
}
#endif
@@ -234,7 +235,7 @@ bool Chrome::canRunBeforeUnloadConfirmPanel()
bool Chrome::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
{
- // Defer loads in case the client method runs a new event loop that would
+ // Defer loads in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of executing JavaScript.
PageGroupLoadDeferrer deferrer(m_page, true);
@@ -248,7 +249,7 @@ void Chrome::closeWindowSoon()
void Chrome::runJavaScriptAlert(Frame* frame, const String& message)
{
- // Defer loads in case the client method runs a new event loop that would
+ // Defer loads in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of executing JavaScript.
PageGroupLoadDeferrer deferrer(m_page, true);
@@ -258,7 +259,7 @@ void Chrome::runJavaScriptAlert(Frame* frame, const String& message)
bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message)
{
- // Defer loads in case the client method runs a new event loop that would
+ // Defer loads in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of executing JavaScript.
PageGroupLoadDeferrer deferrer(m_page, true);
@@ -268,16 +269,16 @@ bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message)
bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultValue, String& result)
{
- // Defer loads in case the client method runs a new event loop that would
+ // Defer loads in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of executing JavaScript.
PageGroupLoadDeferrer deferrer(m_page, true);
ASSERT(frame);
bool ok = m_client->runJavaScriptPrompt(frame, frame->displayStringModifiedByEncoding(prompt), frame->displayStringModifiedByEncoding(defaultValue), result);
-
+
if (ok)
result = frame->displayStringModifiedByEncoding(result);
-
+
return ok;
}
@@ -289,7 +290,7 @@ void Chrome::setStatusbarText(Frame* frame, const String& status)
bool Chrome::shouldInterruptJavaScript()
{
- // Defer loads in case the client method runs a new event loop that would
+ // Defer loads in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of executing JavaScript.
PageGroupLoadDeferrer deferrer(m_page, true);
@@ -317,7 +318,8 @@ void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modif
void Chrome::setToolTip(const HitTestResult& result)
{
// First priority is a potential toolTip representing a spelling or grammar error
- String toolTip = result.spellingToolTip();
+ TextDirection toolTipDirection;
+ String toolTip = result.spellingToolTip(toolTipDirection);
// Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those).
if (toolTip.isEmpty() && m_page->settings()->showsURLsInToolTips()) {
@@ -326,20 +328,28 @@ void Chrome::setToolTip(const HitTestResult& result)
if (node->hasTagName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
if (input->inputType() == HTMLInputElement::SUBMIT)
- if (HTMLFormElement* form = input->form())
+ if (HTMLFormElement* form = input->form()) {
toolTip = form->action();
+ if (form->renderer())
+ toolTipDirection = form->renderer()->style()->direction();
+ else
+ toolTipDirection = LTR;
+ }
}
}
// Get tooltip representing link's URL
- if (toolTip.isEmpty())
+ if (toolTip.isEmpty()) {
// FIXME: Need to pass this URL through userVisibleString once that's in WebCore
toolTip = result.absoluteLinkURL().string();
+ // URL always display as LTR.
+ toolTipDirection = LTR;
+ }
}
// Next we'll consider a tooltip for element with "title" attribute
if (toolTip.isEmpty())
- toolTip = result.title();
+ toolTip = result.title(toolTipDirection);
// Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames
if (toolTip.isEmpty()) {
@@ -357,13 +367,15 @@ void Chrome::setToolTip(const HitTestResult& result)
names.append('\n');
}
toolTip = String::adopt(names);
+ // filename always display as LTR.
+ toolTipDirection = LTR;
}
}
}
}
}
-
- m_client->setToolTip(toolTip);
+
+ m_client->setToolTip(toolTip, toolTipDirection);
}
void Chrome::print(Frame* frame)
@@ -373,7 +385,7 @@ void Chrome::print(Frame* frame)
void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
{
- // Defer loads in case the client method runs a new event loop that would
+ // Defer loads in case the client method runs a new event loop that would
// otherwise cause the load to continue while we're in the middle of executing JavaScript.
PageGroupLoadDeferrer deferrer(m_page, true);
@@ -420,10 +432,10 @@ bool ChromeClient::shouldReplaceWithGeneratedFileForUpload(const String&, String
String ChromeClient::generateReplacementFile(const String&)
{
ASSERT_NOT_REACHED();
- return String();
+ return String();
}
-bool ChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize,
+bool ChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize,
ScrollbarControlState, ScrollbarPart, bool,
float, float, ScrollbarControlPartMask)
{
diff --git a/WebCore/page/ChromeClient.h b/WebCore/page/ChromeClient.h
index 46f37f3..409a492 100644
--- a/WebCore/page/ChromeClient.h
+++ b/WebCore/page/ChromeClient.h
@@ -103,7 +103,7 @@ namespace WebCore {
virtual void setResizable(bool) = 0;
- virtual void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID) = 0;
+ virtual void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID) = 0;
virtual bool canRunBeforeUnloadConfirmPanel() = 0;
virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame) = 0;
@@ -131,7 +131,7 @@ namespace WebCore {
virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) = 0;
- virtual void setToolTip(const String&) = 0;
+ virtual void setToolTip(const String&, TextDirection) = 0;
virtual void print(Frame*) = 0;
@@ -177,6 +177,9 @@ namespace WebCore {
// Notification that the given form element has changed. This function
// will be called frequently, so handling should be very fast.
virtual void formStateDidChange(const Node*) = 0;
+
+ virtual void formDidFocus(const Node*) { };
+ virtual void formDidBlur(const Node*) { };
virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() = 0;
@@ -188,7 +191,7 @@ namespace WebCore {
virtual void setNeedsOneShotDrawingSynchronization() = 0;
// Sets a flag to specify that the view needs to be updated, so we need
// to do an eager layout before the drawing.
- virtual void scheduleViewUpdate() = 0;
+ virtual void scheduleCompositingLayerSync() = 0;
#endif
#if PLATFORM(MAC)
diff --git a/WebCore/page/Console.cpp b/WebCore/page/Console.cpp
index 99a0fc8..b5c9bb2 100644
--- a/WebCore/page/Console.cpp
+++ b/WebCore/page/Console.cpp
@@ -29,8 +29,9 @@
#include "config.h"
#include "Console.h"
-#include "ChromeClient.h"
#include "CString.h"
+#include "ChromeClient.h"
+#include "ConsoleMessage.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameTree.h"
@@ -90,75 +91,63 @@ static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel
{
const char* sourceString;
switch (source) {
- case HTMLMessageSource:
- sourceString = "HTML";
- break;
- case WMLMessageSource:
- sourceString = "WML";
- break;
- case XMLMessageSource:
- sourceString = "XML";
- break;
- case JSMessageSource:
- sourceString = "JS";
- break;
- case CSSMessageSource:
- sourceString = "CSS";
- break;
- case OtherMessageSource:
- sourceString = "OTHER";
- break;
- default:
- ASSERT_NOT_REACHED();
- sourceString = "UNKNOWN";
- break;
+ case HTMLMessageSource:
+ sourceString = "HTML";
+ break;
+ case WMLMessageSource:
+ sourceString = "WML";
+ break;
+ case XMLMessageSource:
+ sourceString = "XML";
+ break;
+ case JSMessageSource:
+ sourceString = "JS";
+ break;
+ case CSSMessageSource:
+ sourceString = "CSS";
+ break;
+ case OtherMessageSource:
+ sourceString = "OTHER";
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ sourceString = "UNKNOWN";
+ break;
}
const char* levelString;
switch (level) {
- case TipMessageLevel:
- levelString = "TIP";
- break;
- case LogMessageLevel:
- levelString = "LOG";
- break;
- case WarningMessageLevel:
- levelString = "WARN";
- break;
- case ErrorMessageLevel:
- levelString = "ERROR";
- break;
- case ObjectMessageLevel:
- levelString = "OBJECT";
- break;
- case TraceMessageLevel:
- levelString = "TRACE";
- break;
- case StartGroupMessageLevel:
- levelString = "START GROUP";
- break;
- case EndGroupMessageLevel:
- levelString = "END GROUP";
- break;
- default:
- ASSERT_NOT_REACHED();
- levelString = "UNKNOWN";
- break;
+ case TipMessageLevel:
+ levelString = "TIP";
+ break;
+ case LogMessageLevel:
+ levelString = "LOG";
+ break;
+ case WarningMessageLevel:
+ levelString = "WARN";
+ break;
+ case ErrorMessageLevel:
+ levelString = "ERROR";
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ levelString = "UNKNOWN";
+ break;
}
printf("%s %s:", sourceString, levelString);
}
-void Console::addMessage(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
+void Console::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
{
Page* page = this->page();
if (!page)
return;
- if (source == JSMessageSource || source == WMLMessageSource)
- page->chrome()->client()->addMessageToConsole(source, level, message, lineNumber, sourceURL);
+ if (source == JSMessageSource)
+ page->chrome()->client()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL);
- page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL);
+ page->inspectorController()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL);
if (!Console::shouldPrintExceptions())
return;
@@ -169,7 +158,8 @@ void Console::addMessage(MessageSource source, MessageLevel level, const String&
printf(" %s\n", message.utf8().data());
}
-void Console::addMessage(MessageLevel level, ScriptCallStack* callStack, bool acceptNoArguments) {
+void Console::addMessage(MessageType type, MessageLevel level, ScriptCallStack* callStack, bool acceptNoArguments)
+{
Page* page = this->page();
if (!page)
return;
@@ -181,9 +171,9 @@ void Console::addMessage(MessageLevel level, ScriptCallStack* callStack, bool ac
String message;
if (getFirstArgumentAsString(callStack->state(), lastCaller, message))
- page->chrome()->client()->addMessageToConsole(JSMessageSource, level, message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL());
+ page->chrome()->client()->addMessageToConsole(JSMessageSource, type, level, message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL());
- page->inspectorController()->addMessageToConsole(JSMessageSource, level, callStack);
+ page->inspectorController()->addMessageToConsole(JSMessageSource, type, level, callStack);
if (!Console::shouldPrintExceptions())
return;
@@ -207,7 +197,7 @@ void Console::debug(ScriptCallStack* callStack)
void Console::error(ScriptCallStack* callStack)
{
- addMessage(ErrorMessageLevel, callStack);
+ addMessage(LogMessageType, ErrorMessageLevel, callStack);
}
void Console::info(ScriptCallStack* callStack)
@@ -217,12 +207,12 @@ void Console::info(ScriptCallStack* callStack)
void Console::log(ScriptCallStack* callStack)
{
- addMessage(LogMessageLevel, callStack);
+ addMessage(LogMessageType, LogMessageLevel, callStack);
}
void Console::dir(ScriptCallStack* callStack)
{
- addMessage(ObjectMessageLevel, callStack);
+ addMessage(ObjectMessageType, LogMessageLevel, callStack);
}
void Console::dirxml(ScriptCallStack* callStack)
@@ -233,7 +223,7 @@ void Console::dirxml(ScriptCallStack* callStack)
void Console::trace(ScriptCallStack* callStack)
{
- addMessage(TraceMessageLevel, callStack, true);
+ addMessage(TraceMessageType, LogMessageLevel, callStack, true);
if (!shouldPrintExceptions())
return;
@@ -251,7 +241,7 @@ void Console::assertCondition(bool condition, ScriptCallStack* callStack)
return;
// FIXME: <https://bugs.webkit.org/show_bug.cgi?id=19135> It would be nice to prefix assertion failures with a message like "Assertion failed: ".
- addMessage(ErrorMessageLevel, callStack, true);
+ addMessage(LogMessageType, ErrorMessageLevel, callStack, true);
}
void Console::count(ScriptCallStack* callStack)
@@ -269,6 +259,32 @@ void Console::count(ScriptCallStack* callStack)
page->inspectorController()->count(title, lastCaller.lineNumber(), lastCaller.sourceURL().string());
}
+#if ENABLE(WML)
+String Console::lastWMLErrorMessage() const
+{
+ Page* page = this->page();
+ if (!page)
+ return String();
+
+ const Vector<ConsoleMessage*>& consoleMessages = page->inspectorController()->consoleMessages();
+ if (consoleMessages.isEmpty())
+ return String();
+
+ Vector<ConsoleMessage*>::const_iterator it = consoleMessages.begin();
+ const Vector<ConsoleMessage*>::const_iterator end = consoleMessages.end();
+
+ for (; it != end; ++it) {
+ ConsoleMessage* message = *it;
+ if (message->source() != WMLMessageSource)
+ continue;
+
+ return message->message();
+ }
+
+ return String();
+}
+#endif
+
#if ENABLE(JAVASCRIPT_DEBUGGER)
void Console::profile(const JSC::UString& title, ScriptCallStack* callStack)
@@ -277,16 +293,19 @@ void Console::profile(const JSC::UString& title, ScriptCallStack* callStack)
if (!page)
return;
+ InspectorController* controller = page->inspectorController();
// FIXME: log a console message when profiling is disabled.
- if (!page->inspectorController()->profilerEnabled())
+ if (!controller->profilerEnabled())
return;
- if (title.isNull()) { // no title so give it the next user initiated profile title.
- page->inspectorController()->startUserInitiatedProfiling(0);
- return;
- }
+ JSC::UString resolvedTitle = title;
+ if (title.isNull()) // no title so give it the next user initiated profile title.
+ resolvedTitle = controller->getCurrentUserInitiatedProfileName(true);
+
+ JSC::Profiler::profiler()->startProfiling(callStack->state(), resolvedTitle);
- JSC::Profiler::profiler()->startProfiling(callStack->state(), title);
+ const ScriptCallFrame& lastCaller = callStack->at(0);
+ controller->addStartProfilingMessageToConsole(resolvedTitle, lastCaller.lineNumber(), lastCaller.sourceURL());
}
void Console::profileEnd(const JSC::UString& title, ScriptCallStack* callStack)
@@ -295,7 +314,11 @@ void Console::profileEnd(const JSC::UString& title, ScriptCallStack* callStack)
if (!page)
return;
- if (!page->inspectorController()->profilerEnabled())
+ if (!this->page())
+ return;
+
+ InspectorController* controller = page->inspectorController();
+ if (!controller->profilerEnabled())
return;
RefPtr<JSC::Profile> profile = JSC::Profiler::profiler()->stopProfiling(callStack->state(), title);
@@ -304,14 +327,12 @@ void Console::profileEnd(const JSC::UString& title, ScriptCallStack* callStack)
m_profiles.append(profile);
- if (Page* page = this->page()) {
- const ScriptCallFrame& lastCaller = callStack->at(0);
- page->inspectorController()->addProfile(profile, lastCaller.lineNumber(), lastCaller.sourceURL());
- }
+ const ScriptCallFrame& lastCaller = callStack->at(0);
+ controller->addProfile(profile, lastCaller.lineNumber(), lastCaller.sourceURL());
}
#endif
-
+
void Console::time(const String& title)
{
Page* page = this->page();
@@ -322,7 +343,7 @@ void Console::time(const String& title)
// undefined for timing functions
if (title.isNull())
return;
-
+
page->inspectorController()->startTiming(title);
}
@@ -344,7 +365,7 @@ void Console::timeEnd(const String& title, ScriptCallStack* callStack)
String message = title + String::format(": %.0fms", elapsed);
const ScriptCallFrame& lastCaller = callStack->at(0);
- page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, lastCaller.lineNumber(), lastCaller.sourceURL().string());
+ page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lastCaller.lineNumber(), lastCaller.sourceURL().string());
}
void Console::group(ScriptCallStack* callStack)
@@ -367,7 +388,7 @@ void Console::groupEnd()
void Console::warn(ScriptCallStack* callStack)
{
- addMessage(WarningMessageLevel, callStack);
+ addMessage(LogMessageType, WarningMessageLevel, callStack);
}
static bool printExceptions = false;
diff --git a/WebCore/page/Console.h b/WebCore/page/Console.h
index 79396ea..6d4dbce 100644
--- a/WebCore/page/Console.h
+++ b/WebCore/page/Console.h
@@ -59,16 +59,19 @@ namespace WebCore {
OtherMessageSource
};
+ enum MessageType {
+ LogMessageType,
+ ObjectMessageType,
+ TraceMessageType,
+ StartGroupMessageType,
+ EndGroupMessageType
+ };
+
enum MessageLevel {
TipMessageLevel,
LogMessageLevel,
WarningMessageLevel,
- ErrorMessageLevel,
- // FIXME: the remaining levels should become a new MessageType enum.
- ObjectMessageLevel,
- TraceMessageLevel,
- StartGroupMessageLevel,
- EndGroupMessageLevel
+ ErrorMessageLevel
};
class Console : public RefCounted<Console> {
@@ -78,7 +81,7 @@ namespace WebCore {
Frame* frame() const;
void disconnectFrame();
- void addMessage(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL);
+ void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL);
void debug(ScriptCallStack*);
void error(ScriptCallStack*);
@@ -90,6 +93,9 @@ namespace WebCore {
void trace(ScriptCallStack*);
void assertCondition(bool condition, ScriptCallStack*);
void count(ScriptCallStack*);
+#if ENABLE(WML)
+ String lastWMLErrorMessage() const;
+#endif
#if ENABLE(JAVASCRIPT_DEBUGGER)
void profile(const JSC::UString&, ScriptCallStack*);
void profileEnd(const JSC::UString&, ScriptCallStack*);
@@ -108,7 +114,7 @@ namespace WebCore {
private:
inline Page* page() const;
- void addMessage(MessageLevel, ScriptCallStack*, bool acceptNoArguments = false);
+ void addMessage(MessageType, MessageLevel, ScriptCallStack*, bool acceptNoArguments = false);
Console(Frame*);
diff --git a/WebCore/page/Console.idl b/WebCore/page/Console.idl
index 4803508..0e9f3dc 100644
--- a/WebCore/page/Console.idl
+++ b/WebCore/page/Console.idl
@@ -45,6 +45,10 @@ module window {
[CustomArgumentHandling, ImplementationFunction=assertCondition] void assert(in boolean condition);
[CustomArgumentHandling] void count();
+#if defined(ENABLE_WML) && ENABLE_WML
+ [DontEnum] DOMString lastWMLErrorMessage();
+#endif
+
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
[CustomArgumentHandling] void profile(in [ConvertUndefinedOrNullToNullString] DOMString title);
[CustomArgumentHandling] void profileEnd(in [ConvertUndefinedOrNullToNullString] DOMString title);
diff --git a/WebCore/page/ContextMenuClient.h b/WebCore/page/ContextMenuClient.h
index 775adc5..1997cd0 100644
--- a/WebCore/page/ContextMenuClient.h
+++ b/WebCore/page/ContextMenuClient.h
@@ -47,6 +47,7 @@ namespace WebCore {
virtual void downloadURL(const KURL& url) = 0;
virtual void searchWithGoogle(const Frame*) = 0;
virtual void lookUpInDictionary(Frame*) = 0;
+ virtual bool isSpeaking() = 0;
virtual void speak(const String&) = 0;
virtual void stopSpeaking() = 0;
diff --git a/WebCore/page/ContextMenuController.cpp b/WebCore/page/ContextMenuController.cpp
index 58e6519..0ec9d1c 100644
--- a/WebCore/page/ContextMenuController.cpp
+++ b/WebCore/page/ContextMenuController.cpp
@@ -39,11 +39,11 @@
#include "EventNames.h"
#include "FormState.h"
#include "Frame.h"
-#include "FrameLoader.h"
#include "FrameLoadRequest.h"
+#include "FrameLoader.h"
+#include "HTMLFormElement.h"
#include "HitTestRequest.h"
#include "HitTestResult.h"
-#include "HTMLFormElement.h"
#include "InspectorController.h"
#include "MouseEvent.h"
#include "Node.h"
@@ -108,8 +108,7 @@ static void openNewWindow(const KURL& urlToLoad, Frame* frame)
{
if (Page* oldPage = frame->page()) {
WindowFeatures features;
- if (Page* newPage = oldPage->chrome()->createWindow(frame,
- FrameLoadRequest(ResourceRequest(urlToLoad, frame->loader()->outgoingReferrer())), features))
+ if (Page* newPage = oldPage->chrome()->createWindow(frame, FrameLoadRequest(ResourceRequest(urlToLoad, frame->loader()->outgoingReferrer())), features))
newPage->chrome()->show();
}
}
@@ -127,215 +126,211 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
Frame* frame = result.innerNonSharedNode()->document()->frame();
if (!frame)
return;
-
+
switch (item->action()) {
- case ContextMenuItemTagOpenLinkInNewWindow:
- openNewWindow(result.absoluteLinkURL(), frame);
- break;
- case ContextMenuItemTagDownloadLinkToDisk:
- // FIXME: Some day we should be able to do this from within WebCore.
- m_client->downloadURL(result.absoluteLinkURL());
- break;
- case ContextMenuItemTagCopyLinkToClipboard:
- frame->editor()->copyURL(result.absoluteLinkURL(), result.textContent());
- break;
- case ContextMenuItemTagOpenImageInNewWindow:
- openNewWindow(result.absoluteImageURL(), frame);
- break;
- case ContextMenuItemTagDownloadImageToDisk:
- // FIXME: Some day we should be able to do this from within WebCore.
- m_client->downloadURL(result.absoluteImageURL());
- break;
- case ContextMenuItemTagCopyImageToClipboard:
- // FIXME: The Pasteboard class is not written yet
- // For now, call into the client. This is temporary!
- frame->editor()->copyImage(result);
- break;
- case ContextMenuItemTagOpenFrameInNewWindow: {
- DocumentLoader* loader = frame->loader()->documentLoader();
- if (!loader->unreachableURL().isEmpty())
- openNewWindow(loader->unreachableURL(), frame);
- else
- openNewWindow(loader->url(), frame);
- break;
- }
- case ContextMenuItemTagCopy:
- frame->editor()->copy();
- break;
- case ContextMenuItemTagGoBack:
- frame->loader()->goBackOrForward(-1);
- break;
- case ContextMenuItemTagGoForward:
- frame->loader()->goBackOrForward(1);
- break;
- case ContextMenuItemTagStop:
- frame->loader()->stop();
- break;
- case ContextMenuItemTagReload:
- frame->loader()->reload();
- break;
- case ContextMenuItemTagCut:
- frame->editor()->cut();
- break;
- case ContextMenuItemTagPaste:
- frame->editor()->paste();
- break;
+ case ContextMenuItemTagOpenLinkInNewWindow:
+ openNewWindow(result.absoluteLinkURL(), frame);
+ break;
+ case ContextMenuItemTagDownloadLinkToDisk:
+ // FIXME: Some day we should be able to do this from within WebCore.
+ m_client->downloadURL(result.absoluteLinkURL());
+ break;
+ case ContextMenuItemTagCopyLinkToClipboard:
+ frame->editor()->copyURL(result.absoluteLinkURL(), result.textContent());
+ break;
+ case ContextMenuItemTagOpenImageInNewWindow:
+ openNewWindow(result.absoluteImageURL(), frame);
+ break;
+ case ContextMenuItemTagDownloadImageToDisk:
+ // FIXME: Some day we should be able to do this from within WebCore.
+ m_client->downloadURL(result.absoluteImageURL());
+ break;
+ case ContextMenuItemTagCopyImageToClipboard:
+ // FIXME: The Pasteboard class is not written yet
+ // For now, call into the client. This is temporary!
+ frame->editor()->copyImage(result);
+ break;
+ case ContextMenuItemTagOpenFrameInNewWindow: {
+ DocumentLoader* loader = frame->loader()->documentLoader();
+ if (!loader->unreachableURL().isEmpty())
+ openNewWindow(loader->unreachableURL(), frame);
+ else
+ openNewWindow(loader->url(), frame);
+ break;
+ }
+ case ContextMenuItemTagCopy:
+ frame->editor()->copy();
+ break;
+ case ContextMenuItemTagGoBack:
+ frame->loader()->goBackOrForward(-1);
+ break;
+ case ContextMenuItemTagGoForward:
+ frame->loader()->goBackOrForward(1);
+ break;
+ case ContextMenuItemTagStop:
+ frame->loader()->stop();
+ break;
+ case ContextMenuItemTagReload:
+ frame->loader()->reload();
+ break;
+ case ContextMenuItemTagCut:
+ frame->editor()->cut();
+ break;
+ case ContextMenuItemTagPaste:
+ frame->editor()->paste();
+ break;
#if PLATFORM(GTK)
- case ContextMenuItemTagDelete:
- frame->editor()->performDelete();
- break;
- case ContextMenuItemTagSelectAll:
- frame->editor()->command("SelectAll").execute();
- break;
+ case ContextMenuItemTagDelete:
+ frame->editor()->performDelete();
+ break;
+ case ContextMenuItemTagSelectAll:
+ frame->editor()->command("SelectAll").execute();
+ break;
#endif
- case ContextMenuItemTagSpellingGuess:
- ASSERT(frame->selectedText().length());
- if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toNormalizedRange().get(),
- EditorInsertActionPasted)) {
- Document* document = frame->document();
- RefPtr<ReplaceSelectionCommand> command =
- ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""),
- true, false, true);
- applyCommand(command);
- frame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
- }
- break;
- case ContextMenuItemTagIgnoreSpelling:
- frame->editor()->ignoreSpelling();
- break;
- case ContextMenuItemTagLearnSpelling:
- frame->editor()->learnSpelling();
- break;
- case ContextMenuItemTagSearchWeb:
- m_client->searchWithGoogle(frame);
- break;
- case ContextMenuItemTagLookUpInDictionary:
- // FIXME: Some day we may be able to do this from within WebCore.
- m_client->lookUpInDictionary(frame);
- break;
- case ContextMenuItemTagOpenLink:
- if (Frame* targetFrame = result.targetFrame()) {
- targetFrame->loader()->loadFrameRequest(FrameLoadRequest(ResourceRequest(result.absoluteLinkURL(),
- frame->loader()->outgoingReferrer())), false, false, 0, 0);
- } else
- openNewWindow(result.absoluteLinkURL(), frame);
- break;
- case ContextMenuItemTagBold:
- frame->editor()->command("ToggleBold").execute();
- break;
- case ContextMenuItemTagItalic:
- frame->editor()->command("ToggleItalic").execute();
- break;
- case ContextMenuItemTagUnderline:
- frame->editor()->toggleUnderline();
- break;
- case ContextMenuItemTagOutline:
- // We actually never enable this because CSS does not have a way to specify an outline font,
- // which may make this difficult to implement. Maybe a special case of text-shadow?
- break;
- case ContextMenuItemTagStartSpeaking: {
- ExceptionCode ec;
- RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
- if (!selectedRange || selectedRange->collapsed(ec)) {
- Document* document = result.innerNonSharedNode()->document();
- selectedRange = document->createRange();
- selectedRange->selectNode(document->documentElement(), ec);
- }
- m_client->speak(plainText(selectedRange.get()));
- break;
+ case ContextMenuItemTagSpellingGuess:
+ ASSERT(frame->selectedText().length());
+ if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toNormalizedRange().get(), EditorInsertActionPasted)) {
+ Document* document = frame->document();
+ RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""), true, false, true);
+ applyCommand(command);
+ frame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
}
- case ContextMenuItemTagStopSpeaking:
- m_client->stopSpeaking();
- break;
- case ContextMenuItemTagDefaultDirection:
- frame->editor()->setBaseWritingDirection(NaturalWritingDirection);
- break;
- case ContextMenuItemTagLeftToRight:
- frame->editor()->setBaseWritingDirection(LeftToRightWritingDirection);
- break;
- case ContextMenuItemTagRightToLeft:
- frame->editor()->setBaseWritingDirection(RightToLeftWritingDirection);
- break;
- case ContextMenuItemTagTextDirectionDefault:
- frame->editor()->command("MakeTextWritingDirectionNatural").execute();
- break;
- case ContextMenuItemTagTextDirectionLeftToRight:
- frame->editor()->command("MakeTextWritingDirectionLeftToRight").execute();
- break;
- case ContextMenuItemTagTextDirectionRightToLeft:
- frame->editor()->command("MakeTextWritingDirectionRightToLeft").execute();
- break;
+ break;
+ case ContextMenuItemTagIgnoreSpelling:
+ frame->editor()->ignoreSpelling();
+ break;
+ case ContextMenuItemTagLearnSpelling:
+ frame->editor()->learnSpelling();
+ break;
+ case ContextMenuItemTagSearchWeb:
+ m_client->searchWithGoogle(frame);
+ break;
+ case ContextMenuItemTagLookUpInDictionary:
+ // FIXME: Some day we may be able to do this from within WebCore.
+ m_client->lookUpInDictionary(frame);
+ break;
+ case ContextMenuItemTagOpenLink:
+ if (Frame* targetFrame = result.targetFrame())
+ targetFrame->loader()->loadFrameRequest(FrameLoadRequest(ResourceRequest(result.absoluteLinkURL(), frame->loader()->outgoingReferrer())), false, false, 0, 0);
+ else
+ openNewWindow(result.absoluteLinkURL(), frame);
+ break;
+ case ContextMenuItemTagBold:
+ frame->editor()->command("ToggleBold").execute();
+ break;
+ case ContextMenuItemTagItalic:
+ frame->editor()->command("ToggleItalic").execute();
+ break;
+ case ContextMenuItemTagUnderline:
+ frame->editor()->toggleUnderline();
+ break;
+ case ContextMenuItemTagOutline:
+ // We actually never enable this because CSS does not have a way to specify an outline font,
+ // which may make this difficult to implement. Maybe a special case of text-shadow?
+ break;
+ case ContextMenuItemTagStartSpeaking: {
+ ExceptionCode ec;
+ RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
+ if (!selectedRange || selectedRange->collapsed(ec)) {
+ Document* document = result.innerNonSharedNode()->document();
+ selectedRange = document->createRange();
+ selectedRange->selectNode(document->documentElement(), ec);
+ }
+ m_client->speak(plainText(selectedRange.get()));
+ break;
+ }
+ case ContextMenuItemTagStopSpeaking:
+ m_client->stopSpeaking();
+ break;
+ case ContextMenuItemTagDefaultDirection:
+ frame->editor()->setBaseWritingDirection(NaturalWritingDirection);
+ break;
+ case ContextMenuItemTagLeftToRight:
+ frame->editor()->setBaseWritingDirection(LeftToRightWritingDirection);
+ break;
+ case ContextMenuItemTagRightToLeft:
+ frame->editor()->setBaseWritingDirection(RightToLeftWritingDirection);
+ break;
+ case ContextMenuItemTagTextDirectionDefault:
+ frame->editor()->command("MakeTextWritingDirectionNatural").execute();
+ break;
+ case ContextMenuItemTagTextDirectionLeftToRight:
+ frame->editor()->command("MakeTextWritingDirectionLeftToRight").execute();
+ break;
+ case ContextMenuItemTagTextDirectionRightToLeft:
+ frame->editor()->command("MakeTextWritingDirectionRightToLeft").execute();
+ break;
#if PLATFORM(MAC)
- case ContextMenuItemTagSearchInSpotlight:
- m_client->searchWithSpotlight();
- break;
+ case ContextMenuItemTagSearchInSpotlight:
+ m_client->searchWithSpotlight();
+ break;
#endif
- case ContextMenuItemTagShowSpellingPanel:
- frame->editor()->showSpellingGuessPanel();
- break;
- case ContextMenuItemTagCheckSpelling:
- frame->editor()->advanceToNextMisspelling();
- break;
- case ContextMenuItemTagCheckSpellingWhileTyping:
- frame->editor()->toggleContinuousSpellChecking();
- break;
+ case ContextMenuItemTagShowSpellingPanel:
+ frame->editor()->showSpellingGuessPanel();
+ break;
+ case ContextMenuItemTagCheckSpelling:
+ frame->editor()->advanceToNextMisspelling();
+ break;
+ case ContextMenuItemTagCheckSpellingWhileTyping:
+ frame->editor()->toggleContinuousSpellChecking();
+ break;
#ifndef BUILDING_ON_TIGER
- case ContextMenuItemTagCheckGrammarWithSpelling:
- frame->editor()->toggleGrammarChecking();
- break;
+ case ContextMenuItemTagCheckGrammarWithSpelling:
+ frame->editor()->toggleGrammarChecking();
+ break;
#endif
#if PLATFORM(MAC)
- case ContextMenuItemTagShowFonts:
- frame->editor()->showFontPanel();
- break;
- case ContextMenuItemTagStyles:
- frame->editor()->showStylesPanel();
- break;
- case ContextMenuItemTagShowColors:
- frame->editor()->showColorPanel();
- break;
+ case ContextMenuItemTagShowFonts:
+ frame->editor()->showFontPanel();
+ break;
+ case ContextMenuItemTagStyles:
+ frame->editor()->showStylesPanel();
+ break;
+ case ContextMenuItemTagShowColors:
+ frame->editor()->showColorPanel();
+ break;
#endif
#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- case ContextMenuItemTagMakeUpperCase:
- frame->editor()->uppercaseWord();
- break;
- case ContextMenuItemTagMakeLowerCase:
- frame->editor()->lowercaseWord();
- break;
- case ContextMenuItemTagCapitalize:
- frame->editor()->capitalizeWord();
- break;
- case ContextMenuItemTagShowSubstitutions:
- frame->editor()->showSubstitutionsPanel();
- break;
- case ContextMenuItemTagSmartCopyPaste:
- frame->editor()->toggleSmartInsertDelete();
- break;
- case ContextMenuItemTagSmartQuotes:
- frame->editor()->toggleAutomaticQuoteSubstitution();
- break;
- case ContextMenuItemTagSmartDashes:
- frame->editor()->toggleAutomaticDashSubstitution();
- break;
- case ContextMenuItemTagSmartLinks:
- frame->editor()->toggleAutomaticLinkDetection();
- break;
- case ContextMenuItemTagTextReplacement:
- frame->editor()->toggleAutomaticTextReplacement();
- break;
- case ContextMenuItemTagCorrectSpellingAutomatically:
- frame->editor()->toggleAutomaticSpellingCorrection();
- break;
- case ContextMenuItemTagChangeBack:
- frame->editor()->changeBackToReplacedString(result.replacedString());
- break;
+ case ContextMenuItemTagMakeUpperCase:
+ frame->editor()->uppercaseWord();
+ break;
+ case ContextMenuItemTagMakeLowerCase:
+ frame->editor()->lowercaseWord();
+ break;
+ case ContextMenuItemTagCapitalize:
+ frame->editor()->capitalizeWord();
+ break;
+ case ContextMenuItemTagShowSubstitutions:
+ frame->editor()->showSubstitutionsPanel();
+ break;
+ case ContextMenuItemTagSmartCopyPaste:
+ frame->editor()->toggleSmartInsertDelete();
+ break;
+ case ContextMenuItemTagSmartQuotes:
+ frame->editor()->toggleAutomaticQuoteSubstitution();
+ break;
+ case ContextMenuItemTagSmartDashes:
+ frame->editor()->toggleAutomaticDashSubstitution();
+ break;
+ case ContextMenuItemTagSmartLinks:
+ frame->editor()->toggleAutomaticLinkDetection();
+ break;
+ case ContextMenuItemTagTextReplacement:
+ frame->editor()->toggleAutomaticTextReplacement();
+ break;
+ case ContextMenuItemTagCorrectSpellingAutomatically:
+ frame->editor()->toggleAutomaticSpellingCorrection();
+ break;
+ case ContextMenuItemTagChangeBack:
+ frame->editor()->changeBackToReplacedString(result.replacedString());
+ break;
#endif
- case ContextMenuItemTagInspectElement:
- if (Page* page = frame->page())
- page->inspectorController()->inspect(result.innerNonSharedNode());
- break;
- default:
- break;
+ case ContextMenuItemTagInspectElement:
+ if (Page* page = frame->page())
+ page->inspectorController()->inspect(result.innerNonSharedNode());
+ break;
+ default:
+ break;
}
}
diff --git a/WebCore/page/ContextMenuController.h b/WebCore/page/ContextMenuController.h
index cb7e6ee..38095f6 100644
--- a/WebCore/page/ContextMenuController.h
+++ b/WebCore/page/ContextMenuController.h
@@ -37,7 +37,7 @@ namespace WebCore {
class Event;
class Page;
- class ContextMenuController : Noncopyable {
+ class ContextMenuController : public Noncopyable {
public:
ContextMenuController(Page*, ContextMenuClient*);
~ContextMenuController();
diff --git a/WebCore/page/Coordinates.cpp b/WebCore/page/Coordinates.cpp
index 637a8c2..728882a 100644
--- a/WebCore/page/Coordinates.cpp
+++ b/WebCore/page/Coordinates.cpp
@@ -31,7 +31,7 @@ namespace WebCore {
String Coordinates::toString() const
{
return String::format("coordinate(%.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.6lg)",
- m_latitude, m_longitude, m_altitude, m_accuracy,
+ m_latitude, m_longitude, m_altitude, m_accuracy,
m_altitudeAccuracy, m_heading, m_speed);
}
diff --git a/WebCore/page/DOMSelection.cpp b/WebCore/page/DOMSelection.cpp
index 3b54f02..0d21c56 100644
--- a/WebCore/page/DOMSelection.cpp
+++ b/WebCore/page/DOMSelection.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,15 +32,26 @@
#include "ExceptionCode.h"
#include "Frame.h"
-#include "htmlediting.h"
#include "Node.h"
#include "PlatformString.h"
#include "Range.h"
#include "SelectionController.h"
#include "TextIterator.h"
+#include "htmlediting.h"
namespace WebCore {
+static Node* selectionShadowAncestor(Frame* frame)
+{
+ Node* node = frame->selection()->selection().base().anchorNode();
+ if (!node)
+ return 0;
+ Node* shadowAncestor = node->shadowAncestorNode();
+ if (shadowAncestor == node)
+ return 0;
+ return shadowAncestor;
+}
+
DOMSelection::DOMSelection(Frame* frame)
: m_frame(frame)
{
@@ -88,6 +99,8 @@ Node* DOMSelection::anchorNode() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->parentNode();
return anchorPosition(visibleSelection()).node();
}
@@ -95,6 +108,8 @@ int DOMSelection::anchorOffset() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->nodeIndex();
return anchorPosition(visibleSelection()).deprecatedEditingOffset();
}
@@ -102,6 +117,8 @@ Node* DOMSelection::focusNode() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->parentNode();
return focusPosition(visibleSelection()).node();
}
@@ -109,6 +126,8 @@ int DOMSelection::focusOffset() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->nodeIndex();
return focusPosition(visibleSelection()).deprecatedEditingOffset();
}
@@ -116,6 +135,8 @@ Node* DOMSelection::baseNode() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->parentNode();
return basePosition(visibleSelection()).node();
}
@@ -123,14 +144,17 @@ int DOMSelection::baseOffset() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->nodeIndex();
return basePosition(visibleSelection()).deprecatedEditingOffset();
}
-
Node* DOMSelection::extentNode() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->parentNode();
return extentPosition(visibleSelection()).node();
}
@@ -138,13 +162,15 @@ int DOMSelection::extentOffset() const
{
if (!m_frame)
return 0;
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
+ return shadowAncestor->nodeIndex();
return extentPosition(visibleSelection()).deprecatedEditingOffset();
}
bool DOMSelection::isCollapsed() const
{
- if (!m_frame)
- return false;
+ if (!m_frame || selectionShadowAncestor(m_frame))
+ return true;
return !m_frame->selection()->isRange();
}
@@ -206,7 +232,7 @@ void DOMSelection::empty()
{
if (!m_frame)
return;
- m_frame->selection()->moveTo(VisiblePosition());
+ m_frame->selection()->clear();
}
void DOMSelection::setBaseAndExtent(Node* baseNode, int baseOffset, Node* extentNode, int extentOffset, ExceptionCode& ec)
@@ -220,7 +246,7 @@ void DOMSelection::setBaseAndExtent(Node* baseNode, int baseOffset, Node* extent
}
VisiblePosition visibleBase = VisiblePosition(baseNode, baseOffset, DOWNSTREAM);
VisiblePosition visibleExtent = VisiblePosition(extentNode, extentOffset, DOWNSTREAM);
-
+
m_frame->selection()->moveTo(visibleBase, visibleExtent);
}
@@ -245,9 +271,9 @@ void DOMSelection::modify(const String& alterString, const String& directionStri
alter = SelectionController::EXTEND;
else if (equalIgnoringCase(alterString, "move"))
alter = SelectionController::MOVE;
- else
+ else
return;
-
+
SelectionController::EDirection direction;
if (equalIgnoringCase(directionString, "forward"))
direction = SelectionController::FORWARD;
@@ -259,7 +285,7 @@ void DOMSelection::modify(const String& alterString, const String& directionStri
direction = SelectionController::RIGHT;
else
return;
-
+
TextGranularity granularity;
if (equalIgnoringCase(granularityString, "character"))
granularity = CharacterGranularity;
@@ -317,6 +343,12 @@ PassRefPtr<Range> DOMSelection::getRangeAt(int index, ExceptionCode& ec)
// If you're hitting this, you've added broken multi-range selection support
ASSERT(rangeCount() == 1);
+ if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) {
+ Node* container = shadowAncestor->parentNode();
+ int offset = shadowAncestor->nodeIndex();
+ return Range::create(shadowAncestor->document(), container, offset, container, offset);
+ }
+
const VisibleSelection& selection = m_frame->selection()->selection();
return selection.firstRange();
}
@@ -336,7 +368,7 @@ void DOMSelection::addRange(Range* r)
return;
SelectionController* selection = m_frame->selection();
-
+
if (selection->isNone()) {
selection->setSelection(VisibleSelection(r));
return;
@@ -385,7 +417,7 @@ void DOMSelection::deleteFromDocument()
ExceptionCode ec = 0;
selectedRange->deleteContents(ec);
ASSERT(!ec);
-
+
setBaseAndExtent(selectedRange->startContainer(ec), selectedRange->startOffset(ec), selectedRange->startContainer(ec), selectedRange->startOffset(ec), ec);
ASSERT(!ec);
}
diff --git a/WebCore/page/DOMSelection.h b/WebCore/page/DOMSelection.h
index 6a914d6..e0fe1e3 100644
--- a/WebCore/page/DOMSelection.h
+++ b/WebCore/page/DOMSelection.h
@@ -30,9 +30,9 @@
#ifndef DOMSelection_h
#define DOMSelection_h
-#include <wtf/RefCounted.h>
#include <wtf/Forward.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
diff --git a/WebCore/page/DOMTimer.cpp b/WebCore/page/DOMTimer.cpp
index 1cc7730..c42a0dc 100644
--- a/WebCore/page/DOMTimer.cpp
+++ b/WebCore/page/DOMTimer.cpp
@@ -54,7 +54,7 @@ DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int
if (lastUsedTimeoutId <= 0)
lastUsedTimeoutId = 1;
m_timeoutId = lastUsedTimeoutId;
-
+
m_nestingLevel = timerNestingLevel + 1;
scriptExecutionContext()->addTimeout(m_timeoutId, this);
@@ -74,11 +74,10 @@ DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int
DOMTimer::~DOMTimer()
{
- if (scriptExecutionContext()) {
+ if (scriptExecutionContext())
scriptExecutionContext()->removeTimeout(m_timeoutId);
- }
}
-
+
int DOMTimer::install(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot)
{
// DOMTimer constructor links the new timer into a list of ActiveDOMObjects held by the 'context'.
@@ -110,7 +109,7 @@ void DOMTimer::fired()
if (m_nestingLevel >= maxTimerNestingLevel)
augmentRepeatInterval(s_minTimerInterval - repeatInterval());
}
-
+
// No access to member variables after this point, it can delete the timer.
m_action->execute(context);
return;
@@ -121,7 +120,7 @@ void DOMTimer::fired()
// No access to member variables after this point.
delete this;
-
+
action->execute(context);
delete action;
timerNestingLevel = 0;
@@ -147,24 +146,24 @@ void DOMTimer::stop()
m_action.clear();
}
-void DOMTimer::suspend()
-{
- ASSERT(m_nextFireInterval == 0 && m_repeatInterval == 0);
+void DOMTimer::suspend()
+{
+ ASSERT(!m_nextFireInterval && !m_repeatInterval);
m_nextFireInterval = nextFireInterval();
m_repeatInterval = repeatInterval();
TimerBase::stop();
-}
-
-void DOMTimer::resume()
-{
+}
+
+void DOMTimer::resume()
+{
start(m_nextFireInterval, m_repeatInterval);
m_nextFireInterval = 0;
m_repeatInterval = 0;
-}
-
-
-bool DOMTimer::canSuspend() const
-{
+}
+
+
+bool DOMTimer::canSuspend() const
+{
return true;
}
diff --git a/WebCore/page/DOMTimer.h b/WebCore/page/DOMTimer.h
index f6343fc..6d6271f 100644
--- a/WebCore/page/DOMTimer.h
+++ b/WebCore/page/DOMTimer.h
@@ -33,41 +33,41 @@
namespace WebCore {
-class ScheduledAction;
+ class ScheduledAction;
-class DOMTimer : public TimerBase, public ActiveDOMObject {
-public:
- virtual ~DOMTimer();
- // Creates a new timer owned by specified ScriptExecutionContext, starts it
- // and returns its Id.
- static int install(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot);
- static void removeById(ScriptExecutionContext*, int timeoutId);
+ class DOMTimer : public TimerBase, public ActiveDOMObject {
+ public:
+ virtual ~DOMTimer();
+ // Creates a new timer owned by specified ScriptExecutionContext, starts it
+ // and returns its Id.
+ static int install(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot);
+ static void removeById(ScriptExecutionContext*, int timeoutId);
- // ActiveDOMObject
- virtual bool hasPendingActivity() const;
- virtual void contextDestroyed();
- virtual void stop();
- virtual bool canSuspend() const;
- virtual void suspend();
- virtual void resume();
+ // ActiveDOMObject
+ virtual bool hasPendingActivity() const;
+ virtual void contextDestroyed();
+ virtual void stop();
+ virtual bool canSuspend() const;
+ virtual void suspend();
+ virtual void resume();
- // The lowest allowable timer setting (in seconds, 0.001 == 1 ms).
- // Default is 10ms.
- // Chromium uses a non-default timeout.
- static double minTimerInterval() { return s_minTimerInterval; }
- static void setMinTimerInterval(double value) { s_minTimerInterval = value; }
+ // The lowest allowable timer setting (in seconds, 0.001 == 1 ms).
+ // Default is 10ms.
+ // Chromium uses a non-default timeout.
+ static double minTimerInterval() { return s_minTimerInterval; }
+ static void setMinTimerInterval(double value) { s_minTimerInterval = value; }
-private:
- DOMTimer(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot);
- virtual void fired();
+ private:
+ DOMTimer(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot);
+ virtual void fired();
- int m_timeoutId;
- int m_nestingLevel;
- OwnPtr<ScheduledAction> m_action;
- double m_nextFireInterval;
- double m_repeatInterval;
- static double s_minTimerInterval;
-};
+ int m_timeoutId;
+ int m_nestingLevel;
+ OwnPtr<ScheduledAction> m_action;
+ double m_nextFireInterval;
+ double m_repeatInterval;
+ static double s_minTimerInterval;
+ };
} // namespace WebCore
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp
index b4f3dee..e50b488 100644
--- a/WebCore/page/DOMWindow.cpp
+++ b/WebCore/page/DOMWindow.cpp
@@ -51,6 +51,7 @@
#include "History.h"
#include "InspectorController.h"
#include "Location.h"
+#include "Media.h"
#include "MessageEvent.h"
#include "Navigator.h"
#include "Page.h"
@@ -70,10 +71,9 @@
#endif
#if ENABLE(DOM_STORAGE)
-#include "LocalStorage.h"
-#include "SessionStorage.h"
#include "Storage.h"
#include "StorageArea.h"
+#include "StorageNamespace.h"
#endif
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
@@ -87,14 +87,25 @@ namespace WebCore {
class PostMessageTimer : public TimerBase {
public:
- PostMessageTimer(DOMWindow* window, PassRefPtr<MessageEvent> event, SecurityOrigin* targetOrigin)
+ PostMessageTimer(DOMWindow* window, const String& message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannel> channel, SecurityOrigin* targetOrigin)
: m_window(window)
- , m_event(event)
+ , m_message(message)
+ , m_origin(sourceOrigin)
+ , m_source(source)
+ , m_channel(channel)
, m_targetOrigin(targetOrigin)
{
}
- MessageEvent* event() const { return m_event.get(); }
+ PassRefPtr<MessageEvent> event(ScriptExecutionContext* context)
+ {
+ RefPtr<MessagePort> messagePort;
+ if (m_channel) {
+ messagePort = MessagePort::create(*context);
+ messagePort->entangle(m_channel.release());
+ }
+ return MessageEvent::create(m_message, m_origin, "", m_source, messagePort.release());
+ }
SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
private:
@@ -104,7 +115,10 @@ private:
}
RefPtr<DOMWindow> m_window;
- RefPtr<MessageEvent> m_event;
+ String m_message;
+ String m_origin;
+ RefPtr<DOMWindow> m_source;
+ OwnPtr<MessagePortChannel> m_channel;
RefPtr<SecurityOrigin> m_targetOrigin;
};
@@ -508,7 +522,7 @@ Console* DOMWindow::console() const
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
DOMApplicationCache* DOMWindow::applicationCache() const
{
- if (!m_applicationCache)
+ if (!m_applicationCache && m_frame && m_frame->settings() && m_frame->settings()->offlineWebApplicationCacheEnabled())
m_applicationCache = DOMApplicationCache::create(m_frame);
return m_applicationCache.get();
}
@@ -533,12 +547,17 @@ Storage* DOMWindow::sessionStorage() const
{
if (m_sessionStorage)
return m_sessionStorage.get();
-
- Page* page = m_frame->page();
+
+ Document* document = this->document();
+ if (!document)
+ return 0;
+
+ Page* page = document->page();
if (!page)
return 0;
- Document* document = m_frame->document();
+ if (!page->settings()->sessionStorageEnabled())
+ return 0;
RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
page->inspectorController()->didUseDOMStorage(storageArea.get(), false, m_frame);
@@ -560,11 +579,10 @@ Storage* DOMWindow::localStorage() const
if (!page)
return 0;
- Settings* settings = document->settings();
- if (!settings || !settings->localStorageEnabled())
+ if (!page->settings()->localStorageEnabled())
return 0;
- LocalStorage* localStorage = page->group().localStorage();
+ StorageNamespace* localStorage = page->group().localStorage();
RefPtr<StorageArea> storageArea = localStorage ? localStorage->storageArea(document->securityOrigin()) : 0;
if (storageArea) {
page->inspectorController()->didUseDOMStorage(storageArea.get(), true, m_frame);
@@ -591,9 +609,9 @@ void DOMWindow::postMessage(const String& message, MessagePort* messagePort, con
}
}
- RefPtr<MessagePort> newMessagePort;
+ OwnPtr<MessagePortChannel> channel;
if (messagePort)
- newMessagePort = messagePort->clone(ec);
+ channel = messagePort->disentangle(ec);
if (ec)
return;
@@ -605,7 +623,7 @@ void DOMWindow::postMessage(const String& message, MessagePort* messagePort, con
String sourceOrigin = sourceDocument->securityOrigin()->toString();
// Schedule the message.
- PostMessageTimer* timer = new PostMessageTimer(this, MessageEvent::create(message, sourceOrigin, "", source, newMessagePort), target.get());
+ PostMessageTimer* timer = new PostMessageTimer(this, message, sourceOrigin, source, channel.release(), target.get());
timer->startOneShot(0);
}
@@ -621,18 +639,13 @@ void DOMWindow::postMessageTimerFired(PostMessageTimer* t)
if (!timer->targetOrigin()->isSameSchemeHostPort(document()->securityOrigin())) {
String message = String::format("Unable to post message to %s. Recipient has origin %s.\n",
timer->targetOrigin()->toString().utf8().data(), document()->securityOrigin()->toString().utf8().data());
- console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 0, String());
+ console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 0, String());
return;
}
}
- MessagePort* messagePort = timer->event()->messagePort();
- ASSERT(!messagePort || !messagePort->scriptExecutionContext());
- if (messagePort)
- messagePort->attachToContext(document());
-
ExceptionCode ec = 0;
- dispatchEvent(timer->event(), ec);
+ dispatchEvent(timer->event(document()), ec);
}
DOMSelection* DOMWindow::getSelection()
@@ -997,6 +1010,11 @@ Document* DOMWindow::document() const
return m_frame->document();
}
+PassRefPtr<Media> DOMWindow::media() const
+{
+ return Media::create(const_cast<DOMWindow*>(this));
+}
+
PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String&) const
{
if (!elt)
diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h
index 7d97445..12caf7e 100644
--- a/WebCore/page/DOMWindow.h
+++ b/WebCore/page/DOMWindow.h
@@ -52,6 +52,7 @@ namespace WebCore {
class Frame;
class History;
class Location;
+ class Media;
class MessagePort;
class Navigator;
class Node;
@@ -61,7 +62,6 @@ namespace WebCore {
class WebKitPoint;
#if ENABLE(DOM_STORAGE)
- class SessionStorage;
class Storage;
#endif
@@ -175,6 +175,8 @@ namespace WebCore {
// DOM Level 2 AbstractView Interface
Document* document() const;
+ // CSSOM View Module
+ PassRefPtr<Media> media() const;
// DOM Level 2 Style Interface
PassRefPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const;
@@ -383,7 +385,7 @@ namespace WebCore {
void captureEvents();
void releaseEvents();
- // These methods are used for GC marking. See JSDOMWindow::mark() in
+ // These methods are used for GC marking. See JSDOMWindow::markChildren(MarkStack&) in
// JSDOMWindowCustom.cpp.
Screen* optionalScreen() const { return m_screen.get(); }
DOMSelection* optionalSelection() const { return m_selection.get(); }
diff --git a/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl
index 612ae42..aba92f0 100644
--- a/WebCore/page/DOMWindow.idl
+++ b/WebCore/page/DOMWindow.idl
@@ -136,12 +136,15 @@ module window {
attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow frames;
attribute [Replaceable, DoNotCheckDomainSecurityOnGet, V8CustomSetter] DOMWindow opener;
- attribute [Replaceable, DoNotCheckDomainSecurity] DOMWindow parent;
- attribute [Replaceable, DoNotCheckDomainSecurity, V8DisallowShadowing, V8ReadOnly] DOMWindow top;
+ attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow parent;
+ attribute [Replaceable, DoNotCheckDomainSecurityOnGet, V8DisallowShadowing, V8ReadOnly] DOMWindow top;
// DOM Level 2 AbstractView Interface
readonly attribute Document document;
+ // CSSOM View Module
+ readonly attribute Media media;
+
// DOM Level 2 Style Interface
CSSStyleDeclaration getComputedStyle(in Element element,
in DOMString pseudoElement);
@@ -257,7 +260,6 @@ module window {
// Not implemented yet.
// attribute EventListener onafterprint;
// attribute EventListener onbeforeprint;
- // attribute EventListener ondataunavailable;
// attribute EventListener onformchange;
// attribute EventListener onforminput;
// attribute EventListener onhashchange;
@@ -315,11 +317,12 @@ module window {
attribute CounterConstructor Counter;
attribute CSSRuleListConstructor CSSRuleList;
attribute RectConstructor Rect;
+ attribute RGBColorConstructor RGBColor;
attribute StyleSheetListConstructor StyleSheetList;
// FIXME: Implement the commented-out global constructors for interfaces listed in DOM Level 3 Core specification.
attribute DOMCoreExceptionConstructor DOMException;
- attribute DOMStringListConstructor DOMStringList;
+// attribute DOMStringListConstructor DOMStringList;
// attribute NameListConstructor NameList;
// attribute DOMImplementationListConstructor DOMImplementationList;
// attribute DOMImplementationSourceConstructor DOMImplementationSource;
@@ -360,6 +363,9 @@ module window {
attribute HTMLBodyElementConstructor HTMLBodyElement;
attribute HTMLButtonElementConstructor HTMLButtonElement;
attribute HTMLCanvasElementConstructor HTMLCanvasElement;
+ attribute [Conditional=DATAGRID] HTMLDataGridElementConstructor HTMLDataGridElement;
+ attribute [Conditional=DATAGRID] HTMLDataGridCellElementConstructor HTMLDataGridCellElement;
+ attribute [Conditional=DATAGRID] HTMLDataGridColElementConstructor HTMLDataGridColElement;
attribute HTMLDListElementConstructor HTMLDListElement;
attribute HTMLDirectoryElementConstructor HTMLDirectoryElement;
attribute HTMLDivElementConstructor HTMLDivElement;
@@ -472,6 +478,10 @@ module window {
attribute [JSCCustomGetter] WorkerConstructor Worker; // Usable with the new operator
#endif
+#if defined(ENABLE_SHARED_WORKERS) && ENABLE_SHARED_WORKERS
+ attribute [JSCCustomGetter] SharedWorkerConstructor SharedWorker; // Usable with the new operator
+#endif
+
attribute PluginConstructor Plugin;
attribute PluginArrayConstructor PluginArray;
diff --git a/WebCore/page/DragController.cpp b/WebCore/page/DragController.cpp
index e1b5ea7..08fb872 100644
--- a/WebCore/page/DragController.cpp
+++ b/WebCore/page/DragController.cpp
@@ -72,7 +72,7 @@ static PlatformMouseEvent createMouseEvent(DragData* dragData)
LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
}
-
+
DragController::DragController(Page* page, DragClient* client)
: m_page(page)
, m_client(client)
@@ -85,12 +85,12 @@ DragController::DragController(Page* page, DragClient* client)
, m_sourceDragOperation(DragOperationNone)
{
}
-
+
DragController::~DragController()
-{
+{
m_client->dragControllerDestroyed();
}
-
+
static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragData, RefPtr<Range> context,
bool allowPlainText, bool& chosePlainText)
{
@@ -122,7 +122,7 @@ static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragD
chosePlainText = true;
return createFragmentFromText(context.get(), dragData->asPlainText()).get();
}
-
+
return 0;
}
@@ -140,20 +140,20 @@ void DragController::cancelDrag()
void DragController::dragEnded()
{
m_dragInitiator = 0;
- m_didInitiateDrag = false;
- m_page->dragCaretController()->clear();
-}
+ m_didInitiateDrag = false;
+ m_page->dragCaretController()->clear();
+}
-DragOperation DragController::dragEntered(DragData* dragData)
+DragOperation DragController::dragEntered(DragData* dragData)
{
return dragEnteredOrUpdated(dragData);
}
-
-void DragController::dragExited(DragData* dragData)
-{
+
+void DragController::dragExited(DragData* dragData)
+{
ASSERT(dragData);
Frame* mainFrame = m_page->mainFrame();
-
+
if (RefPtr<FrameView> v = mainFrame->view()) {
ClipboardAccessPolicy policy = (!m_documentUnderMouse || m_documentUnderMouse->securityOrigin()->isLocal()) ? ClipboardReadable : ClipboardTypesReadable;
RefPtr<Clipboard> clipboard = dragData->createClipboard(policy);
@@ -164,14 +164,13 @@ void DragController::dragExited(DragData* dragData)
mouseMovedIntoDocument(0);
}
-
-DragOperation DragController::dragUpdated(DragData* dragData)
+DragOperation DragController::dragUpdated(DragData* dragData)
{
return dragEnteredOrUpdated(dragData);
}
-
+
bool DragController::performDrag(DragData* dragData)
-{
+{
ASSERT(dragData);
m_documentUnderMouse = m_page->mainFrame()->documentAtPoint(dragData->clientPosition());
if (m_isHandlingDrag) {
@@ -187,13 +186,13 @@ bool DragController::performDrag(DragData* dragData)
}
m_documentUnderMouse = 0;
return true;
- }
-
+ }
+
if ((m_dragDestinationAction & DragDestinationActionEdit) && concludeEditDrag(dragData)) {
m_documentUnderMouse = 0;
return true;
}
-
+
m_documentUnderMouse = 0;
if (operationForLoad(dragData) == DragOperationNone)
@@ -222,60 +221,72 @@ DragOperation DragController::dragEnteredOrUpdated(DragData* dragData)
mouseMovedIntoDocument(m_page->mainFrame()->documentAtPoint(dragData->clientPosition()));
m_dragDestinationAction = m_client->actionMaskForDrag(dragData);
-
- DragOperation operation = DragOperationNone;
-
- if (m_dragDestinationAction == DragDestinationActionNone)
+ if (m_dragDestinationAction == DragDestinationActionNone) {
cancelDrag(); // FIXME: Why not call mouseMovedIntoDocument(0)?
- else {
- operation = tryDocumentDrag(dragData, m_dragDestinationAction);
- if (operation == DragOperationNone && (m_dragDestinationAction & DragDestinationActionLoad))
- return operationForLoad(dragData);
+ return DragOperationNone;
}
-
+
+ DragOperation operation = DragOperationNone;
+ bool handledByDocument = tryDocumentDrag(dragData, m_dragDestinationAction, operation);
+ if (!handledByDocument && (m_dragDestinationAction & DragDestinationActionLoad))
+ return operationForLoad(dragData);
return operation;
}
static HTMLInputElement* asFileInput(Node* node)
{
ASSERT(node);
-
+
// The button for a FILE input is a sub element with no set input type
// In order to get around this problem we assume any non-FILE input element
// is this internal button, and try querying the shadow parent node.
if (node->hasTagName(HTMLNames::inputTag) && node->isShadowNode() && static_cast<HTMLInputElement*>(node)->inputType() != HTMLInputElement::FILE)
node = node->shadowParentNode();
-
+
if (!node || !node->hasTagName(HTMLNames::inputTag))
return 0;
-
+
HTMLInputElement* inputElem = static_cast<HTMLInputElement*>(node);
if (inputElem->inputType() == HTMLInputElement::FILE)
return inputElem;
-
+
return 0;
}
-
-DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction actionMask)
+
+bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction actionMask, DragOperation& operation)
{
ASSERT(dragData);
-
+
if (!m_documentUnderMouse)
- return DragOperationNone;
-
- DragOperation operation = DragOperationNone;
- if (actionMask & DragDestinationActionDHTML)
- operation = tryDHTMLDrag(dragData);
- m_isHandlingDrag = operation != DragOperationNone;
+ return false;
+ m_isHandlingDrag = false;
+ if (actionMask & DragDestinationActionDHTML) {
+ m_isHandlingDrag = tryDHTMLDrag(dragData, operation);
+ // Do not continue if m_documentUnderMouse has been reset by tryDHTMLDrag.
+ // tryDHTMLDrag fires dragenter event. The event listener that listens
+ // to this event may create a nested message loop (open a modal dialog),
+ // which could process dragleave event and reset m_documentUnderMouse in
+ // dragExited.
+ if (!m_documentUnderMouse)
+ return false;
+ }
+
+ // It's unclear why this check is after tryDHTMLDrag.
+ // We send drag events in tryDHTMLDrag and that may be the reason.
RefPtr<FrameView> frameView = m_documentUnderMouse->view();
if (!frameView)
- return operation;
-
- if ((actionMask & DragDestinationActionEdit) && !m_isHandlingDrag && canProcessDrag(dragData)) {
- if (dragData->containsColor())
- return DragOperationGeneric;
-
+ return false;
+
+ if (m_isHandlingDrag) {
+ m_page->dragCaretController()->clear();
+ return true;
+ } else if ((actionMask & DragDestinationActionEdit) && canProcessDrag(dragData)) {
+ if (dragData->containsColor()) {
+ operation = DragOperationGeneric;
+ return true;
+ }
+
IntPoint dragPos = dragData->clientPosition();
IntPoint point = frameView->windowToContents(dragPos);
Element* element = m_documentUnderMouse->elementFromPoint(point.x(), point.y());
@@ -286,19 +297,20 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio
}
Frame* innerFrame = element->document()->frame();
- return dragIsMove(innerFrame->selection()) ? DragOperationMove : DragOperationCopy;
- }
-
+ operation = dragIsMove(innerFrame->selection()) ? DragOperationMove : DragOperationCopy;
+ return true;
+ }
+ // If we're not over an editable region, make sure we're clearing any prior drag cursor.
m_page->dragCaretController()->clear();
- return operation;
+ return false;
}
DragSourceAction DragController::delegateDragSourceAction(const IntPoint& windowPoint)
-{
+{
m_dragSourceAction = m_client->dragSourceActionMaskForPoint(windowPoint);
return m_dragSourceAction;
}
-
+
DragOperation DragController::operationForLoad(DragData* dragData)
{
ASSERT(dragData);
@@ -323,15 +335,15 @@ bool DragController::concludeEditDrag(DragData* dragData)
{
ASSERT(dragData);
ASSERT(!m_isHandlingDrag);
-
+
if (!m_documentUnderMouse)
return false;
-
+
IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition());
Element* element = m_documentUnderMouse->elementFromPoint(point.x(), point.y());
ASSERT(element);
Frame* innerFrame = element->ownerDocument()->frame();
- ASSERT(innerFrame);
+ ASSERT(innerFrame);
if (dragData->containsColor()) {
Color color = dragData->asColor();
@@ -349,32 +361,31 @@ bool DragController::concludeEditDrag(DragData* dragData)
innerFrame->editor()->applyStyle(style.get(), EditActionSetColor);
return true;
}
-
+
if (!m_page->dragController()->canProcessDrag(dragData)) {
m_page->dragCaretController()->clear();
return false;
}
-
+
if (HTMLInputElement* fileInput = asFileInput(element)) {
if (!fileInput->isEnabledFormControl())
return false;
-
+
if (!dragData->containsFiles())
return false;
-
+
Vector<String> filenames;
dragData->asFilenames(filenames);
if (filenames.isEmpty())
return false;
-
- // Ugly. For security none of the API's available to us to set the input value
- // on file inputs. Even forcing a change in HTMLInputElement doesn't work as
- // RenderFileUploadControl clears the file when doing updateFromElement()
- RenderFileUploadControl* renderer = static_cast<RenderFileUploadControl*>(fileInput->renderer());
-
+
+ // Ugly. For security none of the APIs available to us can set the input value
+ // on file inputs. Even forcing a change in HTMLInputElement doesn't work as
+ // RenderFileUploadControl clears the file when doing updateFromElement().
+ RenderFileUploadControl* renderer = toRenderFileUploadControl(fileInput->renderer());
if (!renderer)
return false;
-
+
renderer->receiveDroppedFiles(filenames);
return true;
}
@@ -382,114 +393,121 @@ bool DragController::concludeEditDrag(DragData* dragData)
VisibleSelection dragCaret(m_page->dragCaretController()->selection());
m_page->dragCaretController()->clear();
RefPtr<Range> range = dragCaret.toNormalizedRange();
-
+
// For range to be null a WebKit client must have done something bad while
// manually controlling drag behaviour
- if (!range)
+ if (!range)
return false;
DocLoader* loader = range->ownerDocument()->docLoader();
loader->setAllowStaleResources(true);
- if (dragIsMove(innerFrame->selection()) || dragCaret.isContentRichlyEditable()) {
+ if (dragIsMove(innerFrame->selection()) || dragCaret.isContentRichlyEditable()) {
bool chosePlainText = false;
RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, range, true, chosePlainText);
if (!fragment || !innerFrame->editor()->shouldInsertFragment(fragment, range, EditorInsertActionDropped)) {
loader->setAllowStaleResources(false);
return false;
}
-
+
m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
if (dragIsMove(innerFrame->selection())) {
- bool smartMove = innerFrame->selectionGranularity() == WordGranularity
- && innerFrame->editor()->smartInsertDeleteEnabled()
+ bool smartMove = innerFrame->selectionGranularity() == WordGranularity
+ && innerFrame->editor()->smartInsertDeleteEnabled()
&& dragData->canSmartReplace();
applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartMove));
} else {
if (setSelectionToDragCaret(innerFrame, dragCaret, range, point))
- applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText));
- }
+ applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText));
+ }
} else {
String text = dragData->asPlainText();
if (text.isEmpty() || !innerFrame->editor()->shouldInsertText(text, range.get(), EditorInsertActionDropped)) {
loader->setAllowStaleResources(false);
return false;
}
-
+
m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
if (setSelectionToDragCaret(innerFrame, dragCaret, range, point))
- applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, createFragmentFromText(range.get(), text), true, false, true));
+ applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, createFragmentFromText(range.get(), text), true, false, true));
}
loader->setAllowStaleResources(false);
return true;
}
-
-
-bool DragController::canProcessDrag(DragData* dragData)
+
+bool DragController::canProcessDrag(DragData* dragData)
{
ASSERT(dragData);
if (!dragData->containsCompatibleContent())
return false;
-
+
IntPoint point = m_page->mainFrame()->view()->windowToContents(dragData->clientPosition());
HitTestResult result = HitTestResult(point);
if (!m_page->mainFrame()->contentRenderer())
return false;
result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, true);
-
- if (!result.innerNonSharedNode())
+
+ if (!result.innerNonSharedNode())
return false;
-
+
if (dragData->containsFiles() && asFileInput(result.innerNonSharedNode()))
return true;
-
+
if (!result.innerNonSharedNode()->isContentEditable())
return false;
-
+
if (m_didInitiateDrag && m_documentUnderMouse == m_dragInitiator && result.isSelected())
return false;
return true;
}
-DragOperation DragController::tryDHTMLDrag(DragData* dragData)
-{
+static DragOperation defaultOperationForDrag(DragOperation srcOpMask)
+{
+ // This is designed to match IE's operation fallback for the case where
+ // the page calls preventDefault() in a drag event but doesn't set dropEffect.
+ if (srcOpMask & DragOperationCopy)
+ return DragOperationCopy;
+ if (srcOpMask & DragOperationMove || srcOpMask & DragOperationGeneric)
+ return DragOperationMove;
+ if (srcOpMask & DragOperationLink)
+ return DragOperationLink;
+
+ // FIXME: Does IE really return "generic" even if no operations were allowed by the source?
+ return DragOperationGeneric;
+}
+
+bool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation)
+{
ASSERT(dragData);
ASSERT(m_documentUnderMouse);
- DragOperation op = DragOperationNone;
RefPtr<Frame> mainFrame = m_page->mainFrame();
RefPtr<FrameView> viewProtector = mainFrame->view();
if (!viewProtector)
- return DragOperationNone;
-
+ return false;
+
ClipboardAccessPolicy policy = m_documentUnderMouse->securityOrigin()->isLocal() ? ClipboardReadable : ClipboardTypesReadable;
RefPtr<Clipboard> clipboard = dragData->createClipboard(policy);
- DragOperation srcOp = dragData->draggingSourceOperationMask();
- clipboard->setSourceOperation(srcOp);
-
- PlatformMouseEvent event = createMouseEvent(dragData);
- if (mainFrame->eventHandler()->updateDragAndDrop(event, clipboard.get())) {
- // *op unchanged if no source op was set
- if (!clipboard->destinationOperation(op)) {
- // The element accepted but they didn't pick an operation, so we pick one for them
- // (as does WinIE).
- if (srcOp & DragOperationCopy)
- op = DragOperationCopy;
- else if (srcOp & DragOperationMove || srcOp & DragOperationGeneric)
- op = DragOperationMove;
- else if (srcOp & DragOperationLink)
- op = DragOperationLink;
- else
- op = DragOperationGeneric;
- } else if (!(op & srcOp)) {
- op = DragOperationNone;
- }
+ DragOperation srcOpMask = dragData->draggingSourceOperationMask();
+ clipboard->setSourceOperation(srcOpMask);
+ PlatformMouseEvent event = createMouseEvent(dragData);
+ if (!mainFrame->eventHandler()->updateDragAndDrop(event, clipboard.get())) {
clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security
- return op;
+ return false;
}
- return op;
+
+ if (!clipboard->destinationOperation(operation)) {
+ // The element accepted but they didn't pick an operation, so we pick one (to match IE).
+ operation = defaultOperationForDrag(srcOpMask);
+ } else if (!(srcOpMask & operation)) {
+ // The element picked an operation which is not supported by the source
+ operation = DragOperationNone;
+ }
+
+ clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security
+ return true;
}
bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos)
@@ -504,7 +522,7 @@ bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPo
mouseDownTarget = frame->eventHandler()->hitTestResultAtPoint(framePos, true);
- if (mouseDownTarget.image()
+ if (mouseDownTarget.image()
&& !mouseDownTarget.absoluteImageURL().isEmpty()
&& frame->settings()->loadsImagesAutomatically()
&& m_dragSourceAction & DragSourceActionImage)
@@ -522,56 +540,56 @@ bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPo
return false;
}
-
+
static CachedImage* getCachedImage(Element* element)
{
ASSERT(element);
RenderObject* renderer = element->renderer();
- if (!renderer || !renderer->isImage())
+ if (!renderer || !renderer->isImage())
return 0;
RenderImage* image = toRenderImage(renderer);
return image->cachedImage();
}
-
+
static Image* getImage(Element* element)
{
ASSERT(element);
RenderObject* renderer = element->renderer();
- if (!renderer || !renderer->isImage())
+ if (!renderer || !renderer->isImage())
return 0;
-
+
RenderImage* image = toRenderImage(renderer);
if (image->cachedImage() && !image->cachedImage()->errorOccurred())
return image->cachedImage()->image();
return 0;
}
-
+
static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label)
{
RefPtr<Range> range = src->document()->createRange();
ExceptionCode ec = 0;
range->selectNode(node, ec);
- ASSERT(ec == 0);
- src->selection()->setSelection(VisibleSelection(range.get(), DOWNSTREAM));
+ ASSERT(!ec);
+ src->selection()->setSelection(VisibleSelection(range.get(), DOWNSTREAM));
clipboard->declareAndWriteDragImage(node, !linkURL.isEmpty() ? linkURL : imageURL, label, src);
}
-
+
static IntPoint dragLocForDHTMLDrag(const IntPoint& mouseDraggedPoint, const IntPoint& dragOrigin, const IntPoint& dragImageOffset, bool isLinkImage)
{
// dragImageOffset is the cursor position relative to the lower-left corner of the image.
-#if PLATFORM(MAC)
- // We add in the Y dimension because we are a flipped view, so adding moves the image down.
+#if PLATFORM(MAC)
+ // We add in the Y dimension because we are a flipped view, so adding moves the image down.
const int yOffset = dragImageOffset.y();
#else
const int yOffset = -dragImageOffset.y();
#endif
-
+
if (isLinkImage)
return IntPoint(mouseDraggedPoint.x() - dragImageOffset.x(), mouseDraggedPoint.y() + yOffset);
-
+
return IntPoint(dragOrigin.x() - dragImageOffset.x(), dragOrigin.y() + yOffset);
}
-
+
static IntPoint dragLocForSelectionDrag(Frame* src)
{
IntRect draggingRect = enclosingIntRect(src->selectionBounds());
@@ -586,63 +604,63 @@ static IntPoint dragLocForSelectionDrag(Frame* src)
#endif
return IntPoint(xpos, ypos);
}
-
+
bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag)
-{
+{
ASSERT(src);
ASSERT(clipboard);
-
+
if (!src->view() || !src->contentRenderer())
return false;
-
+
HitTestResult dragSource = HitTestResult(dragOrigin);
dragSource = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true);
KURL linkURL = dragSource.absoluteLinkURL();
KURL imageURL = dragSource.absoluteImageURL();
bool isSelected = dragSource.isSelected();
-
+
IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos());
-
+
m_draggingImageURL = KURL();
m_sourceDragOperation = srcOp;
-
+
DragImageRef dragImage = 0;
IntPoint dragLoc(0, 0);
IntPoint dragImageOffset(0, 0);
-
- if (isDHTMLDrag)
+
+ if (isDHTMLDrag)
dragImage = clipboard->createDragImage(dragImageOffset);
-
+
// We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging.
// This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp.
if (dragImage) {
dragLoc = dragLocForDHTMLDrag(mouseDraggedPoint, dragOrigin, dragImageOffset, !linkURL.isEmpty());
m_dragOffset = dragImageOffset;
}
-
+
bool startedDrag = true; // optimism - we almost always manage to start the drag
-
+
Node* node = dragSource.innerNonSharedNode();
-
+
Image* image = getImage(static_cast<Element*>(node));
if (!imageURL.isEmpty() && node && node->isElementNode() && image
&& (m_dragSourceAction & DragSourceActionImage)) {
- // We shouldn't be starting a drag for an image that can't provide an extension.
+ // We shouldn't be starting a drag for an image that can't provide an extension.
// This is an early detection for problems encountered later upon drop.
ASSERT(!image->filenameExtension().isEmpty());
Element* element = static_cast<Element*>(node);
if (!clipboard->hasData()) {
- m_draggingImageURL = imageURL;
+ m_draggingImageURL = imageURL;
prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, dragSource.altDisplayString());
}
-
+
m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard);
-
+
if (!dragImage) {
IntRect imageRect = dragSource.imageRect();
imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location())));
doImageDrag(element, dragOrigin, dragSource.imageRect(), clipboard, src, m_dragOffset);
- } else
+ } else
// DHTML defined drag image
doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
@@ -668,12 +686,12 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
IntSize size = dragImageSize(dragImage);
m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset);
dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y());
- }
+ }
doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true);
} else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) {
RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
ASSERT(selectionRange);
- if (!clipboard->hasData())
+ if (!clipboard->hasData())
clipboard->writeRange(selectionRange.get(), src);
m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
if (!dragImage) {
@@ -691,7 +709,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
// under the mousedown point, so linkURL, imageURL and isSelected are all false/empty.
startedDrag = false;
}
-
+
if (dragImage)
deleteDragImage(dragImage);
return startedDrag;
@@ -702,17 +720,17 @@ void DragController::doImageDrag(Element* element, const IntPoint& dragOrigin, c
IntPoint mouseDownPoint = dragOrigin;
DragImageRef dragImage;
IntPoint origin;
-
+
Image* image = getImage(element);
if (image && image->size().height() * image->size().width() <= MaxOriginalImageArea
&& (dragImage = createDragImageFromImage(image))) {
IntSize originalSize = rect.size();
origin = rect.location();
-
+
dragImage = fitDragImageToMaxSize(dragImage, rect.size(), maxDragImageSize());
dragImage = dissolveDragImageToFraction(dragImage, DragImageAlpha);
IntSize newSize = dragImageSize(dragImage);
-
+
// Properly orient the drag image and orient it differently if it's smaller than the original
float scale = newSize.width() / (float)originalSize.width();
float dx = origin.x() - mouseDownPoint.x();
@@ -730,14 +748,14 @@ void DragController::doImageDrag(Element* element, const IntPoint& dragOrigin, c
if (dragImage)
origin = IntPoint(DragIconRightInset - dragImageSize(dragImage).width(), DragIconBottomInset);
}
-
+
dragImageOffset.setX(mouseDownPoint.x() + origin.x());
dragImageOffset.setY(mouseDownPoint.y() + origin.y());
doSystemDrag(dragImage, dragImageOffset, dragOrigin, clipboard, frame, false);
-
+
deleteDragImage(dragImage);
}
-
+
void DragController::doSystemDrag(DragImageRef image, const IntPoint& dragLoc, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool forLink)
{
m_didInitiateDrag = true;
@@ -747,10 +765,10 @@ void DragController::doSystemDrag(DragImageRef image, const IntPoint& dragLoc, c
RefPtr<FrameView> viewProtector = frameProtector->view();
m_client->startDrag(image, viewProtector->windowToContents(frame->view()->contentsToWindow(dragLoc)),
viewProtector->windowToContents(frame->view()->contentsToWindow(eventPos)), clipboard, frameProtector.get(), forLink);
-
+
cleanupAfterSystemDrag();
}
-
+
// Manual drag caret manipulation
void DragController::placeDragCaret(const IntPoint& windowPoint)
{
@@ -762,8 +780,8 @@ void DragController::placeDragCaret(const IntPoint& windowPoint)
if (!frameView)
return;
IntPoint framePoint = frameView->windowToContents(windowPoint);
- VisibleSelection dragCaret(frame->visiblePositionForPoint(framePoint));
+ VisibleSelection dragCaret(frame->visiblePositionForPoint(framePoint));
m_page->dragCaretController()->setSelection(dragCaret);
}
-
+
} // namespace WebCore
diff --git a/WebCore/page/DragController.h b/WebCore/page/DragController.h
index 6fe1f7f..9472589 100644
--- a/WebCore/page/DragController.h
+++ b/WebCore/page/DragController.h
@@ -96,8 +96,8 @@ namespace WebCore {
bool concludeEditDrag(DragData*);
DragOperation dragEnteredOrUpdated(DragData*);
DragOperation operationForLoad(DragData*);
- DragOperation tryDocumentDrag(DragData*, DragDestinationAction);
- DragOperation tryDHTMLDrag(DragData*);
+ bool tryDocumentDrag(DragData*, DragDestinationAction, DragOperation&);
+ bool tryDHTMLDrag(DragData*, DragOperation&);
DragOperation dragOperation(DragData*);
void cancelDrag();
bool dragIsMove(SelectionController*);
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index c59ad00..624f530 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -150,6 +150,8 @@ EventHandler::EventHandler(Frame* frame)
, m_mouseDownWasSingleClickInSelection(false)
, m_beganSelectingText(false)
, m_panScrollInProgress(false)
+ , m_panScrollButtonPressed(false)
+ , m_springLoadedPanScrollInProgress(false)
, m_hoverTimer(this, &EventHandler::hoverTimerFired)
, m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
, m_autoscrollRenderer(0)
@@ -163,6 +165,8 @@ EventHandler::EventHandler(Frame* frame)
, m_capturingMouseEventsNode(0)
, m_clickCount(0)
, m_mouseDownTimestamp(0)
+ , m_useLatchedWheelEventNode(false)
+ , m_widgetIsLatched(false)
#if PLATFORM(MAC)
, m_mouseDownView(nil)
, m_sendingEventToSubview(false)
@@ -205,6 +209,7 @@ void EventHandler::clear()
m_mousePressed = false;
m_capturesDragging = false;
m_capturingMouseEventsNode = 0;
+ m_latchedWheelEventNode = 0;
}
void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
@@ -355,6 +360,11 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
// Reset drag state.
dragState().m_dragSrc = 0;
+ if (ScrollView* scrollView = m_frame->view()) {
+ if (scrollView->isPointInScrollbarCorner(event.event().pos()))
+ return false;
+ }
+
bool singleClick = event.event().clickCount() <= 1;
// If we got the event back, that must mean it wasn't prevented,
@@ -366,6 +376,8 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
m_mouseDownWasSingleClickInSelection = false;
+ m_mouseDown = event.event();
+
if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
return true;
@@ -405,7 +417,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect ||
(m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled(true));
- return swallowEvent;
+ return swallowEvent;
}
bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
@@ -657,7 +669,7 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
}
}
#if ENABLE(PAN_SCROLLING)
- setPanScrollCursor();
+ updatePanScrollState();
toRenderBox(r)->panScroll(m_panScrollStartPos);
#endif
}
@@ -665,7 +677,7 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
#if ENABLE(PAN_SCROLLING)
-void EventHandler::setPanScrollCursor()
+void EventHandler::updatePanScrollState()
{
FrameView* view = m_frame->view();
if (!view)
@@ -673,12 +685,14 @@ void EventHandler::setPanScrollCursor()
// At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll
// So we don't want to change the cursor over this area
- const int noScrollRadius = 9;
- bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - noScrollRadius);
- bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + noScrollRadius);
- bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + noScrollRadius);
- bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - noScrollRadius);
+ bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - ScrollView::noPanScrollRadius);
+ bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + ScrollView::noPanScrollRadius);
+ bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + ScrollView::noPanScrollRadius);
+ bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - ScrollView::noPanScrollRadius);
+ if ((east || west || north || south) && m_panScrollButtonPressed)
+ m_springLoadedPanScrollInProgress = true;
+
if (north) {
if (east)
view->setCursor(northEastPanningCursor());
@@ -748,7 +762,7 @@ void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
}
-HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping)
+HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars)
{
HitTestResult result(point);
if (!m_frame->contentRenderer())
@@ -762,7 +776,7 @@ HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all
Node* n = result.innerNode();
if (!result.isOverWidget() || !n || !n->renderer() || !n->renderer()->isWidget())
break;
- RenderWidget* renderWidget = static_cast<RenderWidget*>(n->renderer());
+ RenderWidget* renderWidget = toRenderWidget(n->renderer());
Widget* widget = renderWidget->widget();
if (!widget || !widget->isFrameView())
break;
@@ -775,6 +789,12 @@ HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all
HitTestResult widgetHitTestResult(widgetPoint);
frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult);
result = widgetHitTestResult;
+
+ if (testScrollbars == ShouldHitTestScrollbars) {
+ Scrollbar* eventScrollbar = view->scrollbarAtPoint(point);
+ if (eventScrollbar)
+ result.setScrollbar(eventScrollbar);
+ }
}
// If our HitTestResult is not visible, then we started hit testing too far down the frame chain.
@@ -833,6 +853,7 @@ void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
m_autoscrollTimer.stop();
m_panScrollInProgress = false;
+ m_springLoadedPanScrollInProgress = false;
// If we're not in the top frame we notify it that we are not doing a panScroll any more.
if (Page* page = m_frame->page()) {
@@ -869,6 +890,21 @@ bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity g
return false;
}
+bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity)
+{
+ bool handled = scrollOverflow(direction, granularity);
+ if (!handled) {
+ Frame* frame = m_frame;
+ do {
+ FrameView* view = frame->view();
+ handled = view ? view->scroll(direction, granularity) : false;
+ frame = frame->tree()->parent();
+ } while (!handled && frame);
+ }
+
+ return handled;
+}
+
IntPoint EventHandler::currentMousePosition() const
{
return m_currentMousePosition;
@@ -890,7 +926,7 @@ Frame* subframeForTargetNode(Node* node)
if (!renderer || !renderer->isWidget())
return 0;
- Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
+ Widget* widget = toRenderWidget(renderer)->widget();
if (!widget || !widget->isFrameView())
return 0;
@@ -921,10 +957,10 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr
RenderStyle* style = renderer ? renderer->style() : 0;
if (renderer && renderer->isFrameSet()) {
- RenderFrameSet* fs = static_cast<RenderFrameSet*>(renderer);
- if (fs->canResizeRow(event.localPoint()))
+ RenderFrameSet* frameSetRenderer = toRenderFrameSet(renderer);
+ if (frameSetRenderer->canResizeRow(event.localPoint()))
return rowResizeCursor();
- if (fs->canResizeColumn(event.localPoint()))
+ if (frameSetRenderer->canResizeColumn(event.localPoint()))
return columnResizeCursor();
}
@@ -957,7 +993,7 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr
// If the link is editable, then we need to check the settings to see whether or not the link should be followed
if (editable) {
ASSERT(m_frame->settings());
- switch(m_frame->settings()->editableLinkBehavior()) {
+ switch (m_frame->settings()->editableLinkBehavior()) {
default:
case EditableLinkDefaultBehavior:
case EditableLinkAlwaysLive:
@@ -1145,11 +1181,12 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
if (renderer) {
m_panScrollInProgress = true;
+ m_panScrollButtonPressed = true;
handleAutoscroll(renderer);
invalidateClick();
return true;
}
- }
+ }
#endif
m_clickCount = mouseEvent.clickCount();
@@ -1182,8 +1219,12 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
if (swallowEvent) {
// scrollbars should get events anyway, even disabled controls might be scrollable
- if (mev.scrollbar())
- passMousePressEventToScrollbar(mev, mev.scrollbar());
+ Scrollbar* scrollbar = mev.scrollbar();
+
+ updateLastScrollbarUnderMouse(scrollbar, true);
+
+ if (scrollbar)
+ passMousePressEventToScrollbar(mev, scrollbar);
} else {
// Refetch the event target node if it currently is the shadow node inside an <input> element.
// If a mouse event handler changes the input element type to one that has a widget associated,
@@ -1195,9 +1236,12 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
}
FrameView* view = m_frame->view();
- Scrollbar* scrollbar = view ? view->scrollbarUnderMouse(mouseEvent) : 0;
+ Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.pos()) : 0;
if (!scrollbar)
scrollbar = mev.scrollbar();
+
+ updateLastScrollbarUnderMouse(scrollbar, true);
+
if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
swallowEvent = true;
else
@@ -1287,7 +1331,7 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
// Send events right to a scrollbar if the mouse is pressed.
if (m_lastScrollbarUnderMouse && m_mousePressed)
- return m_lastScrollbarUnderMouse->mouseMoved(m_lastScrollbarUnderMouse->transformEvent(mouseEvent));
+ return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
// Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
// if we are allowed to select.
@@ -1309,17 +1353,12 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
else {
if (FrameView* view = m_frame->view())
- scrollbar = view->scrollbarUnderMouse(mouseEvent);
+ scrollbar = view->scrollbarAtPoint(mouseEvent.pos());
if (!scrollbar)
scrollbar = mev.scrollbar();
- if (m_lastScrollbarUnderMouse != scrollbar) {
- // Send mouse exited to the old scrollbar.
- if (m_lastScrollbarUnderMouse)
- m_lastScrollbarUnderMouse->mouseExited();
- m_lastScrollbarUnderMouse = m_mousePressed ? 0 : scrollbar;
- }
+ updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
}
bool swallowEvent = false;
@@ -1339,7 +1378,7 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
} else {
if (scrollbar && !m_mousePressed)
- scrollbar->mouseMoved(scrollbar->transformEvent(mouseEvent)); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
+ scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
if (Page* page = m_frame->page()) {
if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) {
if (FrameView* view = m_frame->view())
@@ -1370,6 +1409,13 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
{
RefPtr<FrameView> protector(m_frame->view());
+#if ENABLE(PAN_SCROLLING)
+ if (mouseEvent.button() == MiddleButton)
+ m_panScrollButtonPressed = false;
+ if (m_springLoadedPanScrollInProgress)
+ stopAutoscrollTimer();
+#endif
+
m_mousePressed = false;
m_currentMousePosition = mouseEvent.pos();
@@ -1705,18 +1751,39 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
return false;
IntPoint vPoint = view->windowToContents(e.pos());
- HitTestRequest request(HitTestRequest::ReadOnly);
- HitTestResult result(vPoint);
- doc->renderView()->layer()->hitTest(request, result);
- Node* node = result.innerNode();
+ Node* node;
+ bool isOverWidget;
+ bool didSetLatchedNode = false;
+
+ if (m_useLatchedWheelEventNode) {
+ if (!m_latchedWheelEventNode) {
+ HitTestRequest request(HitTestRequest::ReadOnly);
+ HitTestResult result(vPoint);
+ doc->renderView()->layer()->hitTest(request, result);
+ m_latchedWheelEventNode = result.innerNode();
+ m_widgetIsLatched = result.isOverWidget();
+ didSetLatchedNode = true;
+ }
+
+ node = m_latchedWheelEventNode.get();
+ isOverWidget = m_widgetIsLatched;
+ } else {
+ if (m_latchedWheelEventNode)
+ m_latchedWheelEventNode = 0;
+
+ HitTestRequest request(HitTestRequest::ReadOnly);
+ HitTestResult result(vPoint);
+ doc->renderView()->layer()->hitTest(request, result);
+ node = result.innerNode();
+ isOverWidget = result.isOverWidget();
+ }
if (node) {
// Figure out which view to send the event to.
RenderObject* target = node->renderer();
- if (result.isOverWidget() && target && target->isWidget()) {
- Widget* widget = static_cast<RenderWidget*>(target)->widget();
-
+ if (isOverWidget && target && target->isWidget()) {
+ Widget* widget = toRenderWidget(target)->widget();
if (widget && passWheelEventToWidget(e, widget)) {
e.accept();
return true;
@@ -1896,10 +1963,8 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
#if ENABLE(PAN_SCROLLING)
if (Page* page = m_frame->page()) {
if (page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
- static const char* const escapeKeyIdentifier = "U+001B";
-
// If a key is pressed while the autoscroll/panScroll is in progress then we want to stop
- if (initialKeyEvent.keyIdentifier() == escapeKeyIdentifier && initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp)
+ if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown || initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown)
stopAutoscrollTimer();
// If we were in autoscroll/panscroll mode, we swallow the key event
@@ -2024,7 +2089,7 @@ void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event)
void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
{
- if (event->type() == eventNames().keydownEvent) {
+ if (event->type() == eventNames().keydownEvent) {
m_frame->editor()->handleKeyboardEvent(event);
if (event->defaultHandled())
return;
@@ -2034,14 +2099,14 @@ void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
// provides KB navigation and selection for enhanced accessibility users
if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
handleKeyboardSelectionMovement(event);
- }
- if (event->type() == eventNames().keypressEvent) {
+ }
+ if (event->type() == eventNames().keypressEvent) {
m_frame->editor()->handleKeyboardEvent(event);
if (event->defaultHandled())
return;
if (event->charCode() == ' ')
defaultSpaceEventHandler(event);
- }
+ }
}
bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
@@ -2099,6 +2164,9 @@ void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperat
}
freeClipboard();
dragState().m_dragSrc = 0;
+ // In case the drag was ended due to an escape key press we need to ensure
+ // that consecutive mousemove events don't reinitiate the drag and drop.
+ m_mouseDownMayStartDrag = false;
}
// returns if we should continue "default processing", i.e., whether eventhandler canceled
@@ -2365,7 +2433,7 @@ void EventHandler::capsLockStateMayHaveChanged()
if (Node* node = d->focusedNode()) {
if (RenderObject* r = node->renderer()) {
if (r->isTextField())
- static_cast<RenderTextControlSingleLine*>(r)->capsLockStateMayHaveChanged();
+ toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged();
}
}
}
@@ -2391,6 +2459,7 @@ bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults&
return scrollbar->mouseDown(mev.event());
}
+#ifdef MANUAL_MERGE_REQUIRED
#if ENABLE(TOUCH_EVENTS) // Android
bool EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
{
@@ -2499,4 +2568,18 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
}
#endif
+#else // MANUAL_MERGE_REQUIRED
+// If scrollbar (under mouse) is different from last, send a mouse exited. Set
+// last to scrollbar if setLast is true; else set last to 0.
+void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast)
+{
+ if (m_lastScrollbarUnderMouse != scrollbar) {
+ // Send mouse exited to the old scrollbar.
+ if (m_lastScrollbarUnderMouse)
+ m_lastScrollbarUnderMouse->mouseExited();
+ m_lastScrollbarUnderMouse = setLast ? scrollbar : 0;
+ }
+}
+
+#endif // MANUAL_MERGE_REQUIRED
}
diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h
index 0ad70c2..7fe64ad 100644
--- a/WebCore/page/EventHandler.h
+++ b/WebCore/page/EventHandler.h
@@ -71,7 +71,9 @@ extern const int ImageDragHysteresis;
extern const int TextDragHysteresis;
extern const int GeneralDragHysteresis;
-class EventHandler : Noncopyable {
+enum HitTestScrollbars { ShouldHitTestScrollbars, DontHitTestScrollbars };
+
+class EventHandler : public Noncopyable {
public:
EventHandler(Frame*);
~EventHandler();
@@ -90,7 +92,7 @@ public:
RenderObject* autoscrollRenderer() const;
void updateAutoscrollRenderer();
- HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false);
+ HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false, HitTestScrollbars scrollbars = DontHitTestScrollbars);
bool mousePressed() const { return m_mousePressed; }
void setMousePressed(bool pressed) { m_mousePressed = pressed; }
@@ -113,6 +115,8 @@ public:
bool scrollOverflow(ScrollDirection, ScrollGranularity);
+ bool scrollRecursively(ScrollDirection, ScrollGranularity);
+
bool shouldDragAutoNode(Node*, const IntPoint&) const; // -webkit-user-drag == auto
bool tabsToLinks(KeyboardEvent*) const;
@@ -211,7 +215,7 @@ private:
Cursor selectCursor(const MouseEventWithHitTestResults&, Scrollbar*);
#if ENABLE(PAN_SCROLLING)
- void setPanScrollCursor();
+ void updatePanScrollState();
#endif
void hoverTimerFired(Timer<EventHandler>*);
@@ -275,6 +279,8 @@ private:
void updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint);
+ void updateLastScrollbarUnderMouse(Scrollbar*, bool);
+
bool capturesDragging() const { return m_capturesDragging; }
#if PLATFORM(MAC) && defined(__OBJC__)
@@ -299,6 +305,9 @@ private:
IntPoint m_panScrollStartPos;
bool m_panScrollInProgress;
+ bool m_panScrollButtonPressed;
+ bool m_springLoadedPanScrollInProgress;
+
Timer<EventHandler> m_hoverTimer;
Timer<EventHandler> m_autoscrollTimer;
@@ -339,6 +348,10 @@ private:
double m_mouseDownTimestamp;
PlatformMouseEvent m_mouseDown;
+ bool m_useLatchedWheelEventNode;
+ RefPtr<Node> m_latchedWheelEventNode;
+ bool m_widgetIsLatched;
+
#if PLATFORM(MAC)
NSView *m_mouseDownView;
bool m_sendingEventToSubview;
diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp
index 8dad846..817801c 100644
--- a/WebCore/page/FocusController.cpp
+++ b/WebCore/page/FocusController.cpp
@@ -58,6 +58,7 @@ using namespace HTMLNames;
FocusController::FocusController(Page* page)
: m_page(page)
, m_isActive(false)
+ , m_isFocused(false)
{
}
@@ -66,16 +67,20 @@ void FocusController::setFocusedFrame(PassRefPtr<Frame> frame)
if (m_focusedFrame == frame)
return;
- if (m_focusedFrame && m_focusedFrame->view()) {
- m_focusedFrame->selection()->setFocused(false);
- m_focusedFrame->document()->dispatchWindowEvent(eventNames().blurEvent, false, false);
- }
+ RefPtr<Frame> oldFrame = m_focusedFrame;
+ RefPtr<Frame> newFrame = frame;
- m_focusedFrame = frame;
+ m_focusedFrame = newFrame;
- if (m_focusedFrame && m_focusedFrame->view()) {
- m_focusedFrame->selection()->setFocused(true);
- m_focusedFrame->document()->dispatchWindowEvent(eventNames().focusEvent, false, false);
+ // Now that the frame is updated, fire events and update the selection focused states of both frames.
+ if (oldFrame && oldFrame->view()) {
+ oldFrame->selection()->setFocused(false);
+ oldFrame->document()->dispatchWindowEvent(eventNames().blurEvent, false, false);
+ }
+
+ if (newFrame && newFrame->view() && isFocused()) {
+ newFrame->selection()->setFocused(true);
+ newFrame->document()->dispatchWindowEvent(eventNames().focusEvent, false, false);
}
}
@@ -86,6 +91,19 @@ Frame* FocusController::focusedOrMainFrame()
return m_page->mainFrame();
}
+void FocusController::setFocused(bool focused)
+{
+ if (isFocused() == focused)
+ return;
+
+ m_isFocused = focused;
+
+ if (m_focusedFrame && m_focusedFrame->view()) {
+ m_focusedFrame->selection()->setFocused(focused);
+ m_focusedFrame->document()->dispatchWindowEvent(focused ? eventNames().focusEvent : eventNames().blurEvent, false, false);
+ }
+}
+
static Node* deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event)
{
// The node we found might be a HTMLFrameOwnerElement, so descend down the frame tree until we find either:
@@ -322,7 +340,7 @@ void FocusController::setActive(bool active)
focusedOrMainFrame()->selection()->pageActivationChanged();
- if (m_focusedFrame)
+ if (m_focusedFrame && isFocused())
m_focusedFrame->document()->dispatchWindowEvent(active ? eventNames().focusEvent : eventNames().blurEvent, false, false);
}
diff --git a/WebCore/page/FocusController.h b/WebCore/page/FocusController.h
index f4a6632..33debf1 100644
--- a/WebCore/page/FocusController.h
+++ b/WebCore/page/FocusController.h
@@ -53,10 +53,14 @@ namespace WebCore {
void setActive(bool);
bool isActive() const { return m_isActive; }
+ void setFocused(bool);
+ bool isFocused() const { return m_isFocused; }
+
private:
Page* m_page;
RefPtr<Frame> m_focusedFrame;
bool m_isActive;
+ bool m_isFocused;
};
} // namespace WebCore
diff --git a/WebCore/page/Frame.cpp b/WebCore/page/Frame.cpp
index eedf09b..78cc25c 100644
--- a/WebCore/page/Frame.cpp
+++ b/WebCore/page/Frame.cpp
@@ -41,21 +41,20 @@
#include "EditingText.h"
#include "EditorClient.h"
#include "EventNames.h"
-#include "FocusController.h"
#include "FloatQuad.h"
+#include "FocusController.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLDocument.h"
+#include "HTMLFormControlElement.h"
#include "HTMLFormElement.h"
#include "HTMLFrameElementBase.h"
-#include "HTMLFormControlElement.h"
#include "HTMLNames.h"
#include "HTMLTableCellElement.h"
#include "HitTestResult.h"
#include "Logging.h"
-#include "markup.h"
#include "MediaFeatureNames.h"
#include "Navigator.h"
#include "NodeList.h"
@@ -66,12 +65,13 @@
#include "RenderTextControl.h"
#include "RenderTheme.h"
#include "RenderView.h"
+#include "ScriptController.h"
#include "Settings.h"
#include "TextIterator.h"
#include "TextResourceDecoder.h"
#include "XMLNames.h"
-#include "ScriptController.h"
#include "htmlediting.h"
+#include "markup.h"
#include "npruntime_impl.h"
#include "visible_units.h"
#include <wtf/RefCountedLeakCounter.h>
@@ -107,7 +107,7 @@ namespace WebCore {
using namespace HTMLNames;
-#ifndef NDEBUG
+#ifndef NDEBUG
static WTF::RefCountedLeakCounter frameCounter("Frame");
#endif
@@ -118,7 +118,7 @@ static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
return ownerElement->document()->frame();
}
-Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
+Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
: m_page(page)
, m_treeNode(this, parentFromOwnerElement(ownerElement))
, m_loader(this, frameLoaderClient)
@@ -166,7 +166,7 @@ Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient*
else {
page->incrementFrameCount();
// Make sure we will not end up with two frames referencing the same owner element.
- ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement));
+ ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement));
ownerElement->m_contentFrame = this;
}
@@ -179,7 +179,7 @@ Frame::~Frame()
{
setView(0);
loader()->cancelAndClear();
-
+
// FIXME: We should not be doing all this work inside the destructor
ASSERT(!m_lifeSupportTimer.isActive());
@@ -189,14 +189,14 @@ Frame::~Frame()
#endif
disconnectOwnerElement();
-
+
if (m_domWindow)
m_domWindow->disconnectFrame();
HashSet<DOMWindow*>::iterator end = m_liveFormerWindows.end();
for (HashSet<DOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it)
(*it)->disconnectFrame();
-
+
if (m_view) {
m_view->hide();
m_view->clearFrame();
@@ -265,7 +265,7 @@ void Frame::setDocument(PassRefPtr<Document> newDoc)
m_doc = newDoc;
if (m_doc && selection()->isFocusedAndActive())
setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive());
-
+
if (m_doc && !m_doc->attached())
m_doc->attach();
@@ -310,14 +310,14 @@ IntRect Frame::firstRectForRange(Range* range) const
if (startCaretRect.y() == endCaretRect.y()) {
// start and end are on the same line
- return IntRect(min(startCaretRect.x(), endCaretRect.x()),
- startCaretRect.y(),
+ return IntRect(min(startCaretRect.x(), endCaretRect.x()),
+ startCaretRect.y(),
abs(endCaretRect.x() - startCaretRect.x()),
max(startCaretRect.height(), endCaretRect.height()));
}
-
+
// start and end aren't on the same line, so go from start to the end of its line
- return IntRect(startCaretRect.x(),
+ return IntRect(startCaretRect.x(),
startCaretRect.y(),
startCaretRect.width() + extraWidthToEndOfLine,
startCaretRect.height());
@@ -368,23 +368,21 @@ static RegularExpression* createRegExpForLabels(const Vector<String>& labels)
bool startsWithWordChar = false;
bool endsWithWordChar = false;
- if (label.length() != 0) {
+ if (label.length()) {
startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
}
-
- if (i != 0)
+
+ if (i)
pattern.append("|");
// Search for word boundaries only if label starts/ends with "word characters".
// If we always searched for word boundaries, this wouldn't work for languages
// such as Japanese.
- if (startsWithWordChar) {
+ if (startsWithWordChar)
pattern.append("\\b");
- }
pattern.append(label);
- if (endsWithWordChar) {
+ if (endsWithWordChar)
pattern.append("\\b");
- }
}
pattern.append(")");
return new RegularExpression(pattern, TextCaseInsensitive);
@@ -392,10 +390,11 @@ static RegularExpression* createRegExpForLabels(const Vector<String>& labels)
String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell)
{
- RenderTableCell* cellRenderer = static_cast<RenderTableCell*>(cell->renderer());
+ RenderObject* cellRenderer = cell->renderer();
if (cellRenderer && cellRenderer->isTableCell()) {
- RenderTableCell* cellAboveRenderer = cellRenderer->table()->cellAbove(cellRenderer);
+ RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer);
+ RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer);
if (cellAboveRenderer) {
HTMLTableCellElement* aboveCell =
@@ -465,9 +464,8 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element
// If we started in a cell, but bailed because we found the start of the form or the
// previous element, we still might need to search the row above us for a label.
- if (startingTableCell && !searchedCellAbove) {
+ if (startingTableCell && !searchedCellAbove)
return searchForLabelsAboveCell(regExp.get(), startingTableCell);
- }
return String();
}
@@ -480,7 +478,7 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e
// Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
replace(name, RegularExpression("\\d", TextCaseSensitive), " ");
name.replace('_', ' ');
-
+
OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
// Use the largest match we can find in the whole name string
int pos;
@@ -565,7 +563,7 @@ static bool isFrameElement(const Node *n)
RenderObject *renderer = n->renderer();
if (!renderer || !renderer->isWidget())
return false;
- Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
+ Widget* widget = toRenderWidget(renderer)->widget();
return widget && widget->isFrameView();
}
@@ -625,7 +623,7 @@ void Frame::selectionLayoutChanged()
// Start blinking with a black caret. Be sure not to restart if we're
// already blinking in the right location.
if (shouldBlink && !m_caretBlinkTimer.isActive()) {
- if (double blinkInterval = theme()->caretBlinkInterval())
+ if (double blinkInterval = page()->theme()->caretBlinkInterval())
m_caretBlinkTimer.startRepeating(blinkInterval);
if (!m_caretPaint) {
@@ -643,7 +641,7 @@ void Frame::selectionLayoutChanged()
return;
VisibleSelection selection = this->selection()->selection();
-
+
if (!selection.isRange())
view->clearSelection();
else {
@@ -657,7 +655,7 @@ void Frame::selectionLayoutChanged()
Position endPos = selection.end();
if (endPos.upstream().isCandidate())
endPos = endPos.upstream();
-
+
// We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
// because we don't yet notify the SelectionController of text removal.
if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
@@ -732,12 +730,12 @@ bool Frame::shouldApplyPageZoom() const
}
void Frame::setZoomFactor(float percent, bool isTextOnly)
-{
+{
if (m_zoomFactor == percent && isZoomFactorTextOnly() == isTextOnly)
return;
#if ENABLE(SVG)
- // SVG doesn't care if the zoom factor is text only. It will always apply a
+ // SVG doesn't care if the zoom factor is text only. It will always apply a
// zoom to the whole SVG.
if (m_doc->isSVGDocument()) {
if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled())
@@ -796,7 +794,7 @@ String Frame::jsStatusBarText() const
String Frame::jsDefaultStatusBarText() const
{
- return m_kjsDefaultStatusBarText;
+ return m_kjsDefaultStatusBarText;
}
void Frame::setNeedsReapplyStyles()
@@ -830,7 +828,7 @@ void Frame::reapplyStyles()
// FIXME: This call doesn't really make sense in a function called reapplyStyles.
// We should probably eventually move it into its own function.
m_doc->docLoader()->setAutoLoadImages(m_page && m_page->settings()->loadsImagesAutomatically());
-
+
#if FRAME_LOADS_USER_STYLESHEET
const KURL userStyleSheetLocation = m_page ? m_page->settings()->userStyleSheetLocation() : KURL();
if (!userStyleSheetLocation.isEmpty())
@@ -862,7 +860,7 @@ bool Frame::shouldDeleteSelection(const VisibleSelection& selection) const
return editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get());
}
-bool Frame::isContentEditable() const
+bool Frame::isContentEditable() const
{
if (m_editor.clientIsEditable())
return true;
@@ -900,7 +898,7 @@ void Frame::clearTypingStyle()
void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
{
- if (!style || style->length() == 0) {
+ if (!style || !style->length()) {
clearTypingStyle();
return;
}
@@ -936,7 +934,7 @@ void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction edit
blockStyle->diff(mutableStyle.get());
if (blockStyle->length() > 0)
applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
-
+
// Set the remaining style as the typing style.
m_typingStyle = mutableStyle.release();
}
@@ -953,7 +951,7 @@ String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
if (nodeToRemove) {
ExceptionCode ec = 0;
nodeToRemove->remove(ec);
- ASSERT(ec == 0);
+ ASSERT(!ec);
}
return value;
@@ -972,7 +970,7 @@ PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nod
Element *elem = pos.element();
if (!elem)
return 0;
-
+
RefPtr<Element> styleElement = elem;
ExceptionCode ec = 0;
@@ -980,10 +978,10 @@ PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nod
styleElement = document()->createElement(spanTag, false);
styleElement->setAttribute(styleAttr, m_typingStyle->cssText().impl(), ec);
- ASSERT(ec == 0);
-
+ ASSERT(!ec);
+
styleElement->appendChild(document()->createEditingTextNode(""), ec);
- ASSERT(ec == 0);
+ ASSERT(!ec);
if (elem->renderer() && elem->renderer()->canHaveChildren()) {
elem->appendChild(styleElement, ec);
@@ -991,13 +989,12 @@ PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nod
Node *parent = elem->parent();
Node *next = elem->nextSibling();
- if (next) {
+ if (next)
parent->insertBefore(styleElement, next, ec);
- } else {
+ else
parent->appendChild(styleElement, ec);
- }
}
- ASSERT(ec == 0);
+ ASSERT(!ec);
nodeToRemove = styleElement.get();
}
@@ -1047,18 +1044,16 @@ void Frame::applyEditingStyleToBodyElement() const
{
RefPtr<NodeList> list = m_doc->getElementsByTagName("body");
unsigned len = list->length();
- for (unsigned i = 0; i < len; i++) {
- applyEditingStyleToElement(static_cast<Element*>(list->item(i)));
- }
+ for (unsigned i = 0; i < len; i++)
+ applyEditingStyleToElement(static_cast<Element*>(list->item(i)));
}
void Frame::removeEditingStyleFromBodyElement() const
{
RefPtr<NodeList> list = m_doc->getElementsByTagName("body");
unsigned len = list->length();
- for (unsigned i = 0; i < len; i++) {
- removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));
- }
+ for (unsigned i = 0; i < len; i++)
+ removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));
}
void Frame::applyEditingStyleToElement(Element* element) const
@@ -1071,11 +1066,11 @@ void Frame::applyEditingStyleToElement(Element* element) const
ExceptionCode ec = 0;
style->setProperty(CSSPropertyWordWrap, "break-word", false, ec);
- ASSERT(ec == 0);
+ ASSERT(!ec);
style->setProperty(CSSPropertyWebkitNbspMode, "space", false, ec);
- ASSERT(ec == 0);
+ ASSERT(!ec);
style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false, ec);
- ASSERT(ec == 0);
+ ASSERT(!ec);
}
void Frame::removeEditingStyleFromElement(Element*) const
@@ -1162,7 +1157,7 @@ RenderPart* Frame::ownerRenderer() const
// https://bugs.webkit.org/show_bug.cgi?id=18585
if (!object->isRenderPart())
return 0;
- return static_cast<RenderPart*>(object);
+ return toRenderPart(object);
}
bool Frame::isDisconnected() const
@@ -1192,7 +1187,7 @@ FloatRect Frame::selectionBounds(bool clipToVisibleContent) const
FrameView* view = m_view.get();
if (!root || !view)
return IntRect();
-
+
IntRect selectionRect = root->selectionBounds(clipToVisibleContent);
return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect;
}
@@ -1243,7 +1238,7 @@ HTMLFormElement *Frame::currentForm() const
Node *start = m_doc ? m_doc->focusedNode() : 0;
if (!start)
start = selection()->start().node();
-
+
// try walking up the node tree to find a form element
Node *n;
for (n = start; n; n = n->parentNode()) {
@@ -1252,7 +1247,7 @@ HTMLFormElement *Frame::currentForm() const
else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())
return static_cast<HTMLFormControlElement*>(n)->form();
}
-
+
// try walking forward in the node tree to find a form element
return start ? scanForForm(start) : 0;
}
@@ -1262,21 +1257,21 @@ void Frame::revealSelection(const ScrollAlignment& alignment, bool revealExtent)
IntRect rect;
switch (selection()->selectionType()) {
- case VisibleSelection::NoSelection:
- return;
- case VisibleSelection::CaretSelection:
- rect = selection()->absoluteCaretBounds();
- break;
- case VisibleSelection::RangeSelection:
- rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false));
- break;
+ case VisibleSelection::NoSelection:
+ return;
+ case VisibleSelection::CaretSelection:
+ rect = selection()->absoluteCaretBounds();
+ break;
+ case VisibleSelection::RangeSelection:
+ rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false));
+ break;
}
Position start = selection()->start();
ASSERT(start.node());
if (start.node() && start.node()->renderer()) {
// FIXME: This code only handles scrolling the startContainer's layer, but
- // the selection rect could intersect more than just that.
+ // the selection rect could intersect more than just that.
// See <rdar://problem/4799899>.
if (RenderLayer* layer = start.node()->renderer()->enclosingLayer())
layer->scrollRectToVisible(rect, false, alignment, alignment);
@@ -1316,46 +1311,46 @@ void Frame::clearTimers()
RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
{
nodeToRemove = 0;
-
+
if (selection()->isNone())
return 0;
-
+
Position pos = selection()->selection().visibleStart().deepEquivalent();
if (!pos.isCandidate())
return 0;
Node *node = pos.node();
if (!node)
return 0;
-
+
if (!m_typingStyle)
return node->renderer()->style();
-
+
RefPtr<Element> styleElement = document()->createElement(spanTag, false);
-
+
ExceptionCode ec = 0;
String styleText = m_typingStyle->cssText() + " display: inline";
styleElement->setAttribute(styleAttr, styleText.impl(), ec);
- ASSERT(ec == 0);
-
+ ASSERT(!ec);
+
styleElement->appendChild(document()->createEditingTextNode(""), ec);
- ASSERT(ec == 0);
-
+ ASSERT(!ec);
+
node->parentNode()->appendChild(styleElement, ec);
- ASSERT(ec == 0);
-
- nodeToRemove = styleElement.get();
+ ASSERT(!ec);
+
+ nodeToRemove = styleElement.get();
return styleElement->renderer() ? styleElement->renderer()->style() : 0;
}
void Frame::setSelectionFromNone()
{
- // Put a caret inside the body if the entire frame is editable (either the
+ // Put a caret inside the body if the entire frame is editable (either the
// entire WebView is editable or designMode is on for this document).
Document *doc = document();
bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
if (!selection()->isNone() || !(isContentEditable() || caretBrowsing))
return;
-
+
Node* node = doc->documentElement();
while (node && !node->hasTagName(bodyTag))
node = node->traverseNextNode();
@@ -1378,10 +1373,10 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
{
if (target.isEmpty())
return false;
-
+
if (excludeFromTextSearch())
return false;
-
+
// Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
// is used depends on whether we're searching forward or backward, and whether startInSelection is set.
RefPtr<Range> searchRange(rangeOfContents(document()));
@@ -1422,7 +1417,7 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
}
-
+
ExceptionCode exception = 0;
// If nothing was found in the shadow tree, search in main content following the shadow tree.
@@ -1435,7 +1430,7 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
}
-
+
if (!editor()->insideVisibleArea(resultRange.get())) {
resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag);
if (!resultRange)
@@ -1464,9 +1459,9 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
{
if (target.isEmpty())
return 0;
-
+
RefPtr<Range> searchRange(rangeOfContents(document()));
-
+
ExceptionCode exception = 0;
unsigned matchCount = 0;
do {
@@ -1479,7 +1474,7 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception);
continue;
}
-
+
// A non-collapsed result range can in some funky whitespace cases still not
// advance the range's start position (4509328). Break to avoid infinite loop.
VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
@@ -1491,18 +1486,18 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
++matchCount;
document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);
}
-
+
// Stop looking if we hit the specified limit. A limit of 0 means no limit.
if (limit > 0 && matchCount >= limit)
break;
-
+
setStart(searchRange.get(), newStart);
Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
if (searchRange->collapsed(exception) && shadowTreeRoot)
searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception);
} while (true);
-
- // Do a "fake" paint in order to execute the code that computes the rendered rect for
+
+ // Do a "fake" paint in order to execute the code that computes the rendered rect for
// each text match.
Document* doc = document();
if (m_view && contentRenderer()) {
@@ -1514,7 +1509,7 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
m_view->paintContents(&context, visibleRect);
}
}
-
+
return matchCount;
}
@@ -1527,7 +1522,7 @@ void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
{
if (flag == m_highlightTextMatches)
return;
-
+
m_highlightTextMatches = flag;
document()->repaintMarkers(DocumentMarker::TextMatch);
}
@@ -1556,7 +1551,7 @@ DOMWindow* Frame::domWindow() const
void Frame::clearFormerDOMWindow(DOMWindow* window)
{
- m_liveFormerWindows.remove(window);
+ m_liveFormerWindows.remove(window);
}
Page* Frame::page() const
@@ -1623,7 +1618,7 @@ void Frame::unfocusWindow()
{
if (!page())
return;
-
+
// If we're a top level window, deactivate the window.
if (!tree()->parent())
page()->chrome()->unfocus();
@@ -1685,14 +1680,13 @@ void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool
// oldSelection may no longer be in the document.
if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
VisiblePosition oldStart(oldSelection.visibleStart());
- VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
+ VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
if (oldAdjacentWords != newAdjacentWords) {
if (isContinuousGrammarCheckingEnabled) {
VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence);
- } else {
+ } else
editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
- }
}
}
@@ -1727,15 +1721,15 @@ VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
visiblePos = VisiblePosition(Position(node, 0));
return visiblePos;
}
-
+
Document* Frame::documentAtPoint(const IntPoint& point)
-{
- if (!view())
+{
+ if (!view())
return 0;
-
+
IntPoint pt = view()->windowToContents(point);
HitTestResult result = HitTestResult(pt);
-
+
if (contentRenderer())
result = eventHandler()->hitTestResultAtPoint(pt, false);
return result.innerNode() ? result.innerNode()->document() : 0;
@@ -1776,7 +1770,7 @@ void Frame::createView(const IntSize& viewportSize,
frameView->setParentVisible(true);
if (ownerRenderer())
- ownerRenderer()->setWidget(frameView.get());
+ ownerRenderer()->setWidget(frameView);
if (HTMLFrameOwnerElement* owner = ownerElement())
view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
diff --git a/WebCore/page/Frame.h b/WebCore/page/Frame.h
index acd91e5..1b55612 100644
--- a/WebCore/page/Frame.h
+++ b/WebCore/page/Frame.h
@@ -37,8 +37,8 @@
#include "FrameLoader.h"
#include "FrameTree.h"
#include "Range.h"
-#include "ScrollBehavior.h"
#include "ScriptController.h"
+#include "ScrollBehavior.h"
#include "SelectionController.h"
#include "TextGranularity.h"
@@ -62,29 +62,99 @@ typedef struct HBITMAP__* HBITMAP;
namespace WebCore {
-class CSSMutableStyleDeclaration;
-class Editor;
-class EventHandler;
-class FrameLoader;
-class FrameLoaderClient;
-class FrameTree;
-class FrameView;
-class HTMLFrameOwnerElement;
-class HTMLTableCellElement;
-class RegularExpression;
-class RenderPart;
-class ScriptController;
-class SelectionController;
-class Settings;
-class VisibleSelection;
-class Widget;
+ class CSSMutableStyleDeclaration;
+ class Editor;
+ class EventHandler;
+ class FrameLoader;
+ class FrameLoaderClient;
+ class FrameTree;
+ class FrameView;
+ class HTMLFrameOwnerElement;
+ class HTMLTableCellElement;
+ class RegularExpression;
+ class RenderPart;
+ class ScriptController;
+ class SelectionController;
+ class Settings;
+ class VisibleSelection;
+ class Widget;
#if FRAME_LOADS_USER_STYLESHEET
class UserStyleSheetLoader;
#endif
-template <typename T> class Timer;
+ template <typename T> class Timer;
+
+ class Frame : public RefCounted<Frame> {
+ public:
+ static PassRefPtr<Frame> create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
+ {
+ return adoptRef(new Frame(page, ownerElement, client));
+ }
+ void setView(PassRefPtr<FrameView>);
+ ~Frame();
+
+ void init();
+
+ Page* page() const;
+ HTMLFrameOwnerElement* ownerElement() const;
+
+ void pageDestroyed();
+ void disconnectOwnerElement();
+
+ Document* document() const;
+ FrameView* view() const;
+
+ void setDOMWindow(DOMWindow*);
+ DOMWindow* domWindow() const;
+ void clearFormerDOMWindow(DOMWindow*);
+
+ Editor* editor() const;
+ EventHandler* eventHandler() const;
+ FrameLoader* loader() const;
+ SelectionController* selection() const;
+ FrameTree* tree() const;
+ AnimationController* animation() const;
+ ScriptController* script();
+
+ RenderView* contentRenderer() const; // root renderer for the document contained in this frame
+ RenderPart* ownerRenderer() const; // renderer for the element that contains this frame
+
+ bool isDisconnected() const;
+ void setIsDisconnected(bool);
+ bool excludeFromTextSearch() const;
+ void setExcludeFromTextSearch(bool);
+
+ void createView(const IntSize&, const Color&, bool, const IntSize &, bool,
+ ScrollbarMode = ScrollbarAuto, ScrollbarMode = ScrollbarAuto);
+
+ private:
+ Frame(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
+
+ // === undecided, would like to consider moving to another class
+
+ public:
+ static Frame* frameForWidget(const Widget*);
+
+ Settings* settings() const; // can be NULL
+
+ #if FRAME_LOADS_USER_STYLESHEET
+ void setUserStyleSheetLocation(const KURL&);
+ void setUserStyleSheet(const String& styleSheetData);
+ #endif
+
+ void setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize);
+
+ bool inViewSourceMode() const;
+ void setInViewSourceMode(bool = true);
+
+ void keepAlive(); // Used to keep the frame alive when running a script that might destroy it.
+ #ifndef NDEBUG
+ static void cancelAllKeepAlive();
+ #endif
+
+#ifdef MANUAL_MERGE_REQUIRED
class Frame : public RefCounted<Frame> {
public:
static PassRefPtr<Frame> create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
@@ -133,244 +203,225 @@ private:
Frame(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
// === undecided, would like to consider moving to another class
+#else // MANUAL_MERGE_REQUIRED
+ void setDocument(PassRefPtr<Document>);
+#endif // MANUAL_MERGE_REQUIRED
-public:
- static Frame* frameForWidget(const Widget*);
-
- Settings* settings() const; // can be NULL
-
-#if FRAME_LOADS_USER_STYLESHEET
- void setUserStyleSheetLocation(const KURL&);
- void setUserStyleSheet(const String& styleSheetData);
-#endif
-
- void setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize);
+ void clearTimers();
+ static void clearTimers(FrameView*, Document*);
- bool inViewSourceMode() const;
- void setInViewSourceMode(bool = true);
+ void setNeedsReapplyStyles();
+ bool needsReapplyStyles() const;
+ void reapplyStyles();
- void keepAlive(); // Used to keep the frame alive when running a script that might destroy it.
-#ifndef NDEBUG
- static void cancelAllKeepAlive();
-#endif
+ String documentTypeString() const;
- void setDocument(PassRefPtr<Document>);
+ // This method -- and the corresponding list of former DOM windows --
+ // should move onto ScriptController
+ void clearDOMWindow();
- void clearTimers();
- static void clearTimers(FrameView*, Document*);
+ String displayStringModifiedByEncoding(const String& str) const
+ {
+ return document() ? document()->displayStringModifiedByEncoding(str) : str;
+ }
- void setNeedsReapplyStyles();
- bool needsReapplyStyles() const;
- void reapplyStyles();
+ private:
+ void lifeSupportTimerFired(Timer<Frame>*);
- String documentTypeString() const;
+ // === to be moved into FrameView
- // This method -- and the corresponding list of former DOM windows --
- // should move onto ScriptController
- void clearDOMWindow();
+ public:
+ void setZoomFactor(float scale, bool isTextOnly);
+ float zoomFactor() const;
+ bool isZoomFactorTextOnly() const;
+ bool shouldApplyTextZoom() const;
+ bool shouldApplyPageZoom() const;
+ float pageZoomFactor() const { return shouldApplyPageZoom() ? zoomFactor() : 1.0f; }
+ float textZoomFactor() const { return shouldApplyTextZoom() ? zoomFactor() : 1.0f; }
- String displayStringModifiedByEncoding(const String& str) const
- {
- return document() ? document()->displayStringModifiedByEncoding(str) : str;
- }
+ // === to be moved into Chrome
-private:
- void lifeSupportTimerFired(Timer<Frame>*);
+ public:
+ void focusWindow();
+ void unfocusWindow();
+ bool shouldClose(RegisteredEventListenerVector* alternateEventListeners = 0);
+ void scheduleClose();
-// === to be moved into FrameView
+ void setJSStatusBarText(const String&);
+ void setJSDefaultStatusBarText(const String&);
+ String jsStatusBarText() const;
+ String jsDefaultStatusBarText() const;
-public:
- void setZoomFactor(float scale, bool isTextOnly);
- float zoomFactor() const;
- bool isZoomFactorTextOnly() const;
- bool shouldApplyTextZoom() const;
- bool shouldApplyPageZoom() const;
- float pageZoomFactor() const { return shouldApplyPageZoom() ? zoomFactor() : 1.0f; }
- float textZoomFactor() const { return shouldApplyTextZoom() ? zoomFactor() : 1.0f; }
+ // === to be moved into Editor
-// === to be moved into Chrome
+ public:
+ String selectedText() const;
+ bool findString(const String&, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection);
-public:
- void focusWindow();
- void unfocusWindow();
- bool shouldClose(RegisteredEventListenerVector* alternateEventListeners = 0);
- void scheduleClose();
+ const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
+ void setMark(const VisibleSelection&);
- void setJSStatusBarText(const String&);
- void setJSDefaultStatusBarText(const String&);
- String jsStatusBarText() const;
- String jsDefaultStatusBarText() const;
+ void computeAndSetTypingStyle(CSSStyleDeclaration* , EditAction = EditActionUnspecified);
+ String selectionStartStylePropertyValue(int stylePropertyID) const;
+ void applyEditingStyleToBodyElement() const;
+ void removeEditingStyleFromBodyElement() const;
+ void applyEditingStyleToElement(Element*) const;
+ void removeEditingStyleFromElement(Element*) const;
-// === to be moved into Editor
+ IntRect firstRectForRange(Range*) const;
-public:
- String selectedText() const;
- bool findString(const String&, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection);
+ void respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping);
+ bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
- const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
- void setMark(const VisibleSelection&);
+ RenderStyle* styleForSelectionStart(Node*& nodeToRemove) const;
- void computeAndSetTypingStyle(CSSStyleDeclaration* , EditAction = EditActionUnspecified);
- String selectionStartStylePropertyValue(int stylePropertyID) const;
- void applyEditingStyleToBodyElement() const;
- void removeEditingStyleFromBodyElement() const;
- void applyEditingStyleToElement(Element*) const;
- void removeEditingStyleFromElement(Element*) const;
+ unsigned markAllMatchesForText(const String&, bool caseFlag, unsigned limit);
+ bool markedTextMatchesAreHighlighted() const;
+ void setMarkedTextMatchesAreHighlighted(bool flag);
- IntRect firstRectForRange(Range*) const;
-
- void respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping);
- bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
+ PassRefPtr<CSSComputedStyleDeclaration> selectionComputedStyle(Node*& nodeToRemove) const;
- RenderStyle* styleForSelectionStart(Node*& nodeToRemove) const;
+ void textFieldDidBeginEditing(Element*);
+ void textFieldDidEndEditing(Element*);
+ void textDidChangeInTextField(Element*);
+ bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*);
+ void textWillBeDeletedInTextField(Element* input);
+ void textDidChangeInTextArea(Element*);
- unsigned markAllMatchesForText(const String&, bool caseFlag, unsigned limit);
- bool markedTextMatchesAreHighlighted() const;
- void setMarkedTextMatchesAreHighlighted(bool flag);
+ DragImageRef dragImageForSelection();
- PassRefPtr<CSSComputedStyleDeclaration> selectionComputedStyle(Node*& nodeToRemove) const;
+ // === to be moved into SelectionController
- void textFieldDidBeginEditing(Element*);
- void textFieldDidEndEditing(Element*);
- void textDidChangeInTextField(Element*);
- bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*);
- void textWillBeDeletedInTextField(Element* input);
- void textDidChangeInTextArea(Element*);
+ public:
+ TextGranularity selectionGranularity() const;
+ void setSelectionGranularity(TextGranularity);
- DragImageRef dragImageForSelection();
-
-// === to be moved into SelectionController
+ bool shouldChangeSelection(const VisibleSelection&) const;
+ bool shouldDeleteSelection(const VisibleSelection&) const;
+ void clearCaretRectIfNeeded();
+ void setFocusedNodeIfNeeded();
+ void selectionLayoutChanged();
+ void notifyRendererOfSelectionChange(bool userTriggered);
-public:
- TextGranularity selectionGranularity() const;
- void setSelectionGranularity(TextGranularity);
+ void invalidateSelection();
- bool shouldChangeSelection(const VisibleSelection&) const;
- bool shouldDeleteSelection(const VisibleSelection&) const;
- void clearCaretRectIfNeeded();
- void setFocusedNodeIfNeeded();
- void selectionLayoutChanged();
- void notifyRendererOfSelectionChange(bool userTriggered);
+ void setCaretVisible(bool = true);
+ void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
+ void paintDragCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
- void invalidateSelection();
+ bool isContentEditable() const; // if true, everything in frame is editable
- void setCaretVisible(bool = true);
- void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
- void paintDragCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
+ void updateSecureKeyboardEntryIfActive();
- bool isContentEditable() const; // if true, everything in frame is editable
+ CSSMutableStyleDeclaration* typingStyle() const;
+ void setTypingStyle(CSSMutableStyleDeclaration*);
+ void clearTypingStyle();
- void updateSecureKeyboardEntryIfActive();
+ FloatRect selectionBounds(bool clipToVisibleContent = true) const;
+ void selectionTextRects(Vector<FloatRect>&, bool clipToVisibleContent = true) const;
- CSSMutableStyleDeclaration* typingStyle() const;
- void setTypingStyle(CSSMutableStyleDeclaration*);
- void clearTypingStyle();
+ HTMLFormElement* currentForm() const;
- FloatRect selectionBounds(bool clipToVisibleContent = true) const;
- void selectionTextRects(Vector<FloatRect>&, bool clipToVisibleContent = true) const;
+ void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, bool revealExtent = false);
+ void setSelectionFromNone();
- HTMLFormElement* currentForm() const;
+ void setUseSecureKeyboardEntry(bool);
- void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, bool revealExtent = false);
- void setSelectionFromNone();
+ private:
+ void caretBlinkTimerFired(Timer<Frame>*);
- void setUseSecureKeyboardEntry(bool);
+ public:
+ SelectionController* dragCaretController() const;
-private:
- void caretBlinkTimerFired(Timer<Frame>*);
+ String searchForLabelsAboveCell(RegularExpression*, HTMLTableCellElement*);
+ String searchForLabelsBeforeElement(const Vector<String>& labels, Element*);
+ String matchLabelsAgainstElement(const Vector<String>& labels, Element*);
-public:
- SelectionController* dragCaretController() const;
+ VisiblePosition visiblePositionForPoint(const IntPoint& framePoint);
+ Document* documentAtPoint(const IntPoint& windowPoint);
- String searchForLabelsAboveCell(RegularExpression*, HTMLTableCellElement*);
- String searchForLabelsBeforeElement(const Vector<String>& labels, Element*);
- String matchLabelsAgainstElement(const Vector<String>& labels, Element*);
-
- VisiblePosition visiblePositionForPoint(const IntPoint& framePoint);
- Document* documentAtPoint(const IntPoint& windowPoint);
+ #if PLATFORM(MAC)
-#if PLATFORM(MAC)
+ // === undecided, would like to consider moving to another class
-// === undecided, would like to consider moving to another class
+ public:
+ NSString* searchForNSLabelsAboveCell(RegularExpression*, HTMLTableCellElement*);
+ NSString* searchForLabelsBeforeElement(NSArray* labels, Element*);
+ NSString* matchLabelsAgainstElement(NSArray* labels, Element*);
-public:
- NSString* searchForNSLabelsAboveCell(RegularExpression*, HTMLTableCellElement*);
- NSString* searchForLabelsBeforeElement(NSArray* labels, Element*);
- NSString* matchLabelsAgainstElement(NSArray* labels, Element*);
+ #if ENABLE(DASHBOARD_SUPPORT)
+ NSMutableDictionary* dashboardRegionsDictionary();
+ #endif
-#if ENABLE(DASHBOARD_SUPPORT)
- NSMutableDictionary* dashboardRegionsDictionary();
-#endif
+ NSImage* selectionImage(bool forceBlackText = false) const;
+ NSImage* snapshotDragImage(Node*, NSRect* imageRect, NSRect* elementRect) const;
+ NSImage* nodeImage(Node*) const;
- NSImage* selectionImage(bool forceBlackText = false) const;
- NSImage* snapshotDragImage(Node*, NSRect* imageRect, NSRect* elementRect) const;
- NSImage* nodeImage(Node*) const;
+ private:
+ NSImage* imageFromRect(NSRect) const;
-private:
- NSImage* imageFromRect(NSRect) const;
+ // === to be moved into Editor
-// === to be moved into Editor
+ public:
+ NSDictionary* fontAttributesForSelectionStart() const;
+ NSWritingDirection baseWritingDirectionForSelectionStart() const;
-public:
- NSDictionary* fontAttributesForSelectionStart() const;
- NSWritingDirection baseWritingDirectionForSelectionStart() const;
+ #endif
-#endif
+ #if PLATFORM(WIN)
-#if PLATFORM(WIN)
+ public:
+ // FIXME - We should have a single version of nodeImage instead of using platform types.
+ HBITMAP nodeImage(Node*) const;
-public:
- // FIXME - We should have a single version of nodeImage instead of using platform types.
- HBITMAP nodeImage(Node*) const;
+ #endif
-#endif
+ private:
+ Page* m_page;
+ mutable FrameTree m_treeNode;
+ mutable FrameLoader m_loader;
-private:
- Page* m_page;
- mutable FrameTree m_treeNode;
- mutable FrameLoader m_loader;
+ mutable RefPtr<DOMWindow> m_domWindow;
+ HashSet<DOMWindow*> m_liveFormerWindows;
- mutable RefPtr<DOMWindow> m_domWindow;
- HashSet<DOMWindow*> m_liveFormerWindows;
+ HTMLFrameOwnerElement* m_ownerElement;
+ RefPtr<FrameView> m_view;
+ RefPtr<Document> m_doc;
- HTMLFrameOwnerElement* m_ownerElement;
- RefPtr<FrameView> m_view;
- RefPtr<Document> m_doc;
+ ScriptController m_script;
- ScriptController m_script;
+ String m_kjsStatusBarText;
+ String m_kjsDefaultStatusBarText;
- String m_kjsStatusBarText;
- String m_kjsDefaultStatusBarText;
+ float m_zoomFactor;
- float m_zoomFactor;
+ TextGranularity m_selectionGranularity;
- TextGranularity m_selectionGranularity;
+ mutable SelectionController m_selectionController;
+ mutable VisibleSelection m_mark;
+ Timer<Frame> m_caretBlinkTimer;
+ mutable Editor m_editor;
+ mutable EventHandler m_eventHandler;
+ mutable AnimationController m_animationController;
- mutable SelectionController m_selectionController;
- mutable VisibleSelection m_mark;
- Timer<Frame> m_caretBlinkTimer;
- mutable Editor m_editor;
- mutable EventHandler m_eventHandler;
- mutable AnimationController m_animationController;
+ RefPtr<CSSMutableStyleDeclaration> m_typingStyle;
- RefPtr<CSSMutableStyleDeclaration> m_typingStyle;
+ Timer<Frame> m_lifeSupportTimer;
- Timer<Frame> m_lifeSupportTimer;
+ bool m_caretVisible;
+ bool m_caretPaint;
- bool m_caretVisible;
- bool m_caretPaint;
-
- bool m_highlightTextMatches;
- bool m_inViewSourceMode;
- bool m_needsReapplyStyles;
- bool m_isDisconnected;
- bool m_excludeFromTextSearch;
+ bool m_highlightTextMatches;
+ bool m_inViewSourceMode;
+ bool m_needsReapplyStyles;
+ bool m_isDisconnected;
+ bool m_excludeFromTextSearch;
-#if FRAME_LOADS_USER_STYLESHEET
- UserStyleSheetLoader* m_userStyleSheetLoader;
-#endif
+ #if FRAME_LOADS_USER_STYLESHEET
+ UserStyleSheetLoader* m_userStyleSheetLoader;
+ #endif
-};
+ };
} // namespace WebCore
diff --git a/WebCore/page/FrameTree.h b/WebCore/page/FrameTree.h
index d4c8c43..9ab999f 100644
--- a/WebCore/page/FrameTree.h
+++ b/WebCore/page/FrameTree.h
@@ -26,7 +26,7 @@ namespace WebCore {
class Frame;
- class FrameTree : Noncopyable {
+ class FrameTree : public Noncopyable {
public:
FrameTree(Frame* thisFrame, Frame* parentFrame)
: m_thisFrame(thisFrame)
diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp
index f753447..ed91587 100644
--- a/WebCore/page/FrameView.cpp
+++ b/WebCore/page/FrameView.cpp
@@ -6,6 +6,7 @@
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* (C) 2006 Graham Dennis (graham.dennis@gmail.com)
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ * Copyright (C) 2009 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -114,7 +115,6 @@ FrameView::FrameView(Frame* frame)
, m_shouldUpdateWhileOffscreen(true)
, m_deferSetNeedsLayouts(0)
, m_setNeedsLayoutWasDeferred(false)
- , m_lockedToAnchor(false)
{
init();
}
@@ -188,7 +188,7 @@ void FrameView::reset()
m_isPainting = false;
m_isVisuallyNonEmpty = false;
m_firstVisuallyNonEmptyLayoutCallbackPending = true;
- m_lockedToAnchor = false;
+ m_maintainScrollPositionAnchor = 0;
}
bool FrameView::isFrameView() const
@@ -232,6 +232,30 @@ void FrameView::init()
}
}
+void FrameView::detachCustomScrollbars()
+{
+ if (!m_frame)
+ return;
+
+ Document* document = m_frame->document();
+ if (!document)
+ return;
+
+ Element* body = document->body();
+ if (!body)
+ return;
+
+ RenderBox* renderBox = body->renderBox();
+
+ Scrollbar* horizontalBar = horizontalScrollbar();
+ if (horizontalBar && horizontalBar->isCustomScrollbar() && toRenderScrollbar(horizontalBar)->owningRenderer() == renderBox)
+ setHasHorizontalScrollbar(false);
+
+ Scrollbar* verticalBar = verticalScrollbar();
+ if (verticalBar && verticalBar->isCustomScrollbar() && toRenderScrollbar(verticalBar)->owningRenderer() == renderBox)
+ setHasVerticalScrollbar(false);
+}
+
void FrameView::clear()
{
setCanBlitOnScroll(true);
@@ -396,15 +420,18 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S
}
#if USE(ACCELERATED_COMPOSITING)
-void FrameView::updateCompositingLayers(CompositingUpdate updateType)
+void FrameView::updateCompositingLayers()
{
RenderView* view = m_frame->contentRenderer();
- if (!view || !view->usesCompositing())
+ if (!view)
return;
- if (updateType == ForcedCompositingUpdate)
- view->compositor()->setCompositingLayersNeedUpdate();
+ // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
+ view->compositor()->cacheAcceleratedCompositingEnabledFlag();
+ if (!view->usesCompositing())
+ return;
+
view->compositor()->updateCompositingLayers();
}
@@ -416,6 +443,37 @@ void FrameView::setNeedsOneShotDrawingSynchronization()
}
#endif // USE(ACCELERATED_COMPOSITING)
+bool FrameView::syncCompositingStateRecursive()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ ASSERT(m_frame->view() == this);
+ RenderView* contentRenderer = m_frame->contentRenderer();
+ if (!contentRenderer)
+ return true; // We don't want to keep trying to update layers if we have no renderer.
+
+ if (m_layoutTimer.isActive()) {
+ // Don't sync layers if there's a layout pending.
+ return false;
+ }
+
+ if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
+ rootLayer->syncCompositingState();
+
+ bool allSubframesSynced = true;
+ const HashSet<RefPtr<Widget> >* viewChildren = children();
+ HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
+ for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
+ Widget* widget = (*current).get();
+ if (widget->isFrameView()) {
+ bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive();
+ allSubframesSynced &= synced;
+ }
+ }
+ return allSubframesSynced;
+#endif // USE(ACCELERATED_COMPOSITING)
+ return true;
+}
+
void FrameView::didMoveOnscreen()
{
RenderView* view = m_frame->contentRenderer();
@@ -603,7 +661,9 @@ void FrameView::layout(bool allowSubtree)
// Now update the positions of all layers.
beginDeferredRepaints();
- layer->updateLayerPositions(m_doFullRepaint);
+ layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
+ | RenderLayer::CheckForRepaint
+ | RenderLayer::UpdateCompositingLayers);
endDeferredRepaints();
#if USE(ACCELERATED_COMPOSITING)
@@ -649,9 +709,6 @@ void FrameView::layout(bool allowSubtree)
ASSERT(m_enqueueEvents);
}
- if (lockedToAnchor())
- m_frame->loader()->gotoAnchor();
-
m_nestedLayoutCount--;
}
@@ -734,11 +791,27 @@ void FrameView::restoreScrollbar()
setScrollbarsSuppressed(false);
}
+void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
+{
+ m_maintainScrollPositionAnchor = anchorNode;
+ if (!m_maintainScrollPositionAnchor)
+ return;
+
+ // We need to update the layout before scrolling, otherwise we could
+ // really mess things up if an anchor scroll comes at a bad moment.
+ m_frame->document()->updateStyleIfNeeded();
+ // Only do a layout if changes have occurred that make it necessary.
+ if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
+ layout();
+ else
+ scrollToAnchor();
+}
+
void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
{
bool wasInProgrammaticScroll = m_inProgrammaticScroll;
m_inProgrammaticScroll = true;
- setLockedToAnchor(false);
+ m_maintainScrollPositionAnchor = 0;
ScrollView::scrollRectIntoViewRecursively(r);
m_inProgrammaticScroll = wasInProgrammaticScroll;
}
@@ -747,7 +820,7 @@ void FrameView::setScrollPosition(const IntPoint& scrollPoint)
{
bool wasInProgrammaticScroll = m_inProgrammaticScroll;
m_inProgrammaticScroll = true;
- setLockedToAnchor(false);
+ m_maintainScrollPositionAnchor = 0;
ScrollView::setScrollPosition(scrollPoint);
m_inProgrammaticScroll = wasInProgrammaticScroll;
}
@@ -800,6 +873,19 @@ void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
ScrollView::repaintContentRectangle(r, immediate);
}
+void FrameView::visibleContentsResized()
+{
+ // We check to make sure the view is attached to a frame() as this method can
+ // be triggered before the view is attached by Frame::createView(...) setting
+ // various values such as setScrollBarModes(...) for example. An ASSERT is
+ // triggered when a view is layout before being attached to a frame().
+ if (!frame()->view())
+ return;
+
+ if (needsLayout())
+ layout();
+}
+
void FrameView::beginDeferredRepaints()
{
Page* page = m_frame->page();
@@ -1118,6 +1204,27 @@ void FrameView::resumeScheduledEvents()
ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
}
+void FrameView::scrollToAnchor()
+{
+ RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
+ if (!anchorNode)
+ return;
+
+ if (!anchorNode->renderer())
+ return;
+
+ IntRect rect;
+ if (anchorNode != m_frame->document())
+ rect = anchorNode->getRect();
+
+ // Scroll nested layers and frames to reveal the anchor.
+ // Align to the top and to the closest side (this matches other browsers).
+ anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
+
+ // scrollRectToVisible can call into scrollRectIntoViewRecursively(), which resets m_maintainScrollPositionAnchor.
+ m_maintainScrollPositionAnchor = anchorNode;
+}
+
bool FrameView::updateWidgets()
{
if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
@@ -1161,7 +1268,9 @@ void FrameView::performPostLayoutTasks()
if (updateWidgets())
break;
}
-
+
+ scrollToAnchor();
+
resumeScheduledEvents();
if (!root->printing()) {
@@ -1326,10 +1435,10 @@ void FrameView::updateControlTints()
// to define when controls get the tint and to call this function when that changes.
// Optimize the common case where we bring a window to the front while it's still empty.
- if (!m_frame || m_frame->loader()->url().isEmpty())
+ if (!m_frame || m_frame->loader()->url().isEmpty())
return;
-
- if (theme()->supportsControlTints() && m_frame->contentRenderer()) {
+
+ if (m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) {
if (needsLayout())
layout();
PlatformGraphicsContext* const noContext = 0;
@@ -1351,7 +1460,7 @@ void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
{
if (m_inProgrammaticScroll)
return;
- setLockedToAnchor(false);
+ m_maintainScrollPositionAnchor = 0;
m_wasScrolledByUser = wasScrolledByUser;
}
@@ -1395,6 +1504,13 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
if (needsLayout())
return;
+#if USE(ACCELERATED_COMPOSITING)
+ if (!p->paintingDisabled()) {
+ if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
+ rootLayer->syncCompositingState();
+ }
+#endif
+
ASSERT(!m_isPainting);
m_isPainting = true;
@@ -1447,11 +1563,13 @@ void FrameView::layoutIfNeededRecursive()
if (needsLayout())
layout();
- const HashSet<Widget*>* viewChildren = children();
- HashSet<Widget*>::const_iterator end = viewChildren->end();
- for (HashSet<Widget*>::const_iterator current = viewChildren->begin(); current != end; ++current)
- if ((*current)->isFrameView())
- static_cast<FrameView*>(*current)->layoutIfNeededRecursive();
+ const HashSet<RefPtr<Widget> >* viewChildren = children();
+ HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
+ for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
+ Widget* widget = (*current).get();
+ if (widget->isFrameView())
+ static_cast<FrameView*>(widget)->layoutIfNeededRecursive();
+ }
// layoutIfNeededRecursive is called when we need to make sure layout is up-to-date before
// painting, so we need to flush out any deferred repaints too.
@@ -1517,4 +1635,142 @@ void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom
*newBottom = oldBottom;
}
+IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
+{
+ IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
+
+ // Convert from page ("absolute") to FrameView coordinates.
+ rect.move(-scrollX(), -scrollY());
+
+ return rect;
+}
+
+IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
+{
+ IntRect rect = viewRect;
+
+ // Convert from FrameView coords into page ("absolute") coordinates.
+ rect.move(scrollX(), scrollY());
+
+ // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
+ // move the rect for now.
+ rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
+ return rect;
+}
+
+IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
+{
+ IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
+
+ // Convert from page ("absolute") to FrameView coordinates.
+ point.move(-scrollX(), -scrollY());
+ return point;
+}
+
+IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
+{
+ IntPoint point = viewPoint;
+
+ // Convert from FrameView coords into page ("absolute") coordinates.
+ point += IntSize(scrollX(), scrollY());
+
+ return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
+}
+
+IntRect FrameView::convertToContainingView(const IntRect& localRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return localRect;
+
+ IntRect rect(localRect);
+ // Add borders and padding??
+ rect.move(renderer->borderLeft() + renderer->paddingLeft(),
+ renderer->borderTop() + renderer->paddingTop());
+ return parentView->convertFromRenderer(renderer, rect);
+ }
+
+ return Widget::convertToContainingView(localRect);
+ }
+
+ return localRect;
+}
+
+IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return parentRect;
+
+ IntRect rect = parentView->convertToRenderer(renderer, parentRect);
+ // Subtract borders and padding
+ rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
+ -renderer->borderTop() - renderer->paddingTop());
+ return rect;
+ }
+
+ return Widget::convertFromContainingView(parentRect);
+ }
+
+ return parentRect;
+}
+
+IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return localPoint;
+
+ IntPoint point(localPoint);
+
+ // Add borders and padding
+ point.move(renderer->borderLeft() + renderer->paddingLeft(),
+ renderer->borderTop() + renderer->paddingTop());
+ return parentView->convertFromRenderer(renderer, point);
+ }
+
+ return Widget::convertToContainingView(localPoint);
+ }
+
+ return localPoint;
+}
+
+IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return parentPoint;
+
+ IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
+ // Subtract borders and padding
+ point.move(-renderer->borderLeft() - renderer->paddingLeft(),
+ -renderer->borderTop() - renderer->paddingTop());
+ return point;
+ }
+
+ return Widget::convertFromContainingView(parentPoint);
+ }
+
+ return parentPoint;
+}
+
} // namespace WebCore
diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h
index 16eadc5..1bdcfb3 100644
--- a/WebCore/page/FrameView.h
+++ b/WebCore/page/FrameView.h
@@ -48,7 +48,7 @@ class String;
template <typename T> class Timer;
-class FrameView : public ScrollView, public RefCounted<FrameView> {
+class FrameView : public ScrollView {
public:
friend class RenderView;
@@ -93,18 +93,21 @@ public:
bool needsFullRepaint() const { return m_doFullRepaint; }
#if USE(ACCELERATED_COMPOSITING)
- enum CompositingUpdate { NormalCompositingUpdate, ForcedCompositingUpdate };
- void updateCompositingLayers(CompositingUpdate updateType = NormalCompositingUpdate);
+ void updateCompositingLayers();
// Called when changes to the GraphicsLayer hierarchy have to be synchronized with
// content rendered via the normal painting path.
void setNeedsOneShotDrawingSynchronization();
#endif
+ // Only used with accelerated compositing, but outside the #ifdef to make linkage easier.
+ // Returns true if the sync was completed.
+ bool syncCompositingStateRecursive();
void didMoveOnscreen();
void willMoveOffscreen();
void resetScrollbars();
+ void detachCustomScrollbars();
void clear();
@@ -125,11 +128,6 @@ public:
virtual IntRect windowClipRect(bool clipToContents = true) const;
IntRect windowClipRectForLayer(const RenderLayer*, bool clipToLayerContents) const;
- virtual bool isActive() const;
- virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
- virtual void valueChanged(Scrollbar*);
- virtual void getTickmarks(Vector<IntRect>&) const;
-
virtual IntRect windowResizerRect() const;
virtual void scrollRectIntoViewRecursively(const IntRect&);
@@ -184,9 +182,13 @@ public:
void adjustPageHeight(float* newBottom, float oldTop, float oldBottom, float bottomLimit);
- bool lockedToAnchor() { return m_lockedToAnchor; }
- void setLockedToAnchor(bool lockedToAnchor) { m_lockedToAnchor = lockedToAnchor; }
+ void maintainScrollPositionAtAnchor(Node*);
+ // Methods to convert points and rects between the coordinate space of the renderer, and this view.
+ virtual IntRect convertFromRenderer(const RenderObject*, const IntRect&) const;
+ virtual IntRect convertToRenderer(const RenderObject*, const IntRect&) const;
+ virtual IntPoint convertFromRenderer(const RenderObject*, const IntPoint&) const;
+ virtual IntPoint convertToRenderer(const RenderObject*, const IntPoint&) const;
private:
FrameView(Frame*);
@@ -208,11 +210,20 @@ private:
virtual void repaintContentRectangle(const IntRect&, bool immediate);
virtual void contentsResized() { setNeedsLayout(); }
- virtual void visibleContentsResized()
- {
- if (needsLayout())
- layout();
- }
+ virtual void visibleContentsResized();
+
+ // Override ScrollView methods to do point conversion via renderers, in order to
+ // take transforms into account.
+ virtual IntRect convertToContainingView(const IntRect&) const;
+ virtual IntRect convertFromContainingView(const IntRect&) const;
+ virtual IntPoint convertToContainingView(const IntPoint&) const;
+ virtual IntPoint convertFromContainingView(const IntPoint&) const;
+
+ // ScrollBarClient interface
+ virtual void valueChanged(Scrollbar*);
+ virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+ virtual bool isActive() const;
+ virtual void getTickmarks(Vector<IntRect>&) const;
void deferredRepaintTimerFired(Timer<FrameView>*);
void doDeferredRepaints();
@@ -220,6 +231,7 @@ private:
double adjustedDeferredRepaintDelay() const;
bool updateWidgets();
+ void scrollToAnchor();
static double sCurrentPaintTimeStamp; // used for detecting decoded resource thrash in the cache
@@ -289,7 +301,7 @@ private:
bool m_isVisuallyNonEmpty;
bool m_firstVisuallyNonEmptyLayoutCallbackPending;
- bool m_lockedToAnchor;
+ RefPtr<Node> m_maintainScrollPositionAnchor;
};
} // namespace WebCore
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp
index 7010339..875da43 100644
--- a/WebCore/page/Geolocation.cpp
+++ b/WebCore/page/Geolocation.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -73,6 +74,8 @@ Geolocation::Geolocation(Frame* frame)
void Geolocation::disconnectFrame()
{
m_service->stopUpdating();
+ if (m_frame && m_frame->document())
+ m_frame->document()->setUsingGeolocation(false);
m_frame = 0;
}
@@ -143,18 +146,23 @@ void Geolocation::setIsAllowed(bool allowed)
}
}
+void Geolocation::sendError(Vector<RefPtr<GeoNotifier> >& notifiers, PositionError* error)
+{
+ Vector<RefPtr<GeoNotifier> >::const_iterator end = notifiers.end();
+ for (Vector<RefPtr<GeoNotifier> >::const_iterator it = notifiers.begin(); it != end; ++it) {
+ RefPtr<GeoNotifier> notifier = *it;
+
+ if (notifier->m_errorCallback)
+ notifier->m_errorCallback->handleEvent(error);
+ }
+}
+
void Geolocation::sendErrorToOneShots(PositionError* error)
{
Vector<RefPtr<GeoNotifier> > copy;
copyToVector(m_oneShots, copy);
- Vector<RefPtr<GeoNotifier> >::const_iterator end = copy.end();
- for (Vector<RefPtr<GeoNotifier> >::const_iterator it = copy.begin(); it != end; ++it) {
- RefPtr<GeoNotifier> notifier = *it;
-
- if (notifier->m_errorCallback)
- notifier->m_errorCallback->handleEvent(error);
- }
+ sendError(copy, error);
}
void Geolocation::sendErrorToWatchers(PositionError* error)
@@ -162,12 +170,18 @@ void Geolocation::sendErrorToWatchers(PositionError* error)
Vector<RefPtr<GeoNotifier> > copy;
copyValuesToVector(m_watchers, copy);
- Vector<RefPtr<GeoNotifier> >::const_iterator end = copy.end();
- for (Vector<RefPtr<GeoNotifier> >::const_iterator it = copy.begin(); it != end; ++it) {
+ sendError(copy, error);
+}
+
+void Geolocation::sendPosition(Vector<RefPtr<GeoNotifier> >& notifiers, Geoposition* position)
+{
+ Vector<RefPtr<GeoNotifier> >::const_iterator end = notifiers.end();
+ for (Vector<RefPtr<GeoNotifier> >::const_iterator it = notifiers.begin(); it != end; ++it) {
RefPtr<GeoNotifier> notifier = *it;
+ ASSERT(notifier->m_successCallback);
- if (notifier->m_errorCallback)
- notifier->m_errorCallback->handleEvent(error);
+ notifier->m_timer.stop();
+ notifier->m_successCallback->handleEvent(position);
}
}
@@ -176,14 +190,7 @@ void Geolocation::sendPositionToOneShots(Geoposition* position)
Vector<RefPtr<GeoNotifier> > copy;
copyToVector(m_oneShots, copy);
- Vector<RefPtr<GeoNotifier> >::const_iterator end = copy.end();
- for (Vector<RefPtr<GeoNotifier> >::const_iterator it = copy.begin(); it != end; ++it) {
- RefPtr<GeoNotifier> notifier = *it;
- ASSERT(notifier->m_successCallback);
-
- notifier->m_timer.stop();
- notifier->m_successCallback->handleEvent(position);
- }
+ sendPosition(copy, position);
}
void Geolocation::sendPositionToWatchers(Geoposition* position)
@@ -191,6 +198,7 @@ void Geolocation::sendPositionToWatchers(Geoposition* position)
Vector<RefPtr<GeoNotifier> > copy;
copyValuesToVector(m_watchers, copy);
+#ifdef MANUAL_MERGE_REQUIRED
Vector<RefPtr<GeoNotifier> >::const_iterator end = copy.end();
for (Vector<RefPtr<GeoNotifier> >::const_iterator it = copy.begin(); it != end; ++it) {
RefPtr<GeoNotifier> notifier = *it;
@@ -199,6 +207,9 @@ void Geolocation::sendPositionToWatchers(Geoposition* position)
notifier->m_timer.stop();
notifier->m_successCallback->handleEvent(position);
}
+#else // MANUAL_MERGE_REQUIRED
+ sendPosition(copy, position);
+#endif // MANUAL_MERGE_REQUIRED
}
void Geolocation::startTimer(Vector<RefPtr<GeoNotifier> >& notifiers)
@@ -240,6 +251,9 @@ void Geolocation::handleError(PositionError* error)
sendErrorToWatchers(error);
m_oneShots.clear();
+
+ if (!hasListeners())
+ m_service->stopUpdating();
}
void Geolocation::requestPermission()
@@ -254,10 +268,10 @@ void Geolocation::requestPermission()
if (!page)
return;
+ m_allowGeolocation = InProgress;
+
// Ask the chrome: it maintains the geolocation challenge policy itself.
page->chrome()->requestGeolocationPermissionForFrame(m_frame, this);
-
- m_allowGeolocation = InProgress;
}
void Geolocation::geolocationServicePositionChanged(GeolocationService*)
diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h
index 44a7fe0..a3fd5e8 100644
--- a/WebCore/page/Geolocation.h
+++ b/WebCore/page/Geolocation.h
@@ -89,8 +89,11 @@ private:
bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); }
+ void sendError(Vector<RefPtr<GeoNotifier> >&, PositionError*);
void sendErrorToOneShots(PositionError*);
void sendErrorToWatchers(PositionError*);
+
+ void sendPosition(Vector<RefPtr<GeoNotifier> >&, Geoposition*);
void sendPositionToOneShots(Geoposition*);
void sendPositionToWatchers(Geoposition*);
diff --git a/WebCore/page/History.idl b/WebCore/page/History.idl
index fa308fb..914d441 100644
--- a/WebCore/page/History.idl
+++ b/WebCore/page/History.idl
@@ -29,8 +29,8 @@ module window {
#if defined(V8_BINDING) && V8_BINDING
CheckDomainSecurity,
#endif
- CustomGetOwnPropertySlot,
- CustomPutFunction,
+ DelegatingGetOwnPropertySlot,
+ DelegatingPutFunction,
CustomDeleteProperty,
CustomGetPropertyNames
] History {
diff --git a/WebCore/page/Location.cpp b/WebCore/page/Location.cpp
index c8780eb..5adc48d 100644
--- a/WebCore/page/Location.cpp
+++ b/WebCore/page/Location.cpp
@@ -125,8 +125,8 @@ String Location::hash() const
if (!m_frame)
return String();
- const KURL& url = this->url();
- return url.ref().isEmpty() ? "" : "#" + url.ref();
+ const String& fragmentIdentifier = this->url().fragmentIdentifier();
+ return fragmentIdentifier.isEmpty() ? "" : "#" + fragmentIdentifier;
}
String Location::toString() const
diff --git a/WebCore/page/Location.idl b/WebCore/page/Location.idl
index e7fa31a..7d680f2 100644
--- a/WebCore/page/Location.idl
+++ b/WebCore/page/Location.idl
@@ -32,12 +32,12 @@ module window {
#if defined(V8_BINDING) && V8_BINDING
CheckDomainSecurity,
#endif
- CustomGetOwnPropertySlot,
- CustomPutFunction,
+ DelegatingGetOwnPropertySlot,
+ DelegatingPutFunction,
CustomDeleteProperty,
CustomGetPropertyNames,
CustomDefineGetter,
- CustomPrototypePutFunction,
+ DelegatingPrototypePutFunction,
CustomPrototypeDefineGetter
] Location {
attribute [DoNotCheckDomainSecurityOnSet, CustomSetter, V8DisallowShadowing] DOMString href;
diff --git a/WebCore/page/MouseEventWithHitTestResults.h b/WebCore/page/MouseEventWithHitTestResults.h
index c4e419c..7330d93 100644
--- a/WebCore/page/MouseEventWithHitTestResults.h
+++ b/WebCore/page/MouseEventWithHitTestResults.h
@@ -28,7 +28,6 @@ namespace WebCore {
class Scrollbar;
-// FIXME: Why doesn't this class just cache a HitTestResult instead of copying all of HitTestResult's fields over?
class MouseEventWithHitTestResults {
public:
MouseEventWithHitTestResults(const PlatformMouseEvent&, const HitTestResult&);
@@ -46,6 +45,6 @@ private:
HitTestResult m_hitTestResult;
};
-}
+} // namespace WebCore
-#endif
+#endif // MouseEventWithHitTestResults_h
diff --git a/WebCore/page/NavigatorBase.cpp b/WebCore/page/NavigatorBase.cpp
index 5138b0f..5b0c5d4 100644
--- a/WebCore/page/NavigatorBase.cpp
+++ b/WebCore/page/NavigatorBase.cpp
@@ -29,6 +29,10 @@
#include "NetworkStateNotifier.h"
#include "PlatformString.h"
+#if PLATFORM(LINUX)
+#include "sys/utsname.h"
+#include <wtf/StdLibExtras.h>
+#endif
#ifndef WEBCORE_NAVIGATOR_PLATFORM
#if PLATFORM(MAC) && (PLATFORM(PPC) || PLATFORM(PPC64))
@@ -37,6 +41,8 @@
#define WEBCORE_NAVIGATOR_PLATFORM "MacIntel"
#elif PLATFORM(WIN_OS)
#define WEBCORE_NAVIGATOR_PLATFORM "Win32"
+#elif PLATFORM(SYMBIAN)
+#define WEBCORE_NAVIGATOR_PLATFORM "Symbian"
#else
#define WEBCORE_NAVIGATOR_PLATFORM ""
#endif
@@ -79,7 +85,15 @@ String NavigatorBase::appVersion() const
String NavigatorBase::platform() const
{
+#if PLATFORM(LINUX)
+ if (String("") != WEBCORE_NAVIGATOR_PLATFORM)
+ return WEBCORE_NAVIGATOR_PLATFORM;
+ struct utsname osname;
+ DEFINE_STATIC_LOCAL(String, platformName, (uname(&osname) >= 0 ? String(osname.sysname) + String(" ") + String(osname.machine) : ""));
+ return platformName;
+#else
return WEBCORE_NAVIGATOR_PLATFORM;
+#endif
}
String NavigatorBase::appCodeName() const
diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp
index 70b4459..a13496b 100644
--- a/WebCore/page/Page.cpp
+++ b/WebCore/page/Page.cpp
@@ -34,6 +34,7 @@
#include "FocusController.h"
#include "Frame.h"
#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "HTMLElement.h"
@@ -46,6 +47,7 @@
#include "PluginData.h"
#include "ProgressTracker.h"
#include "RenderWidget.h"
+#include "RenderTheme.h"
#include "ScriptController.h"
#include "SelectionController.h"
#include "Settings.h"
@@ -57,9 +59,8 @@
#include <wtf/StdLibExtras.h>
#if ENABLE(DOM_STORAGE)
-#include "LocalStorage.h"
-#include "SessionStorage.h"
#include "StorageArea.h"
+#include "StorageNamespace.h"
#endif
#if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -100,10 +101,11 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi
, m_dragController(new DragController(this, dragClient))
, m_focusController(new FocusController(this))
, m_contextMenuController(new ContextMenuController(this, contextMenuClient))
- , m_inspectorController(InspectorController::create(this, inspectorClient))
+ , m_inspectorController(new InspectorController(this, inspectorClient))
, m_settings(new Settings(this))
, m_progress(new ProgressTracker)
, m_backForwardList(BackForwardList::create(this))
+ , m_theme(RenderTheme::themeForPage(this))
, m_editorClient(editorClient)
, m_frameCount(0)
, m_tabKeyCyclesThroughElements(true)
@@ -120,6 +122,7 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi
, m_debugger(0)
, m_customHTMLTokenizerTimeDelay(-1)
, m_customHTMLTokenizerChunkSize(-1)
+ , m_canStartPlugins(true)
{
if (!allPages) {
allPages = new HashSet<Page*>;
@@ -210,7 +213,7 @@ void Page::goToItem(HistoryItem* item, FrameLoadType type)
const KURL& currentURL = m_mainFrame->loader()->url();
const KURL& newURL = item->url();
- if (newURL.hasRef() && equalIgnoringRef(currentURL, newURL))
+ if (newURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(currentURL, newURL))
databasePolicy = DatabasePolicyContinue;
#endif
m_mainFrame->loader()->stopAllLoaders(databasePolicy);
@@ -297,6 +300,19 @@ PluginData* Page::pluginData() const
return m_pluginData.get();
}
+void Page::addUnstartedPlugin(PluginView* view)
+{
+ ASSERT(!m_canStartPlugins);
+ m_unstartedPlugins.add(view);
+}
+
+void Page::removeUnstartedPlugin(PluginView* view)
+{
+ ASSERT(!m_canStartPlugins);
+ ASSERT(m_unstartedPlugins.contains(view));
+ m_unstartedPlugins.remove(view);
+}
+
static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
{
return forward
@@ -498,7 +514,9 @@ void Page::removeAllVisitedLinks()
void Page::allVisitedStateChanged(PageGroup* group)
{
ASSERT(group);
- ASSERT(allPages);
+ if (!allPages)
+ return;
+
HashSet<Page*>::iterator pagesEnd = allPages->end();
for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
Page* page = *it;
@@ -514,7 +532,9 @@ void Page::allVisitedStateChanged(PageGroup* group)
void Page::visitedStateChanged(PageGroup* group, LinkHash visitedLinkHash)
{
ASSERT(group);
- ASSERT(allPages);
+ if (!allPages)
+ return;
+
HashSet<Page*>::iterator pagesEnd = allPages->end();
for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
Page* page = *it;
@@ -548,17 +568,16 @@ void Page::setDebugger(JSC::Debugger* debugger)
}
#if ENABLE(DOM_STORAGE)
-SessionStorage* Page::sessionStorage(bool optionalCreate)
+StorageNamespace* Page::sessionStorage(bool optionalCreate)
{
if (!m_sessionStorage && optionalCreate)
- m_sessionStorage = SessionStorage::create(this);
+ m_sessionStorage = StorageNamespace::sessionStorageNamespace();
return m_sessionStorage.get();
}
-void Page::setSessionStorage(PassRefPtr<SessionStorage> newStorage)
+void Page::setSessionStorage(PassRefPtr<StorageNamespace> newStorage)
{
- ASSERT(newStorage->page() == this);
m_sessionStorage = newStorage;
}
#endif
diff --git a/WebCore/page/Page.h b/WebCore/page/Page.h
index eedd24c..9d9af86 100644
--- a/WebCore/page/Page.h
+++ b/WebCore/page/Page.h
@@ -59,29 +59,38 @@ namespace WebCore {
class Node;
class PageGroup;
class PluginData;
+ class PluginView;
class ProgressTracker;
+ class RenderTheme;
class VisibleSelection;
class SelectionController;
+ class Settings;
#if ENABLE(DOM_STORAGE)
- class SessionStorage;
+ class StorageNamespace;
#endif
- class Settings;
#if ENABLE(WML)
class WMLPageState;
#endif
enum FindDirection { FindDirectionForward, FindDirectionBackward };
- class Page : Noncopyable {
+ class Page : public Noncopyable {
public:
static void setNeedsReapplyStyles();
Page(ChromeClient*, ContextMenuClient*, EditorClient*, DragClient*, InspectorClient*);
~Page();
-
+
+ RenderTheme* theme() const { return m_theme.get(); };
+
static void refreshPlugins(bool reload);
PluginData* pluginData() const;
+ void setCanStartPlugins(bool);
+ bool canStartPlugins() const { return m_canStartPlugins; }
+ void addUnstartedPlugin(PluginView*);
+ void removeUnstartedPlugin(PluginView*);
+
EditorClient* editorClient() const { return m_editorClient; }
void setMainFrame(PassRefPtr<Frame>);
@@ -176,8 +185,8 @@ namespace WebCore {
static void visitedStateChanged(PageGroup*, LinkHash visitedHash);
#if ENABLE(DOM_STORAGE)
- SessionStorage* sessionStorage(bool optionalCreate = true);
- void setSessionStorage(PassRefPtr<SessionStorage>);
+ StorageNamespace* sessionStorage(bool optionalCreate = true);
+ void setSessionStorage(PassRefPtr<StorageNamespace>);
#endif
#if ENABLE(WML)
@@ -206,7 +215,7 @@ namespace WebCore {
OwnPtr<DragController> m_dragController;
OwnPtr<FocusController> m_focusController;
OwnPtr<ContextMenuController> m_contextMenuController;
- RefPtr<InspectorController> m_inspectorController;
+ OwnPtr<InspectorController> m_inspectorController;
OwnPtr<Settings> m_settings;
OwnPtr<ProgressTracker> m_progress;
@@ -217,6 +226,8 @@ namespace WebCore {
mutable RefPtr<PluginData> m_pluginData;
+ RefPtr<RenderTheme> m_theme;
+
EditorClient* m_editorClient;
int m_frameCount;
@@ -247,8 +258,11 @@ namespace WebCore {
double m_customHTMLTokenizerTimeDelay;
int m_customHTMLTokenizerChunkSize;
+ bool m_canStartPlugins;
+ HashSet<PluginView*> m_unstartedPlugins;
+
#if ENABLE(DOM_STORAGE)
- RefPtr<SessionStorage> m_sessionStorage;
+ RefPtr<StorageNamespace> m_sessionStorage;
#endif
#if PLATFORM(WIN) || (PLATFORM(WX) && defined(__WXMSW__)) || (PLATFORM(QT) && defined(Q_WS_WIN))
diff --git a/WebCore/page/PageGroup.cpp b/WebCore/page/PageGroup.cpp
index f098211..c23cb86 100644
--- a/WebCore/page/PageGroup.cpp
+++ b/WebCore/page/PageGroup.cpp
@@ -32,8 +32,7 @@
#include "Settings.h"
#if ENABLE(DOM_STORAGE)
-#include "LocalStorage.h"
-#include "StorageArea.h"
+#include "StorageNamespace.h"
#endif
#if PLATFORM(CHROMIUM)
@@ -181,8 +180,9 @@ void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
}
#if ENABLE(DOM_STORAGE)
-LocalStorage* PageGroup::localStorage()
+StorageNamespace* PageGroup::localStorage()
{
+#ifdef MANUAL_MERGE_REQUIRED
if (!m_localStorage) {
// Need a page in this page group to query the settings for the local storage database path.
Page* page = *m_pages.begin();
@@ -190,6 +190,15 @@ LocalStorage* PageGroup::localStorage()
m_localStorage = LocalStorage::localStorage(page->settings()->localStorageDatabasePath());
}
+#else // MANUAL_MERGE_REQUIRED
+ if (!m_localStorage) {
+ // Need a page in this page group to query the settings for the local storage database path.
+ Page* page = *m_pages.begin();
+ ASSERT(page);
+ m_localStorage = StorageNamespace::localStorageNamespace(page->settings()->localStorageDatabasePath());
+ }
+
+#endif // MANUAL_MERGE_REQUIRED
return m_localStorage.get();
}
#endif
diff --git a/WebCore/page/PageGroup.h b/WebCore/page/PageGroup.h
index d9ffabd..8c842b9 100644
--- a/WebCore/page/PageGroup.h
+++ b/WebCore/page/PageGroup.h
@@ -34,10 +34,10 @@
namespace WebCore {
class KURL;
- class LocalStorage;
class Page;
+ class StorageNamespace;
- class PageGroup : Noncopyable {
+ class PageGroup : public Noncopyable {
public:
PageGroup(const String& name);
PageGroup(Page*);
@@ -63,7 +63,7 @@ namespace WebCore {
unsigned identifier() { return m_identifier; }
#if ENABLE(DOM_STORAGE)
- LocalStorage* localStorage();
+ StorageNamespace* localStorage();
#endif
private:
@@ -80,7 +80,7 @@ namespace WebCore {
unsigned m_identifier;
#if ENABLE(DOM_STORAGE)
- RefPtr<LocalStorage> m_localStorage;
+ RefPtr<StorageNamespace> m_localStorage;
#endif
};
diff --git a/WebCore/page/PageGroupLoadDeferrer.h b/WebCore/page/PageGroupLoadDeferrer.h
index 1bdb45c..d443ebd 100644
--- a/WebCore/page/PageGroupLoadDeferrer.h
+++ b/WebCore/page/PageGroupLoadDeferrer.h
@@ -28,7 +28,7 @@ namespace WebCore {
class Frame;
class Page;
- class PageGroupLoadDeferrer : Noncopyable {
+ class PageGroupLoadDeferrer : public Noncopyable {
public:
PageGroupLoadDeferrer(Page*, bool deferSelf);
~PageGroupLoadDeferrer();
diff --git a/WebCore/page/PrintContext.cpp b/WebCore/page/PrintContext.cpp
index 2202559..b855ca5 100644
--- a/WebCore/page/PrintContext.cpp
+++ b/WebCore/page/PrintContext.cpp
@@ -53,7 +53,7 @@ void PrintContext::computePageRects(const FloatRect& printRect, float headerHeig
if (!m_frame->document() || !m_frame->view() || !m_frame->document()->renderer())
return;
- RenderView* root = static_cast<RenderView*>(m_frame->document()->renderer());
+ RenderView* root = toRenderView(m_frame->document()->renderer());
if (!root) {
LOG_ERROR("document to be printed has no renderer");
diff --git a/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp
index 187ec31..baafd4e 100644
--- a/WebCore/page/SecurityOrigin.cpp
+++ b/WebCore/page/SecurityOrigin.cpp
@@ -33,10 +33,41 @@
#include "FrameLoader.h"
#include "KURL.h"
#include "PlatformString.h"
+#include "StringHash.h"
+#include <wtf/HashSet.h>
#include <wtf/StdLibExtras.h>
namespace WebCore {
+typedef HashSet<String, CaseFoldingHash> URLSchemesMap;
+
+static URLSchemesMap& localSchemes()
+{
+ DEFINE_STATIC_LOCAL(URLSchemesMap, localSchemes, ());
+
+ if (localSchemes.isEmpty()) {
+ localSchemes.add("file");
+#if PLATFORM(MAC)
+ localSchemes.add("applewebdata");
+#endif
+#if PLATFORM(QT)
+ localSchemes.add("qrc");
+#endif
+ }
+
+ return localSchemes;
+}
+
+static URLSchemesMap& noAccessSchemes()
+{
+ DEFINE_STATIC_LOCAL(URLSchemesMap, noAccessSchemes, ());
+
+ if (noAccessSchemes.isEmpty())
+ noAccessSchemes.add("data");
+
+ return noAccessSchemes;
+}
+
static bool isDefaultPortForProtocol(unsigned short port, const String& protocol)
{
if (protocol.isEmpty())
@@ -66,7 +97,7 @@ SecurityOrigin::SecurityOrigin(const KURL& url)
m_protocol = "";
// Some URLs are not allowed access to anything other than themselves.
- if (FrameLoader::shouldTreatURLSchemeAsNoAccess(m_protocol))
+ if (shouldTreatURLSchemeAsNoAccess(m_protocol))
m_noAccess = true;
// document.domain starts as m_host, but can be set by the DOM.
@@ -193,7 +224,7 @@ void SecurityOrigin::grantUniversalAccess()
bool SecurityOrigin::isLocal() const
{
- return FrameLoader::shouldTreatURLSchemeAsLocal(m_protocol);
+ return shouldTreatURLSchemeAsLocal(m_protocol);
}
bool SecurityOrigin::isSecureTransitionTo(const KURL& url) const
@@ -307,4 +338,62 @@ bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const
return true;
}
+// static
+void SecurityOrigin::registerURLSchemeAsLocal(const String& scheme)
+{
+ localSchemes().add(scheme);
+}
+
+// static
+bool SecurityOrigin::shouldTreatURLAsLocal(const String& url)
+{
+ // This avoids an allocation of another String and the HashSet contains()
+ // call for the file: and http: schemes.
+ if (url.length() >= 5) {
+ const UChar* s = url.characters();
+ if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p' && s[4] == ':')
+ return false;
+ if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e' && s[4] == ':')
+ return true;
+ }
+
+ int loc = url.find(':');
+ if (loc == -1)
+ return false;
+
+ String scheme = url.left(loc);
+ return localSchemes().contains(scheme);
+}
+
+// static
+bool SecurityOrigin::shouldTreatURLSchemeAsLocal(const String& scheme)
+{
+ // This avoids an allocation of another String and the HashSet contains()
+ // call for the file: and http: schemes.
+ if (scheme.length() == 4) {
+ const UChar* s = scheme.characters();
+ if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p')
+ return false;
+ if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e')
+ return true;
+ }
+
+ if (scheme.isEmpty())
+ return false;
+
+ return localSchemes().contains(scheme);
+}
+
+// static
+void SecurityOrigin::registerURLSchemeAsNoAccess(const String& scheme)
+{
+ noAccessSchemes().add(scheme);
+}
+
+// static
+bool SecurityOrigin::shouldTreatURLSchemeAsNoAccess(const String& scheme)
+{
+ return noAccessSchemes().contains(scheme);
+}
+
} // namespace WebCore
diff --git a/WebCore/page/SecurityOrigin.h b/WebCore/page/SecurityOrigin.h
index 96f85df..ab92683 100644
--- a/WebCore/page/SecurityOrigin.h
+++ b/WebCore/page/SecurityOrigin.h
@@ -128,6 +128,13 @@ namespace WebCore {
// (and whether it was set) but considering the host. It is used for postMessage.
bool isSameSchemeHostPort(const SecurityOrigin*) const;
+ static void registerURLSchemeAsLocal(const String&);
+ static bool shouldTreatURLAsLocal(const String&);
+ static bool shouldTreatURLSchemeAsLocal(const String&);
+
+ static void registerURLSchemeAsNoAccess(const String&);
+ static bool shouldTreatURLSchemeAsNoAccess(const String&);
+
private:
explicit SecurityOrigin(const KURL&);
explicit SecurityOrigin(const SecurityOrigin*);
diff --git a/WebCore/page/Settings.cpp b/WebCore/page/Settings.cpp
index b67cf44..b36d458 100644
--- a/WebCore/page/Settings.cpp
+++ b/WebCore/page/Settings.cpp
@@ -28,6 +28,7 @@
#include "Frame.h"
#include "FrameTree.h"
+#include "FrameView.h"
#include "HistoryItem.h"
#include "Page.h"
#include "PageCache.h"
@@ -44,7 +45,7 @@ static void setNeedsReapplyStylesInAllFrames(Page* page)
}
#if USE(SAFARI_THEME)
-bool Settings::gShouldPaintNativeControls = false;
+bool Settings::gShouldPaintNativeControls = true;
#endif
Settings::Settings(Page* page)
@@ -75,6 +76,7 @@ Settings::Settings(Page* page)
, m_arePluginsEnabled(false)
, m_databasesEnabled(false)
, m_localStorageEnabled(false)
+ , m_sessionStorageEnabled(true)
, m_isJavaScriptEnabled(false)
, m_isWebSecurityEnabled(true)
, m_allowUniversalAccessFromFileURLs(true)
@@ -86,6 +88,7 @@ Settings::Settings(Page* page)
#endif
, m_needsAdobeFrameReloadingQuirk(false)
, m_needsKeyboardEventDisambiguationQuirks(false)
+ , m_treatsAnyTextCSSLinkAsStylesheet(false)
, m_needsLeopardMailQuirks(false)
, m_needsTigerMailQuirks(false)
, m_isDOMPasteAllowed(false)
@@ -98,6 +101,7 @@ Settings::Settings(Page* page)
, m_needsSiteSpecificQuirks(false)
, m_fontRenderingMode(0)
, m_webArchiveDebugModeEnabled(false)
+ , m_localFileContentSniffingEnabled(false)
, m_inApplicationChromeMode(false)
, m_offlineWebApplicationCacheEnabled(false)
, m_shouldPaintCustomScrollbars(false)
@@ -115,6 +119,8 @@ Settings::Settings(Page* page)
// FIXME: This should really be disabled by default as it makes platforms that don't support the feature download files
// they can't use by. Leaving enabled for now to not change existing behavior.
, m_downloadableBinaryFontsEnabled(true)
+ , m_xssAuditorEnabled(false)
+ , m_acceleratedCompositingEnabled(true)
{
// A Frame may not have been created yet, so we initialize the AtomicString
// hash before trying to use it.
@@ -261,6 +267,11 @@ void Settings::setLocalStorageEnabled(bool localStorageEnabled)
m_localStorageEnabled = localStorageEnabled;
}
+void Settings::setSessionStorageEnabled(bool sessionStorageEnabled)
+{
+ m_sessionStorageEnabled = sessionStorageEnabled;
+}
+
void Settings::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
{
m_privateBrowsingEnabled = privateBrowsingEnabled;
@@ -333,6 +344,11 @@ void Settings::setNeedsKeyboardEventDisambiguationQuirks(bool needsQuirks)
m_needsKeyboardEventDisambiguationQuirks = needsQuirks;
}
+void Settings::setTreatsAnyTextCSSLinkAsStylesheet(bool treatsAnyTextCSSLinkAsStylesheet)
+{
+ m_treatsAnyTextCSSLinkAsStylesheet = treatsAnyTextCSSLinkAsStylesheet;
+}
+
void Settings::setNeedsLeopardMailQuirks(bool needsQuirks)
{
m_needsLeopardMailQuirks = needsQuirks;
@@ -508,6 +524,11 @@ void Settings::setWebArchiveDebugModeEnabled(bool enabled)
m_webArchiveDebugModeEnabled = enabled;
}
+void Settings::setLocalFileContentSniffingEnabled(bool enabled)
+{
+ m_localFileContentSniffingEnabled = enabled;
+}
+
void Settings::setLocalStorageDatabasePath(const String& path)
{
m_localStorageDatabasePath = path;
@@ -569,4 +590,18 @@ void Settings::setDownloadableBinaryFontsEnabled(bool downloadableBinaryFontsEna
m_downloadableBinaryFontsEnabled = downloadableBinaryFontsEnabled;
}
+void Settings::setXSSAuditorEnabled(bool xssAuditorEnabled)
+{
+ m_xssAuditorEnabled = xssAuditorEnabled;
+}
+
+void Settings::setAcceleratedCompositingEnabled(bool enabled)
+{
+ if (m_acceleratedCompositingEnabled == enabled)
+ return;
+
+ m_acceleratedCompositingEnabled = enabled;
+ setNeedsReapplyStylesInAllFrames(m_page);
+}
+
} // namespace WebCore
diff --git a/WebCore/page/Settings.h b/WebCore/page/Settings.h
index f2f4279..574fed7 100644
--- a/WebCore/page/Settings.h
+++ b/WebCore/page/Settings.h
@@ -148,6 +148,9 @@ namespace WebCore {
void setLocalStorageEnabled(bool);
bool localStorageEnabled() const { return m_localStorageEnabled; }
+ void setSessionStorageEnabled(bool);
+ bool sessionStorageEnabled() const { return m_sessionStorageEnabled; }
+
void setPrivateBrowsingEnabled(bool);
bool privateBrowsingEnabled() const { return m_privateBrowsingEnabled; }
@@ -186,6 +189,9 @@ namespace WebCore {
void setNeedsKeyboardEventDisambiguationQuirks(bool);
bool needsKeyboardEventDisambiguationQuirks() const { return m_needsKeyboardEventDisambiguationQuirks; }
+ void setTreatsAnyTextCSSLinkAsStylesheet(bool);
+ bool treatsAnyTextCSSLinkAsStylesheet() const { return m_treatsAnyTextCSSLinkAsStylesheet; }
+
void setNeedsLeopardMailQuirks(bool);
bool needsLeopardMailQuirks() const { return m_needsLeopardMailQuirks; }
@@ -243,6 +249,9 @@ namespace WebCore {
void setWebArchiveDebugModeEnabled(bool);
bool webArchiveDebugModeEnabled() const { return m_webArchiveDebugModeEnabled; }
+ void setLocalFileContentSniffingEnabled(bool);
+ bool localFileContentSniffingEnabled() const { return m_localFileContentSniffingEnabled; }
+
void setLocalStorageDatabasePath(const String&);
const String& localStorageDatabasePath() const { return m_localStorageDatabasePath; }
@@ -279,6 +288,12 @@ namespace WebCore {
void setDownloadableBinaryFontsEnabled(bool);
bool downloadableBinaryFontsEnabled() const { return m_downloadableBinaryFontsEnabled; }
+ void setXSSAuditorEnabled(bool);
+ bool xssAuditorEnabled() const { return m_xssAuditorEnabled; }
+
+ void setAcceleratedCompositingEnabled(bool);
+ bool acceleratedCompositingEnabled() const { return m_acceleratedCompositingEnabled; }
+
private:
Page* m_page;
@@ -340,6 +355,7 @@ namespace WebCore {
bool m_arePluginsEnabled : 1;
bool m_databasesEnabled : 1;
bool m_localStorageEnabled : 1;
+ bool m_sessionStorageEnabled : 1;
bool m_isJavaScriptEnabled : 1;
bool m_isWebSecurityEnabled : 1;
bool m_allowUniversalAccessFromFileURLs: 1;
@@ -351,6 +367,7 @@ namespace WebCore {
#endif
bool m_needsAdobeFrameReloadingQuirk : 1;
bool m_needsKeyboardEventDisambiguationQuirks : 1;
+ bool m_treatsAnyTextCSSLinkAsStylesheet : 1;
bool m_needsLeopardMailQuirks : 1;
bool m_needsTigerMailQuirks : 1;
bool m_isDOMPasteAllowed : 1;
@@ -363,6 +380,7 @@ namespace WebCore {
bool m_needsSiteSpecificQuirks : 1;
unsigned m_fontRenderingMode : 1;
bool m_webArchiveDebugModeEnabled : 1;
+ bool m_localFileContentSniffingEnabled : 1;
bool m_inApplicationChromeMode : 1;
bool m_offlineWebApplicationCacheEnabled : 1;
bool m_shouldPaintCustomScrollbars : 1;
@@ -372,6 +390,8 @@ namespace WebCore {
bool m_allowScriptsToCloseWindows : 1;
unsigned m_editingBehavior : 1;
bool m_downloadableBinaryFontsEnabled : 1;
+ bool m_xssAuditorEnabled : 1;
+ bool m_acceleratedCompositingEnabled : 1;
#if USE(SAFARI_THEME)
static bool gShouldPaintNativeControls;
diff --git a/WebCore/page/XSSAuditor.cpp b/WebCore/page/XSSAuditor.cpp
new file mode 100644
index 0000000..70b691b
--- /dev/null
+++ b/WebCore/page/XSSAuditor.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2008, 2009 Daniel Bates (dbates@intudata.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "XSSAuditor.h"
+
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+#include "Console.h"
+#include "CString.h"
+#include "DocumentLoader.h"
+#include "DOMWindow.h"
+#include "Frame.h"
+#include "KURL.h"
+#include "PreloadScanner.h"
+#include "ResourceResponseBase.h"
+#include "ScriptSourceCode.h"
+#include "Settings.h"
+#include "TextResourceDecoder.h"
+
+using namespace WTF;
+
+namespace WebCore {
+
+static bool isNonCanonicalCharacter(UChar c)
+{
+ // Note, we don't remove backslashes like PHP stripslashes(), which among other things converts "\\0" to the \0 character.
+ // Instead, we remove backslashes and zeros (since the string "\\0" =(remove backslashes)=> "0"). However, this has the
+ // adverse effect that we remove any legitimate zeros from a string.
+ //
+ // For instance: new String("http://localhost:8000") => new String("http://localhost:8").
+ return (c == '\\' || c == '0' || c < ' ' || c == 127);
+}
+
+XSSAuditor::XSSAuditor(Frame* frame)
+ : m_frame(frame)
+{
+}
+
+XSSAuditor::~XSSAuditor()
+{
+}
+
+bool XSSAuditor::isEnabled() const
+{
+ Settings* settings = m_frame->settings();
+ return (settings && settings->xssAuditorEnabled());
+}
+
+bool XSSAuditor::canEvaluate(const String& code) const
+{
+ if (!isEnabled())
+ return true;
+
+ if (findInRequest(code, false)) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
+ return false;
+ }
+ return true;
+}
+
+bool XSSAuditor::canEvaluateJavaScriptURL(const String& code) const
+{
+ if (!isEnabled())
+ return true;
+
+ if (findInRequest(code)) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
+ return false;
+ }
+ return true;
+}
+
+bool XSSAuditor::canCreateInlineEventListener(const String&, const String& code) const
+{
+ if (!isEnabled())
+ return true;
+
+ if (findInRequest(code)) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
+ return false;
+ }
+ return true;
+}
+
+bool XSSAuditor::canLoadExternalScriptFromSrc(const String& context, const String& url) const
+{
+ if (!isEnabled())
+ return true;
+
+ if (findInRequest(context + url)) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
+ return false;
+ }
+ return true;
+}
+
+bool XSSAuditor::canLoadObject(const String& url) const
+{
+ if (!isEnabled())
+ return true;
+
+ if (findInRequest(url)) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request"));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
+ return false;
+ }
+ return true;
+}
+
+bool XSSAuditor::canSetBaseElementURL(const String& url) const
+{
+ if (!isEnabled())
+ return true;
+
+ KURL baseElementURL(m_frame->document()->url(), url);
+ if (m_frame->document()->url().host() != baseElementURL.host() && findInRequest(url)) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request"));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
+ return false;
+ }
+ return true;
+}
+
+String XSSAuditor::canonicalize(const String& string)
+{
+ String result = decodeHTMLEntities(string);
+ return result.removeCharacters(&isNonCanonicalCharacter);
+}
+
+String XSSAuditor::decodeURL(const String& string, const TextEncoding& encoding, bool decodeHTMLentities)
+{
+ String result;
+ String url = string;
+
+ url.replace('+', ' ');
+ result = decodeURLEscapeSequences(url);
+ String decodedResult = encoding.decode(result.utf8().data(), result.length());
+ if (!decodedResult.isEmpty())
+ result = decodedResult;
+ if (decodeHTMLentities)
+ result = decodeHTMLEntities(result);
+ return result;
+}
+
+String XSSAuditor::decodeHTMLEntities(const String& string, bool leaveUndecodableHTMLEntitiesUntouched)
+{
+ SegmentedString source(string);
+ SegmentedString sourceShadow;
+ Vector<UChar> result;
+
+ while (!source.isEmpty()) {
+ UChar cc = *source;
+ source.advance();
+
+ if (cc != '&') {
+ result.append(cc);
+ continue;
+ }
+
+ if (leaveUndecodableHTMLEntitiesUntouched)
+ sourceShadow = source;
+ bool notEnoughCharacters = false;
+ unsigned entity = PreloadScanner::consumeEntity(source, notEnoughCharacters);
+ // We ignore notEnoughCharacters because we might as well use this loop
+ // to copy the remaining characters into |result|.
+
+ if (entity > 0xFFFF) {
+ result.append(U16_LEAD(entity));
+ result.append(U16_TRAIL(entity));
+ } else if (entity && (!leaveUndecodableHTMLEntitiesUntouched || entity != 0xFFFD)){
+ result.append(entity);
+ } else {
+ result.append('&');
+ if (leaveUndecodableHTMLEntitiesUntouched)
+ source = sourceShadow;
+ }
+ }
+
+ return String::adopt(result);
+}
+
+bool XSSAuditor::findInRequest(const String& string, bool decodeHTMLentities) const
+{
+ bool result = false;
+ Frame* parentFrame = m_frame->tree()->parent();
+ if (parentFrame && m_frame->document()->url() == blankURL())
+ result = findInRequest(parentFrame, string, decodeHTMLentities);
+ if (!result)
+ result = findInRequest(m_frame, string, decodeHTMLentities);
+ return result;
+}
+
+bool XSSAuditor::findInRequest(Frame* frame, const String& string, bool decodeHTMLentities) const
+{
+ ASSERT(frame->document());
+ String pageURL = frame->document()->url().string();
+
+ if (!frame->document()->decoder()) {
+ // Note, JavaScript URLs do not have a charset.
+ return false;
+ }
+
+ if (protocolIs(pageURL, "data"))
+ return false;
+
+ if (string.isEmpty())
+ return false;
+
+ String canonicalizedString = canonicalize(string);
+ if (canonicalizedString.isEmpty())
+ return false;
+
+ if (string.length() < pageURL.length()) {
+ // The string can actually fit inside the pageURL.
+ String decodedPageURL = canonicalize(decodeURL(pageURL, frame->document()->decoder()->encoding(), decodeHTMLentities));
+ if (decodedPageURL.find(canonicalizedString, 0, false) != -1)
+ return true; // We've found the smoking gun.
+ }
+
+ FormData* formDataObj = frame->loader()->documentLoader()->originalRequest().httpBody();
+ if (formDataObj && !formDataObj->isEmpty()) {
+ String formData = formDataObj->flattenToString();
+ if (string.length() < formData.length()) {
+ // Notice it is sufficient to compare the length of the string to
+ // the url-encoded POST data because the length of the url-decoded
+ // code is less than or equal to the length of the url-encoded
+ // string.
+ String decodedFormData = canonicalize(decodeURL(formData, frame->document()->decoder()->encoding(), decodeHTMLentities));
+ if (decodedFormData.find(canonicalizedString, 0, false) != -1)
+ return true; // We found the string in the POST data.
+ }
+ }
+
+ return false;
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/page/XSSAuditor.h b/WebCore/page/XSSAuditor.h
new file mode 100644
index 0000000..26f10ab
--- /dev/null
+++ b/WebCore/page/XSSAuditor.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008, 2009 Daniel Bates (dbates@intudata.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef XSSAuditor_h
+#define XSSAuditor_h
+
+#include "PlatformString.h"
+#include "TextEncoding.h"
+
+namespace WebCore {
+
+ class Frame;
+ class ScriptSourceCode;
+
+ // The XSSAuditor class is used to prevent type 1 cross-site scripting
+ // vulnerabilites (also known as reflected vulnerabilities).
+ //
+ // More specifically, the XSSAuditor class decides whether the execution of
+ // a script is to be allowed or denied based on the content of any
+ // user-submitted data, including:
+ //
+ // * the query string of the URL.
+ // * the HTTP-POST data.
+ //
+ // If the source code of a script resembles any user-submitted data then it
+ // is denied execution.
+ //
+ // When you instantiate the XSSAuditor you must specify the {@link Frame}
+ // of the page that you wish to audit.
+ //
+ // Bindings
+ //
+ // An XSSAuditor is instantiated within the contructor of a
+ // ScriptController object and passed the Frame the script originated. The
+ // ScriptController calls back to the XSSAuditor to determine whether a
+ // JavaScript script is safe to execute before executing it. The following
+ // methods call into XSSAuditor:
+ //
+ // * ScriptController::evaluate - used to evaluate JavaScript scripts.
+ // * ScriptController::createInlineEventListener - used to create JavaScript event handlers.
+ // * HTMLTokenizer::scriptHandler - used to load external JavaScript scripts.
+ //
+ class XSSAuditor {
+ public:
+ XSSAuditor(Frame*);
+ ~XSSAuditor();
+
+ bool isEnabled() const;
+
+ // Determines whether the script should be allowed or denied execution
+ // based on the content of any user-submitted data.
+ bool canEvaluate(const String& code) const;
+
+ // Determines whether the JavaScript URL should be allowed or denied execution
+ // based on the content of any user-submitted data.
+ bool canEvaluateJavaScriptURL(const String& code) const;
+
+ // Determines whether the event listener should be created based on the
+ // content of any user-submitted data.
+ bool canCreateInlineEventListener(const String& functionName, const String& code) const;
+
+ // Determines whether the external script should be loaded based on the
+ // content of any user-submitted data.
+ bool canLoadExternalScriptFromSrc(const String& context, const String& url) const;
+
+ // Determines whether object should be loaded based on the content of
+ // any user-submitted data.
+ //
+ // This method is called by FrameLoader::requestObject.
+ bool canLoadObject(const String& url) const;
+
+ // Determines whether the base URL should be changed based on the content
+ // of any user-submitted data.
+ //
+ // This method is called by HTMLBaseElement::process.
+ bool canSetBaseElementURL(const String& url) const;
+
+ private:
+ static String canonicalize(const String&);
+
+ static String decodeURL(const String& url, const TextEncoding& encoding = UTF8Encoding(), bool decodeHTMLentities = true);
+
+ static String decodeHTMLEntities(const String&, bool leaveUndecodableHTMLEntitiesUntouched = true);
+
+ bool findInRequest(const String&, bool decodeHTMLentities = true) const;
+
+ bool findInRequest(Frame*, const String&, bool decodeHTMLentities = true) const;
+
+ // The frame to audit.
+ Frame* m_frame;
+ };
+
+} // namespace WebCore
+
+#endif // XSSAuditor_h
diff --git a/WebCore/page/android/DragControllerAndroid.cpp b/WebCore/page/android/DragControllerAndroid.cpp
index 7a52b56..99e18a6 100644
--- a/WebCore/page/android/DragControllerAndroid.cpp
+++ b/WebCore/page/android/DragControllerAndroid.cpp
@@ -43,7 +43,7 @@ DragOperation DragController::dragOperation(DragData* dragData)
if (dragData->containsURL())
return DragOperationCopy;
- return DragOperationNone;
+ return DragOperationNone;
}
void DragController::cleanupAfterSystemDrag()
diff --git a/WebCore/page/android/EventHandlerAndroid.cpp b/WebCore/page/android/EventHandlerAndroid.cpp
index df73fe0..b52ca22 100644
--- a/WebCore/page/android/EventHandlerAndroid.cpp
+++ b/WebCore/page/android/EventHandlerAndroid.cpp
@@ -39,7 +39,13 @@
namespace WebCore {
+#ifdef MANUAL_MERGE_REQUIRED
bool EventHandler::tabsToAllControls(KeyboardEvent* ) const
+#else // MANUAL_MERGE_REQUIRED
+unsigned EventHandler::s_accessKeyModifiers = PlatformKeyboardEvent::AltKey;
+
+bool EventHandler::tabsToAllControls(KeyboardEvent*) const
+#endif // MANUAL_MERGE_REQUIRED
{
return true;
}
@@ -56,8 +62,7 @@ bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR
RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : 0;
if (!target || !target->isWidget())
return false;
-
- return passMouseDownEventToWidget(static_cast<RenderWidget*>(target)->widget());
+ return passMouseDownEventToWidget(toRenderWidget(target)->widget());
}
bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
diff --git a/WebCore/page/animation/AnimationBase.cpp b/WebCore/page/animation/AnimationBase.cpp
index 7b8a189..7503f0a 100644
--- a/WebCore/page/animation/AnimationBase.cpp
+++ b/WebCore/page/animation/AnimationBase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -45,6 +45,8 @@
#include "MatrixTransformOperation.h"
#include "Matrix3DTransformOperation.h"
#include "RenderBox.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
#include "RenderStyle.h"
#include "UnitBezier.h"
@@ -113,11 +115,23 @@ static inline IntSize blendFunc(const AnimationBase* anim, const IntSize& from,
blendFunc(anim, from.height(), to.height(), progress));
}
+static inline ShadowStyle blendFunc(const AnimationBase* anim, ShadowStyle from, ShadowStyle to, double progress)
+{
+ if (from == to)
+ return to;
+
+ double fromVal = from == Normal ? 1 : 0;
+ double toVal = to == Normal ? 1 : 0;
+ double result = blendFunc(anim, fromVal, toVal, progress);
+ return result > 0 ? Normal : Inset;
+}
+
static inline ShadowData* blendFunc(const AnimationBase* anim, const ShadowData* from, const ShadowData* to, double progress)
{
ASSERT(from && to);
return new ShadowData(blendFunc(anim, from->x, to->x, progress), blendFunc(anim, from->y, to->y, progress),
- blendFunc(anim, from->blur, to->blur, progress), blendFunc(anim, from->color, to->color, progress));
+ blendFunc(anim, from->blur, to->blur, progress), blendFunc(anim, from->spread, to->spread, progress),
+ blendFunc(anim, from->style, to->style, progress), blendFunc(anim, from->color, to->color, progress));
}
static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress)
@@ -300,7 +314,7 @@ public:
{
ShadowData* shadowA = (a->*m_getter)();
ShadowData* shadowB = (b->*m_getter)();
- ShadowData defaultShadowData(0, 0, 0, Color::transparent);
+ ShadowData defaultShadowData(0, 0, 0, 0, Normal, Color::transparent);
if (!shadowA)
shadowA = &defaultShadowData;
@@ -404,8 +418,15 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom));
+
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth));
+
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight));
+
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth));
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth));
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth));
@@ -442,16 +463,18 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent));
+
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY));
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility));
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom));
@@ -473,7 +496,7 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyOutlineColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor));
// These are for shadows
- gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
+ gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow));
#if ENABLE(SVG)
@@ -484,8 +507,6 @@ static void ensurePropertyMap()
// TODO:
//
- // CSSPropertyMinWidth, CSSPropertyMaxWidth, CSSPropertyMinHeight, CSSPropertyMaxHeight
- // CSSPropertyTextIndent
// CSSPropertyVerticalAlign
//
// Compound properties that have components that should be animatable:
@@ -1041,7 +1062,7 @@ void AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const
double nextIterationTime = m_totalDuration;
if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) {
- durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration());
+ durationLeft = m_animation->duration() > 0 ? (m_animation->duration() - fmod(elapsedDuration, m_animation->duration())) : 0;
nextIterationTime = elapsedDuration + durationLeft;
}
@@ -1065,10 +1086,18 @@ void AnimationBase::goIntoEndingOrLoopingState()
m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding;
}
-void AnimationBase::pauseAtTime(double t)
+void AnimationBase::freezeAtTime(double t)
{
- updatePlayState(false);
+ ASSERT(m_startTime); // if m_startTime is zero, we haven't started yet, so we'll get a bad pause time.
m_pauseTime = m_startTime + t - m_animation->delay();
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object && m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ layer->backing()->suspendAnimations(m_pauseTime);
+ }
+#endif
}
double AnimationBase::beginAnimationUpdateTime() const
diff --git a/WebCore/page/animation/AnimationBase.h b/WebCore/page/animation/AnimationBase.h
index 8f55a8e..3482f65 100644
--- a/WebCore/page/animation/AnimationBase.h
+++ b/WebCore/page/animation/AnimationBase.h
@@ -156,7 +156,8 @@ public:
bool isTransformFunctionListValid() const { return m_transformFunctionListValid; }
- void pauseAtTime(double t);
+ // Freeze the animation; used by DumpRenderTree.
+ void freezeAtTime(double t);
double beginAnimationUpdateTime() const;
diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp
index 58a1f5b..ed241e1 100644
--- a/WebCore/page/animation/AnimationController.cpp
+++ b/WebCore/page/animation/AnimationController.cpp
@@ -136,9 +136,9 @@ void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<Animat
Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end();
for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
if (it->eventType == eventNames().webkitTransitionEndEvent)
- it->element->dispatchWebKitTransitionEvent(it->eventType,it->name, it->elapsedTime);
+ it->element->dispatchWebKitTransitionEvent(it->eventType, it->name, it->elapsedTime);
else
- it->element->dispatchWebKitAnimationEvent(it->eventType,it->name, it->elapsedTime);
+ it->element->dispatchWebKitAnimationEvent(it->eventType, it->name, it->elapsedTime);
}
m_eventsToDispatch.clear();
@@ -152,20 +152,6 @@ void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<Animat
if (m_frame)
m_frame->document()->updateStyleIfNeeded();
-
- // We can now safely remove any animations or transitions that are finished.
- // We can't remove them any earlier because we might get a false restart of
- // a transition. This can happen because we have not yet set the final property
- // value until we call the rendering dispatcher. So this can make the current
- // style slightly different from the desired final style (because our last
- // animation step was, say 0.9999 or something). And we need to remove them
- // here because if there are no more animations running we'll never get back
- // into the animation code to clean them up.
- RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
- for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
- CompositeAnimation* compAnim = it->second.get();
- compAnim->cleanupFinishedAnimations(); // will not modify m_compositeAnimations, so OK to call while iterating
- }
}
void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher()
diff --git a/WebCore/page/animation/CompositeAnimation.cpp b/WebCore/page/animation/CompositeAnimation.cpp
index d60455a..8946d80 100644
--- a/WebCore/page/animation/CompositeAnimation.cpp
+++ b/WebCore/page/animation/CompositeAnimation.cpp
@@ -67,91 +67,117 @@ void CompositeAnimation::clearRenderer()
void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
{
- RefPtr<RenderStyle> modifiedCurrentStyle;
-
- // If currentStyle is null, we don't do transitions
- if (!currentStyle || !targetStyle->transitions())
+ // If currentStyle is null or there are no old or new transitions, just skip it
+ if (!currentStyle || (!targetStyle->transitions() && m_transitions.isEmpty()))
return;
+ // Mark all existing transitions as no longer active. We will mark the still active ones
+ // in the next loop and then toss the ones that didn't get marked.
+ CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
+ for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it)
+ it->second->setActive(false);
+
+ RefPtr<RenderStyle> modifiedCurrentStyle;
+
// Check to see if we need to update the active transitions
- for (size_t i = 0; i < targetStyle->transitions()->size(); ++i) {
- const Animation* anim = targetStyle->transitions()->animation(i);
- bool isActiveTransition = anim->duration() || anim->delay() > 0;
+ if (targetStyle->transitions()) {
+ for (size_t i = 0; i < targetStyle->transitions()->size(); ++i) {
+ const Animation* anim = targetStyle->transitions()->animation(i);
+ bool isActiveTransition = anim->duration() || anim->delay() > 0;
- int prop = anim->property();
+ int prop = anim->property();
- if (prop == cAnimateNone)
- continue;
-
- bool all = prop == cAnimateAll;
+ if (prop == cAnimateNone)
+ continue;
- // Handle both the 'all' and single property cases. For the single prop case, we make only one pass
- // through the loop.
- for (int propertyIndex = 0; propertyIndex < AnimationBase::getNumProperties(); ++propertyIndex) {
- if (all) {
- // Get the next property which is not a shorthand.
- bool isShorthand;
- prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand);
- if (isShorthand)
- continue;
- }
+ bool all = prop == cAnimateAll;
+
+ // Handle both the 'all' and single property cases. For the single prop case, we make only one pass
+ // through the loop.
+ for (int propertyIndex = 0; propertyIndex < AnimationBase::getNumProperties(); ++propertyIndex) {
+ if (all) {
+ // Get the next property which is not a shorthand.
+ bool isShorthand;
+ prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand);
+ if (isShorthand)
+ continue;
+ }
- // ImplicitAnimations are always hashed by actual properties, never cAnimateAll
- ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties));
-
- // If there is a running animation for this property, the transition is overridden
- // and we have to use the unanimatedStyle from the animation. We do the test
- // against the unanimated style here, but we "override" the transition later.
- RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop);
- RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle;
-
- // See if there is a current transition for this prop
- ImplicitAnimation* implAnim = m_transitions.get(prop).get();
- bool equal = true;
-
- if (implAnim) {
- // This might be a transition that is just finishing. That would be the case
- // if it were postActive. But we still need to check for equality because
- // it could be just finishing AND changing to a new goal state.
- //
- // This implAnim might also not be an already running transition. It might be
- // newly added to the list in a previous iteration. This would happen if
- // you have both an explicit transition-property and 'all' in the same
- // list. In this case, the latter one overrides the earlier one, so we
- // behave as though this is a running animation being replaced.
- if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) {
-#if USE(ACCELERATED_COMPOSITING)
- // For accelerated animations we need to return a new RenderStyle with the _current_ value
- // of the property, so that restarted transitions use the correct starting point.
- if (AnimationBase::animationOfPropertyIsAccelerated(prop) && !implAnim->isFallbackAnimating()) {
- if (!modifiedCurrentStyle)
- modifiedCurrentStyle = RenderStyle::clone(currentStyle);
-
- implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get());
+ // ImplicitAnimations are always hashed by actual properties, never cAnimateAll
+ ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties));
+
+ // If there is a running animation for this property, the transition is overridden
+ // and we have to use the unanimatedStyle from the animation. We do the test
+ // against the unanimated style here, but we "override" the transition later.
+ RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop);
+ RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle;
+
+ // See if there is a current transition for this prop
+ ImplicitAnimation* implAnim = m_transitions.get(prop).get();
+ bool equal = true;
+
+ if (implAnim) {
+ // If we are post active don't bother setting the active flag. This will cause
+ // this animation to get removed at the end of this function.
+ if (!implAnim->postActive())
+ implAnim->setActive(true);
+
+ // This might be a transition that is just finishing. That would be the case
+ // if it were postActive. But we still need to check for equality because
+ // it could be just finishing AND changing to a new goal state.
+ //
+ // This implAnim might also not be an already running transition. It might be
+ // newly added to the list in a previous iteration. This would happen if
+ // you have both an explicit transition-property and 'all' in the same
+ // list. In this case, the latter one overrides the earlier one, so we
+ // behave as though this is a running animation being replaced.
+ if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) {
+ #if USE(ACCELERATED_COMPOSITING)
+ // For accelerated animations we need to return a new RenderStyle with the _current_ value
+ // of the property, so that restarted transitions use the correct starting point.
+ if (AnimationBase::animationOfPropertyIsAccelerated(prop) && !implAnim->isFallbackAnimating()) {
+ if (!modifiedCurrentStyle)
+ modifiedCurrentStyle = RenderStyle::clone(currentStyle);
+
+ implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get());
+ }
+ #endif
+ m_transitions.remove(prop);
+ equal = false;
}
-#endif
- m_transitions.remove(prop);
- equal = false;
+ } else {
+ // We need to start a transition if it is active and the properties don't match
+ equal = !isActiveTransition || AnimationBase::propertiesEqual(prop, fromStyle, targetStyle);
}
- } else {
- // We need to start a transition if it is active and the properties don't match
- equal = !isActiveTransition || AnimationBase::propertiesEqual(prop, fromStyle, targetStyle);
- }
- // We can be in this loop with an inactive transition (!isActiveTransition). We need
- // to do that to check to see if we are canceling a transition. But we don't want to
- // start one of the inactive transitions. So short circuit that here. (See
- // <https://bugs.webkit.org/show_bug.cgi?id=24787>
- if (!equal && isActiveTransition) {
- // Add the new transition
- m_transitions.set(prop, ImplicitAnimation::create(const_cast<Animation*>(anim), prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle));
+ // We can be in this loop with an inactive transition (!isActiveTransition). We need
+ // to do that to check to see if we are canceling a transition. But we don't want to
+ // start one of the inactive transitions. So short circuit that here. (See
+ // <https://bugs.webkit.org/show_bug.cgi?id=24787>
+ if (!equal && isActiveTransition) {
+ // Add the new transition
+ m_transitions.set(prop, ImplicitAnimation::create(const_cast<Animation*>(anim), prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle));
+ }
+
+ // We only need one pass for the single prop case
+ if (!all)
+ break;
}
-
- // We only need one pass for the single prop case
- if (!all)
- break;
}
}
+
+ // Make a list of transitions to be removed
+ Vector<int> toBeRemoved;
+ end = m_transitions.end();
+ for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
+ ImplicitAnimation* anim = it->second.get();
+ if (!anim->active())
+ toBeRemoved.append(anim->animatingProperty());
+ }
+
+ // Now remove the transitions from the list
+ for (size_t j = 0; j < toBeRemoved.size(); ++j)
+ m_transitions.remove(toBeRemoved[j]);
}
void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
@@ -160,52 +186,62 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render
if (m_keyframeAnimations.isEmpty() && !targetStyle->hasAnimations())
return;
- // Nothing to do if the current and target animations are the same
- if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations()))
- return;
-
- // Mark all existing animations as no longer active
AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end();
- for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
- it->second->setIndex(-1);
-
- // Toss the animation order map
- m_keyframeAnimationOrderMap.clear();
- // Now mark any still active animations as active and add any new animations
- if (targetStyle->animations()) {
- int numAnims = targetStyle->animations()->size();
- for (int i = 0; i < numAnims; ++i) {
- const Animation* anim = targetStyle->animations()->animation(i);
- AtomicString animationName(anim->name());
-
- if (!anim->isValidAnimation())
- continue;
+ if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations())) {
+ // The current and target animations are the same so we just need to toss any
+ // animation which is finished (postActive).
+ for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) {
+ if (it->second->postActive())
+ it->second->setIndex(-1);
+ }
+ } else {
+ // Mark all existing animations as no longer active.
+ for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
+ it->second->setIndex(-1);
- // See if there is a current animation for this name
- RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl());
+ // Toss the animation order map.
+ m_keyframeAnimationOrderMap.clear();
+
+ // Now mark any still active animations as active and add any new animations.
+ if (targetStyle->animations()) {
+ int numAnims = targetStyle->animations()->size();
+ for (int i = 0; i < numAnims; ++i) {
+ const Animation* anim = targetStyle->animations()->animation(i);
+ AtomicString animationName(anim->name());
+
+ if (!anim->isValidAnimation())
+ continue;
+
+ // See if there is a current animation for this name.
+ RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl());
- if (keyframeAnim) {
- // There is one so it is still active
-
- // Animations match, but play states may differ. update if needed
- keyframeAnim->updatePlayState(anim->playState() == AnimPlayStatePlaying);
-
- // Set the saved animation to this new one, just in case the play state has changed
- keyframeAnim->setAnimation(anim);
- keyframeAnim->setIndex(i);
- } else if ((anim->duration() || anim->delay()) && anim->iterationCount()) {
- keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, currentStyle ? currentStyle : targetStyle);
- m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
+ if (keyframeAnim) {
+ // If this animation is postActive, skip it so it gets removed at the end of this function.
+ if (keyframeAnim->postActive())
+ continue;
+
+ // This one is still active.
+
+ // Animations match, but play states may differ. Update if needed.
+ keyframeAnim->updatePlayState(anim->playState() == AnimPlayStatePlaying);
+
+ // Set the saved animation to this new one, just in case the play state has changed.
+ keyframeAnim->setAnimation(anim);
+ keyframeAnim->setIndex(i);
+ } else if ((anim->duration() || anim->delay()) && anim->iterationCount()) {
+ keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, currentStyle ? currentStyle : targetStyle);
+ m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
+ }
+
+ // Add this to the animation order map.
+ if (keyframeAnim)
+ m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl());
}
-
- // Add this to the animation order map
- if (keyframeAnim)
- m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl());
}
}
-
- // Make a list of animations to be removed
+
+ // Make a list of animations to be removed.
Vector<AtomicStringImpl*> animsToBeRemoved;
kfend = m_keyframeAnimations.end();
for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) {
@@ -214,7 +250,7 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render
animsToBeRemoved.append(keyframeAnim->name().impl());
}
- // Now remove the animations from the list
+ // Now remove the animations from the list.
for (size_t j = 0; j < animsToBeRemoved.size(); ++j)
m_keyframeAnimations.remove(animsToBeRemoved[j]);
}
@@ -223,11 +259,9 @@ PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, Rend
{
RefPtr<RenderStyle> resultStyle;
- // Update animations first so we can see if any transitions are overridden
- updateKeyframeAnimations(renderer, currentStyle, targetStyle);
-
- // We don't do any transitions if we don't have a currentStyle (on startup)
+ // We don't do any transitions if we don't have a currentStyle (on startup).
updateTransitions(renderer, currentStyle, targetStyle);
+ updateKeyframeAnimations(renderer, currentStyle, targetStyle);
if (currentStyle) {
// Now that we have transition objects ready, let them know about the new goal state. We want them
@@ -249,8 +283,6 @@ PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, Rend
keyframeAnim->animate(this, renderer, currentStyle, targetStyle, resultStyle);
}
- cleanupFinishedAnimations();
-
return resultStyle ? resultStyle.release() : targetStyle;
}
@@ -341,50 +373,6 @@ PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int pr
return retval;
}
-void CompositeAnimation::cleanupFinishedAnimations()
-{
- if (isSuspended())
- return;
-
- // Make a list of transitions to be deleted
- Vector<int> finishedTransitions;
- if (!m_transitions.isEmpty()) {
- CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end();
-
- for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) {
- ImplicitAnimation* anim = it->second.get();
- if (!anim)
- continue;
- if (anim->postActive())
- finishedTransitions.append(anim->animatingProperty());
- }
-
- // Delete them
- size_t finishedTransitionCount = finishedTransitions.size();
- for (size_t i = 0; i < finishedTransitionCount; ++i)
- m_transitions.remove(finishedTransitions[i]);
- }
-
- // Make a list of animations to be deleted
- Vector<AtomicStringImpl*> finishedAnimations;
- if (!m_keyframeAnimations.isEmpty()) {
- AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end();
-
- for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) {
- KeyframeAnimation* anim = it->second.get();
- if (!anim)
- continue;
- if (anim->postActive())
- finishedAnimations.append(anim->name().impl());
- }
-
- // Delete them
- size_t finishedAnimationCount = finishedAnimations.size();
- for (size_t i = 0; i < finishedAnimationCount; ++i)
- m_keyframeAnimations.remove(finishedAnimations[i]);
- }
-}
-
void CompositeAnimation::suspendAnimations()
{
if (m_isSuspended)
@@ -492,7 +480,7 @@ bool CompositeAnimation::pauseAnimationAtTime(const AtomicString& name, double t
int count = keyframeAnim->m_animation->iterationCount();
if ((t >= 0.0) && (!count || (t <= count * keyframeAnim->duration()))) {
- keyframeAnim->pauseAtTime(t);
+ keyframeAnim->freezeAtTime(t);
return true;
}
@@ -509,7 +497,7 @@ bool CompositeAnimation::pauseTransitionAtTime(int property, double t)
return false;
if ((t >= 0.0) && (t <= implAnim->duration())) {
- implAnim->pauseAtTime(t);
+ implAnim->freezeAtTime(t);
return true;
}
diff --git a/WebCore/page/animation/CompositeAnimation.h b/WebCore/page/animation/CompositeAnimation.h
index 739cfdc..b7db442 100644
--- a/WebCore/page/animation/CompositeAnimation.h
+++ b/WebCore/page/animation/CompositeAnimation.h
@@ -74,8 +74,6 @@ public:
PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property) const;
- void cleanupFinishedAnimations();
-
void overrideImplicitAnimations(int property);
void resumeOverriddenImplicitAnimations(int property);
diff --git a/WebCore/page/animation/ImplicitAnimation.cpp b/WebCore/page/animation/ImplicitAnimation.cpp
index e93fee4..8e6349d 100644
--- a/WebCore/page/animation/ImplicitAnimation.cpp
+++ b/WebCore/page/animation/ImplicitAnimation.cpp
@@ -45,6 +45,7 @@ ImplicitAnimation::ImplicitAnimation(const Animation* transition, int animatingP
, m_transitionProperty(transition->property())
, m_animatingProperty(animatingProperty)
, m_overridden(false)
+ , m_active(true)
, m_fromStyle(fromStyle)
{
ASSERT(animatingProperty != cAnimateAll);
@@ -211,6 +212,10 @@ bool ImplicitAnimation::affectsProperty(int property) const
bool ImplicitAnimation::isTargetPropertyEqual(int prop, const RenderStyle* targetStyle)
{
+ // We can get here for a transition that has not started yet. This would make m_toStyle unset and null.
+ // So we check that here (see <https://bugs.webkit.org/show_bug.cgi?id=26706>)
+ if (!m_toStyle)
+ return false;
return propertiesEqual(prop, m_toStyle.get(), targetStyle);
}
diff --git a/WebCore/page/animation/ImplicitAnimation.h b/WebCore/page/animation/ImplicitAnimation.h
index 33fe4e4..7e286d2 100644
--- a/WebCore/page/animation/ImplicitAnimation.h
+++ b/WebCore/page/animation/ImplicitAnimation.h
@@ -66,6 +66,9 @@ public:
void blendPropertyValueInStyle(int, RenderStyle* currentStyle);
virtual double timeToNextService();
+
+ bool active() const { return m_active; }
+ void setActive(bool b) { m_active = b; }
protected:
bool shouldSendEventForListener(Document::ListenerType) const;
@@ -80,6 +83,7 @@ private:
int m_transitionProperty; // Transition property as specified in the RenderStyle. May be cAnimateAll
int m_animatingProperty; // Specific property for this ImplicitAnimation
bool m_overridden; // true when there is a keyframe animation that overrides the transitioning property
+ bool m_active; // used for culling the list of transitions
// The two styles that we are blending.
RefPtr<RenderStyle> m_fromStyle;
diff --git a/WebCore/page/animation/KeyframeAnimation.cpp b/WebCore/page/animation/KeyframeAnimation.cpp
index 3f84de1..39ae1e7 100644
--- a/WebCore/page/animation/KeyframeAnimation.cpp
+++ b/WebCore/page/animation/KeyframeAnimation.cpp
@@ -93,8 +93,10 @@ void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromSty
return;
const TimingFunction* timingFunction = 0;
- if (fromStyle->animations() && fromStyle->animations()->size() > 0)
+ if (fromStyle->animations() && fromStyle->animations()->size() > 0) {
+ // We get the timing function from the first animation, because we've synthesized a RenderStyle for each keyframe.
timingFunction = &(fromStyle->animations()->animation(0)->timingFunction());
+ }
prog = progress(scale, offset, timingFunction);
}
@@ -209,8 +211,12 @@ void KeyframeAnimation::endAnimation(bool reset)
#if USE(ACCELERATED_COMPOSITING)
if (m_object->hasLayer()) {
RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
- if (layer->isComposited())
- layer->backing()->animationFinished(m_keyframes.animationName(), 0, reset);
+ if (layer->isComposited()) {
+ if (reset)
+ layer->backing()->animationFinished(m_keyframes.animationName());
+ else
+ layer->backing()->animationPaused(m_keyframes.animationName());
+ }
}
#else
UNUSED_PARAM(reset);
diff --git a/WebCore/page/chromium/EventHandlerChromium.cpp b/WebCore/page/chromium/EventHandlerChromium.cpp
index 0cfc12d..467f94e 100644
--- a/WebCore/page/chromium/EventHandlerChromium.cpp
+++ b/WebCore/page/chromium/EventHandlerChromium.cpp
@@ -105,8 +105,7 @@ bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR
// Figure out which view to send the event to.
if (!event.targetNode() || !event.targetNode()->renderer() || !event.targetNode()->renderer()->isWidget())
return false;
-
- return passMouseDownEventToWidget(static_cast<RenderWidget*>(event.targetNode()->renderer())->widget());
+ return passMouseDownEventToWidget(toRenderWidget(event.targetNode()->renderer())->widget());
}
bool EventHandler::passMouseDownEventToWidget(Widget* widget)
diff --git a/WebCore/page/chromium/FrameChromium.cpp b/WebCore/page/chromium/FrameChromium.cpp
index 5253bbc..1372cd9 100644
--- a/WebCore/page/chromium/FrameChromium.cpp
+++ b/WebCore/page/chromium/FrameChromium.cpp
@@ -46,7 +46,7 @@ void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float head
if (!frame->document() || !frame->view() || !frame->document()->renderer())
return;
- RenderView* root = static_cast<RenderView*>(frame->document()->renderer());
+ RenderView* root = toRenderView(frame->document()->renderer());
if (!root) {
LOG_ERROR("document to be printed has no renderer");
diff --git a/WebCore/page/gtk/DragControllerGtk.cpp b/WebCore/page/gtk/DragControllerGtk.cpp
index 9e17255..c064a87 100644
--- a/WebCore/page/gtk/DragControllerGtk.cpp
+++ b/WebCore/page/gtk/DragControllerGtk.cpp
@@ -53,7 +53,7 @@ DragOperation DragController::dragOperation(DragData* dragData)
if (dragData->containsURL())
return DragOperationCopy;
- return DragOperationNone;
+ return DragOperationNone;
}
const IntSize& DragController::maxDragImageSize()
diff --git a/WebCore/page/gtk/EventHandlerGtk.cpp b/WebCore/page/gtk/EventHandlerGtk.cpp
index 7692dae..d12cdcc 100644
--- a/WebCore/page/gtk/EventHandlerGtk.cpp
+++ b/WebCore/page/gtk/EventHandlerGtk.cpp
@@ -62,8 +62,7 @@ bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR
RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : 0;
if (!target || !target->isWidget())
return false;
-
- return passMouseDownEventToWidget(static_cast<RenderWidget*>(target)->widget());
+ return passMouseDownEventToWidget(toRenderWidget(target)->widget());
}
bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
diff --git a/WebCore/page/haiku/DragControllerHaiku.cpp b/WebCore/page/haiku/DragControllerHaiku.cpp
new file mode 100644
index 0000000..0b95558
--- /dev/null
+++ b/WebCore/page/haiku/DragControllerHaiku.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DragController.h"
+
+#include "DragData.h"
+
+#include <InterfaceDefs.h>
+
+
+namespace WebCore
+{
+
+// FIXME: These values are straight out of DragControllerMac, so probably have
+// little correlation with Haiku standards...
+const int DragController::LinkDragBorderInset = 2;
+const int DragController::MaxOriginalImageArea = 1500 * 1500;
+const int DragController::DragIconRightInset = 7;
+const int DragController::DragIconBottomInset = 3;
+
+const float DragController::DragImageAlpha = 0.75f;
+
+
+bool DragController::isCopyKeyDown()
+{
+ if (modifiers() & B_COMMAND_KEY)
+ return true;
+
+ return false;
+}
+
+DragOperation DragController::dragOperation(DragData* dragData)
+{
+ // FIXME: This logic is incomplete
+ if (dragData->containsURL())
+ return DragOperationCopy;
+
+ return DragOperationNone;
+}
+
+const IntSize& DragController::maxDragImageSize()
+{
+ static const IntSize maxDragImageSize(400, 400);
+
+ return maxDragImageSize;
+}
+
+void DragController::cleanupAfterSystemDrag()
+{
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/page/haiku/EventHandlerHaiku.cpp b/WebCore/page/haiku/EventHandlerHaiku.cpp
new file mode 100644
index 0000000..64b8519
--- /dev/null
+++ b/WebCore/page/haiku/EventHandlerHaiku.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "EventHandler.h"
+
+#include "ClipboardHaiku.h"
+#include "EventNames.h"
+#include "FocusController.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "HitTestResult.h"
+#include "KeyboardEvent.h"
+#include "MouseEventWithHitTestResults.h"
+#include "Page.h"
+#include "PlatformKeyboardEvent.h"
+#include "PlatformScrollBar.h"
+#include "PlatformWheelEvent.h"
+#include "RenderWidget.h"
+
+#include "NotImplemented.h"
+
+#include <interface/View.h>
+
+
+namespace WebCore {
+
+const double EventHandler::TextDragDelay = 0.0;
+
+static bool isKeyboardOptionTab(KeyboardEvent* event)
+{
+ return event
+ && (event->type() == eventNames().keydownEvent
+ || event->type() == eventNames().keypressEvent)
+ && event->altKey()
+ && event->keyIdentifier() == "U+000009";
+}
+
+bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent* event) const
+{
+ return isKeyboardOptionTab(event);
+}
+
+bool EventHandler::tabsToAllControls(KeyboardEvent* event) const
+{
+ bool handlingOptionTab = isKeyboardOptionTab(event);
+
+ return handlingOptionTab;
+}
+
+void EventHandler::focusDocumentView()
+{
+ BView* view = m_frame->view()->platformWidget();
+ if (view)
+ view->MakeFocus();
+
+ Page* page = m_frame->page();
+ if (page)
+ page->focusController()->setFocusedFrame(m_frame);
+}
+
+bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
+{
+ // Figure out which view to send the event to.
+ RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : 0;
+ if (!target || !target->isWidget())
+ return false;
+ return passMouseDownEventToWidget(toRenderWidget(target)->widget());
+}
+
+bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
+{
+ return passMouseDownEventToWidget(renderWidget->widget());
+}
+
+bool EventHandler::passMouseDownEventToWidget(Widget* widget)
+{
+ notImplemented();
+ return false;
+}
+
+bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const
+{
+ notImplemented();
+ return false;
+}
+
+bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframe, HitTestResult*)
+{
+ notImplemented();
+ return true;
+}
+
+bool EventHandler::passWheelEventToWidget(PlatformWheelEvent& event, Widget* widget)
+{
+ notImplemented();
+ return false;
+}
+
+PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const
+{
+ return new ClipboardHaiku(ClipboardWritable, true);
+}
+
+bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
+{
+ return passSubframeEventToSubframe(mev, subframe);
+}
+
+bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe, HitTestResult* hoveredNode)
+{
+ return passSubframeEventToSubframe(mev, subframe, hoveredNode);
+}
+
+bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
+{
+ return passSubframeEventToSubframe(mev, subframe);
+}
+
+unsigned EventHandler::accessKeyModifiers()
+{
+ return PlatformKeyboardEvent::AltKey;
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/page/haiku/FrameHaiku.cpp b/WebCore/page/haiku/FrameHaiku.cpp
new file mode 100644
index 0000000..50168dd
--- /dev/null
+++ b/WebCore/page/haiku/FrameHaiku.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Frame.h"
+
+#include "NotImplemented.h"
+
+
+namespace WebCore {
+
+DragImageRef Frame::dragImageForSelection()
+{
+ notImplemented();
+ return 0;
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/page/mac/EventHandlerMac.mm b/WebCore/page/mac/EventHandlerMac.mm
index d69aff4..54bdff9 100644
--- a/WebCore/page/mac/EventHandlerMac.mm
+++ b/WebCore/page/mac/EventHandlerMac.mm
@@ -45,6 +45,7 @@
#include "RuntimeApplicationChecks.h"
#include "Scrollbar.h"
#include "Settings.h"
+#include "WebCoreSystemInterface.h"
#include <objc/objc-runtime.h>
#include <wtf/StdLibExtras.h>
@@ -72,7 +73,7 @@ NSEvent *EventHandler::currentNSEvent()
return currentNSEventSlot().get();
}
-class CurrentEventScope : Noncopyable {
+class CurrentEventScope : public Noncopyable {
public:
CurrentEventScope(NSEvent *);
~CurrentEventScope();
@@ -107,6 +108,8 @@ bool EventHandler::wheelEvent(NSEvent *event)
CurrentEventScope scope(event);
+ m_useLatchedWheelEventNode = wkIsLatchingWheelEvent(event);
+
PlatformWheelEvent wheelEvent(event, page->chrome()->platformWindow());
handleWheelEvent(wheelEvent);
@@ -229,7 +232,7 @@ bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR
// just pass currentEvent down to the widget, we don't want to call it for events that
// don't correspond to Cocoa events. The mousedown/ups will have already been passed on as
// part of the pressed/released handling.
- return passMouseDownEventToWidget(static_cast<RenderWidget*>(target)->widget());
+ return passMouseDownEventToWidget(toRenderWidget(target)->widget());
}
bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
@@ -255,10 +258,12 @@ static bool lastEventIsMouseUp()
return false;
}
-bool EventHandler::passMouseDownEventToWidget(Widget* widget)
+bool EventHandler::passMouseDownEventToWidget(Widget* pWidget)
{
// FIXME: This function always returns true. It should be changed either to return
// false in some cases or the return value should be removed.
+
+ RefPtr<Widget> widget = pWidget;
if (!widget) {
LOG_ERROR("hit a RenderWidget without a corresponding Widget, means a frame is half-constructed");
@@ -300,7 +305,10 @@ bool EventHandler::passMouseDownEventToWidget(Widget* widget)
ASSERT(!m_sendingEventToSubview);
m_sendingEventToSubview = true;
+ NSView *outerView = widget->getOuterView();
+ widget->beforeMouseDown(outerView, widget.get());
[view mouseDown:currentNSEvent()];
+ widget->afterMouseDown(outerView, widget.get());
m_sendingEventToSubview = false;
if (!wasDeferringLoading)
@@ -441,10 +449,10 @@ bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& eve
RenderObject* renderer = node->renderer();
if (!renderer || !renderer->isWidget())
return false;
- Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
+ Widget* widget = toRenderWidget(renderer)->widget();
if (!widget || !widget->isFrameView())
return false;
- if (!passWidgetMouseDownEventToWidget(static_cast<RenderWidget*>(renderer)))
+ if (!passWidgetMouseDownEventToWidget(toRenderWidget(renderer)))
return false;
m_mouseDownWasInSubframe = true;
return true;
@@ -543,8 +551,8 @@ void EventHandler::mouseDown(NSEvent *event)
m_mouseDownView = nil;
CurrentEventScope scope(event);
- m_mouseDown = currentPlatformMouseEvent();
- handleMousePressEvent(m_mouseDown);
+
+ handleMousePressEvent(currentPlatformMouseEvent());
END_BLOCK_OBJC_EXCEPTIONS;
}
diff --git a/WebCore/page/mac/FrameMac.mm b/WebCore/page/mac/FrameMac.mm
index decbcad..c656624 100644
--- a/WebCore/page/mac/FrameMac.mm
+++ b/WebCore/page/mac/FrameMac.mm
@@ -147,10 +147,11 @@ static RegularExpression* regExpForLabels(NSArray* labels)
NSString* Frame::searchForNSLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell)
{
- RenderTableCell* cellRenderer = static_cast<RenderTableCell*>(cell->renderer());
+ RenderObject* cellRenderer = cell->renderer();
if (cellRenderer && cellRenderer->isTableCell()) {
- RenderTableCell* cellAboveRenderer = cellRenderer->table()->cellAbove(cellRenderer);
+ RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer);
+ RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer);
if (cellAboveRenderer) {
HTMLTableCellElement* aboveCell =
@@ -470,8 +471,11 @@ void Frame::setUseSecureKeyboardEntry(bool enable)
#ifdef BUILDING_ON_TIGER
KeyScript(enableRomanKeyboardsOnly);
#else
+ // WebKit substitutes nil for input context when in password field, which corresponds to null TSMDocument. So, there is
+ // no need to call TSMGetActiveDocument(), which may return an incorrect result when selection hasn't been yet updated
+ // after focusing a node.
CFArrayRef inputSources = TISCreateASCIICapableInputSourceList();
- TSMSetDocumentProperty(TSMGetActiveDocument(), kTSMDocumentEnabledInputSourcesPropertyTag, sizeof(CFArrayRef), &inputSources);
+ TSMSetDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag, sizeof(CFArrayRef), &inputSources);
CFRelease(inputSources);
#endif
} else {
@@ -479,7 +483,7 @@ void Frame::setUseSecureKeyboardEntry(bool enable)
#ifdef BUILDING_ON_TIGER
KeyScript(smKeyEnableKybds);
#else
- TSMRemoveDocumentProperty(TSMGetActiveDocument(), kTSMDocumentEnabledInputSourcesPropertyTag);
+ TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag);
#endif
}
}
diff --git a/WebCore/page/mac/WebCoreViewFactory.h b/WebCore/page/mac/WebCoreViewFactory.h
index c18f4d4..d4dc821 100644
--- a/WebCore/page/mac/WebCoreViewFactory.h
+++ b/WebCore/page/mac/WebCoreViewFactory.h
@@ -141,6 +141,9 @@
// FTP Directory Related
- (NSString *)unknownFileSizeText;
+- (NSString *)mediaElementLoadingStateText;
+- (NSString *)mediaElementLiveBroadcastStateText;
+
@end
@interface WebCoreViewFactory : NSObject
diff --git a/WebCore/page/qt/DragControllerQt.cpp b/WebCore/page/qt/DragControllerQt.cpp
index 1fe56b4..e6c7682 100644
--- a/WebCore/page/qt/DragControllerQt.cpp
+++ b/WebCore/page/qt/DragControllerQt.cpp
@@ -31,8 +31,7 @@
#include "FrameView.h"
#include "Page.h"
-namespace WebCore
-{
+namespace WebCore {
// FIXME: These values are straight out of DragControllerMac, so probably have
// little correlation with Qt standards...
diff --git a/WebCore/page/win/DragControllerWin.cpp b/WebCore/page/win/DragControllerWin.cpp
index dca8ea2..f0404ff 100644
--- a/WebCore/page/win/DragControllerWin.cpp
+++ b/WebCore/page/win/DragControllerWin.cpp
@@ -50,7 +50,8 @@ DragOperation DragController::dragOperation(DragData* dragData)
return dragData->containsURL() && !m_didInitiateDrag ? DragOperationCopy : DragOperationNone;
}
-bool DragController::isCopyKeyDown() {
+bool DragController::isCopyKeyDown()
+{
return ::GetAsyncKeyState(VK_CONTROL);
}
diff --git a/WebCore/page/win/EventHandlerWin.cpp b/WebCore/page/win/EventHandlerWin.cpp
index 88bc373..50e50fb 100644
--- a/WebCore/page/win/EventHandlerWin.cpp
+++ b/WebCore/page/win/EventHandlerWin.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -87,9 +88,13 @@ bool EventHandler::eventActivatedView(const PlatformMouseEvent& event) const
PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const
{
+#if PLATFORM(WINCE)
+ return 0;
+#else
COMPtr<WCDataObject> dataObject;
WCDataObject::createInstance(&dataObject);
return ClipboardWin::create(true, dataObject.get(), ClipboardWritable);
+#endif
}
void EventHandler::focusDocumentView()
diff --git a/WebCore/page/win/FrameCGWin.cpp b/WebCore/page/win/FrameCGWin.cpp
index 8b0408d..7483627 100644
--- a/WebCore/page/win/FrameCGWin.cpp
+++ b/WebCore/page/win/FrameCGWin.cpp
@@ -28,6 +28,7 @@
#include <windows.h>
+#include "BitmapInfo.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "Settings.h"
@@ -55,7 +56,7 @@ static HBITMAP imageFromRect(const Frame* frame, IntRect& ir)
HDC hdc = CreateCompatibleDC(0);
int w = ir.width();
int h = ir.height();
- BITMAPINFO bmp = { { sizeof(BITMAPINFOHEADER), w, h, 1, 32 } };
+ BitmapInfo bmp = BitmapInfo::create(IntSize(w, h));
HBITMAP hbmp = CreateDIBSection(0, &bmp, DIB_RGB_COLORS, static_cast<void**>(&bits), 0, 0);
HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc, hbmp));
diff --git a/WebCore/page/win/FrameWin.cpp b/WebCore/page/win/FrameWin.cpp
index 0c1c5b1..1e480fb 100644
--- a/WebCore/page/win/FrameWin.cpp
+++ b/WebCore/page/win/FrameWin.cpp
@@ -47,7 +47,7 @@ void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float head
if (!frame->document() || !frame->view() || !frame->document()->renderer())
return;
- RenderView* root = static_cast<RenderView*>(frame->document()->renderer());
+ RenderView* root = toRenderView(frame->document()->renderer());
if (!root) {
LOG_ERROR("document to be printed has no renderer");
diff --git a/WebCore/page/win/FrameWin.h b/WebCore/page/win/FrameWin.h
index 405c7b2..2924291 100644
--- a/WebCore/page/win/FrameWin.h
+++ b/WebCore/page/win/FrameWin.h
@@ -34,7 +34,7 @@ typedef struct HBITMAP__* HBITMAP;
namespace WebCore {
HBITMAP imageFromSelection(Frame* frame, bool forceWhiteText);
- void computePageRectsForFrame(Frame*, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor,Vector<IntRect>& pages, int& pageHeight);
+ void computePageRectsForFrame(Frame*, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& pages, int& pageHeight);
}
diff --git a/WebCore/page/win/PageWin.cpp b/WebCore/page/win/PageWin.cpp
index f4c744a..5d7450c 100644
--- a/WebCore/page/win/PageWin.cpp
+++ b/WebCore/page/win/PageWin.cpp
@@ -27,12 +27,36 @@
#include "Page.h"
#include "Frame.h"
+#include "FrameLoaderClient.h"
#include "FrameView.h"
#include "FloatRect.h"
+#include "PluginView.h"
#include <windows.h>
namespace WebCore {
HINSTANCE Page::s_instanceHandle = 0;
+void Page::setCanStartPlugins(bool canStartPlugins)
+{
+ if (m_canStartPlugins == canStartPlugins)
+ return;
+
+ m_canStartPlugins = canStartPlugins;
+
+ if (!m_canStartPlugins || m_unstartedPlugins.isEmpty())
+ return;
+
+ Vector<PluginView*> unstartedPlugins;
+ copyToVector(m_unstartedPlugins, unstartedPlugins);
+ m_unstartedPlugins.clear();
+
+ for (size_t i = 0; i < unstartedPlugins.size(); ++i) {
+ if (unstartedPlugins[i]->start())
+ continue;
+ unstartedPlugins[i]->parentFrame()->loader()->client()->dispatchDidFailToStartPlugin(unstartedPlugins[i]);
+ }
+}
+
} // namespace WebCore
+
diff --git a/WebCore/page/wince/FrameWince.cpp b/WebCore/page/wince/FrameWince.cpp
new file mode 100644
index 0000000..480a103
--- /dev/null
+++ b/WebCore/page/wince/FrameWince.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Frame.h"
+
+#include "Document.h"
+#include "EditorClient.h"
+#include "FloatRect.h"
+#include "FrameLoader.h"
+#include "FrameLoadRequest.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLIFrameElement.h"
+#include "HTMLNames.h"
+#include "HTMLTableCellElement.h"
+#include "KeyboardEvent.h"
+#include "NP_jsobject.h"
+#include "npruntime_impl.h"
+#include "Page.h"
+#include "Plugin.h"
+#include "RegularExpression.h"
+#include "RenderFrame.h"
+#include "RenderTableCell.h"
+#include "RenderView.h"
+#include "ResourceHandle.h"
+#include "runtime_root.h"
+#include "Settings.h"
+#include "TextResourceDecoder.h"
+#include "UserStyleSheetLoader.h"
+
+#include <windows.h>
+
+using std::min;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+extern HDC g_screenDC;
+
+void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& pages, int& outPageHeight)
+{
+ ASSERT(frame);
+
+ pages.clear();
+ outPageHeight = 0;
+
+ if (!frame->document() || !frame->view() || !frame->document()->renderer())
+ return;
+
+ RenderView* root = toRenderView(frame->document()->renderer());
+
+ if (!root) {
+ LOG_ERROR("document to be printed has no renderer");
+ return;
+ }
+
+ if (userScaleFactor <= 0) {
+ LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor);
+ return;
+ }
+
+ float ratio = (float)printRect.height() / (float)printRect.width();
+
+ float pageWidth = (float) root->overflowWidth();
+ float pageHeight = pageWidth * ratio;
+ outPageHeight = (int) pageHeight; // this is the height of the page adjusted by margins
+ pageHeight -= (headerHeight + footerHeight);
+
+ if (pageHeight <= 0) {
+ LOG_ERROR("pageHeight has bad value %.2f", pageHeight);
+ return;
+ }
+
+ float currPageHeight = pageHeight / userScaleFactor;
+ float docHeight = root->layer()->height();
+ float docWidth = root->layer()->width();
+ float currPageWidth = pageWidth / userScaleFactor;
+
+
+ // always return at least one page, since empty files should print a blank page
+ float printedPagesHeight = 0.0;
+ do {
+ float proposedBottom = min(docHeight, printedPagesHeight + pageHeight);
+ frame->view()->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
+ currPageHeight = max(1.0f, proposedBottom - printedPagesHeight);
+
+ pages.append(IntRect(0, printedPagesHeight, currPageWidth, currPageHeight));
+ printedPagesHeight += currPageHeight;
+ } while (printedPagesHeight < docHeight);
+}
+
+HBITMAP imageFromSelection(Frame* frame, bool forceBlackText)
+{
+ if (!frame->view())
+ return 0;
+
+ frame->view()->setPaintRestriction(forceBlackText ? PaintRestrictionSelectionOnlyBlackText : PaintRestrictionSelectionOnly);
+ FloatRect fr = frame->selectionBounds();
+ IntRect ir((int)fr.x(), (int)fr.y(), (int)fr.width(), (int)fr.height());
+ if (ir.isEmpty())
+ return 0;
+
+ int w;
+ int h;
+ FrameView* view = frame->view();
+ if (view->parent()) {
+ ir.setLocation(view->parent()->convertChildToSelf(view, ir.location()));
+ w = ir.width() * view->scale() + 0.5;
+ h = ir.height() * view->scale() + 0.5;
+ } else {
+ ir = view->contentsToWindow(ir);
+ w = ir.width();
+ h = ir.height();
+ }
+
+ OwnPtr<HDC> bmpDC(CreateCompatibleDC(g_screenDC));
+ HBITMAP hBmp = MemoryManager::createCompatibleBitmap(g_screenDC, w, h);
+ if (!hBmp)
+ return 0;
+
+ HBITMAP hbmpOld = (HBITMAP)SelectObject(bmpDC.get(), hBmp);
+
+ {
+ GraphicsContext gc(bmpDC.get());
+ frame->document()->updateLayout();
+ view->paint(&gc, ir);
+ }
+
+ SelectObject(bmpDC.get(), hbmpOld);
+
+ frame->view()->setPaintRestriction(PaintRestrictionNone);
+
+ return hBmp;
+}
+
+DragImageRef Frame::dragImageForSelection()
+{
+ if (selection()->isRange())
+ return imageFromSelection(this, false);
+
+ return 0;
+}
+
+void Frame::setUserStyleSheetLocation(const KURL& url)
+{
+ delete m_userStyleSheetLoader;
+ m_userStyleSheetLoader = 0;
+ if (m_doc && m_doc->docLoader())
+ m_userStyleSheetLoader = new UserStyleSheetLoader(m_doc, url.string());
+}
+
+void Frame::setUserStyleSheet(const String& styleSheet)
+{
+ delete m_userStyleSheetLoader;
+ m_userStyleSheetLoader = 0;
+ if (m_doc)
+ m_doc->setUserStyleSheet(styleSheet);
+}
+
+} // namespace WebCore
diff --git a/WebCore/page/wx/EventHandlerWx.cpp b/WebCore/page/wx/EventHandlerWx.cpp
index a0d8b23..65a743c 100644
--- a/WebCore/page/wx/EventHandlerWx.cpp
+++ b/WebCore/page/wx/EventHandlerWx.cpp
@@ -62,7 +62,7 @@ bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR
if (!event.targetNode() || !event.targetNode()->renderer() || !event.targetNode()->renderer()->isWidget())
return false;
- return passMouseDownEventToWidget(static_cast<RenderWidget*>(event.targetNode()->renderer())->widget());
+ return passMouseDownEventToWidget(toRenderWidget(event.targetNode()->renderer())->widget());
}
bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)