summaryrefslogtreecommitdiffstats
path: root/WebCore/page
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-05 14:36:32 +0100
committerBen Murdoch <benm@google.com>2011-05-10 15:38:30 +0100
commitf05b935882198ccf7d81675736e3aeb089c5113a (patch)
tree4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /WebCore/page
parent60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff)
downloadexternal_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.zip
external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.gz
external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.bz2
Merge WebKit at r74534: Initial merge by git.
Change-Id: I6ccd1154fa1b19c2ec2a66878eb675738735f1eb
Diffstat (limited to 'WebCore/page')
-rw-r--r--WebCore/page/Chrome.cpp5
-rw-r--r--WebCore/page/Chrome.h4
-rw-r--r--WebCore/page/ChromeClient.h5
-rw-r--r--WebCore/page/Console.cpp36
-rw-r--r--WebCore/page/Console.h41
-rw-r--r--WebCore/page/ContextMenuClient.h8
-rw-r--r--WebCore/page/ContextMenuController.cpp898
-rw-r--r--WebCore/page/ContextMenuController.h24
-rw-r--r--WebCore/page/Coordinates.h9
-rw-r--r--WebCore/page/DOMSelection.cpp10
-rw-r--r--WebCore/page/DOMWindow.cpp262
-rw-r--r--WebCore/page/DOMWindow.h209
-rw-r--r--WebCore/page/DOMWindow.idl11
-rw-r--r--WebCore/page/DragController.cpp8
-rw-r--r--WebCore/page/EditorClient.h9
-rw-r--r--WebCore/page/EventHandler.cpp96
-rw-r--r--WebCore/page/EventHandler.h2
-rw-r--r--WebCore/page/EventSource.cpp2
-rw-r--r--WebCore/page/FocusController.cpp66
-rw-r--r--WebCore/page/FrameLoadRequest.h19
-rw-r--r--WebCore/page/FrameView.cpp149
-rw-r--r--WebCore/page/FrameView.h5
-rw-r--r--WebCore/page/Geolocation.cpp22
-rw-r--r--WebCore/page/Geolocation.h19
-rw-r--r--WebCore/page/GeolocationClient.h4
-rw-r--r--WebCore/page/GeolocationController.cpp12
-rw-r--r--WebCore/page/GeolocationController.h3
-rw-r--r--WebCore/page/GeolocationPositionCache.cpp169
-rw-r--r--WebCore/page/GeolocationPositionCache.h44
-rw-r--r--WebCore/page/Geoposition.h8
-rw-r--r--WebCore/page/Page.cpp25
-rw-r--r--WebCore/page/Page.h8
-rw-r--r--WebCore/page/PerformanceNavigation.cpp10
-rw-r--r--WebCore/page/PerformanceNavigation.h7
-rw-r--r--WebCore/page/PerformanceNavigation.idl9
-rw-r--r--WebCore/page/PerformanceTiming.cpp32
-rw-r--r--WebCore/page/PerformanceTiming.h5
-rw-r--r--WebCore/page/PerformanceTiming.idl5
-rw-r--r--WebCore/page/SecurityOrigin.cpp11
-rw-r--r--WebCore/page/SecurityOrigin.h12
-rw-r--r--WebCore/page/Settings.cpp7
-rw-r--r--WebCore/page/Settings.h4
-rw-r--r--WebCore/page/SpatialNavigation.cpp83
-rw-r--r--WebCore/page/SpatialNavigation.h34
-rw-r--r--WebCore/page/WindowFeatures.cpp120
-rw-r--r--WebCore/page/WindowFeatures.h22
-rw-r--r--WebCore/page/XSSAuditor.cpp2
-rw-r--r--WebCore/page/animation/AnimationBase.cpp48
-rw-r--r--WebCore/page/animation/AnimationBase.h3
-rw-r--r--WebCore/page/animation/AnimationController.cpp45
-rw-r--r--WebCore/page/animation/AnimationControllerPrivate.h15
-rw-r--r--WebCore/page/animation/CompositeAnimation.cpp16
-rw-r--r--WebCore/page/mac/DragControllerMac.mm4
-rw-r--r--WebCore/page/mac/EventHandlerMac.mm2
-rw-r--r--WebCore/page/mac/WebCoreFrameView.h4
55 files changed, 2153 insertions, 539 deletions
diff --git a/WebCore/page/Chrome.cpp b/WebCore/page/Chrome.cpp
index 83d0f85..a801065 100644
--- a/WebCore/page/Chrome.cpp
+++ b/WebCore/page/Chrome.cpp
@@ -521,4 +521,9 @@ void Chrome::showContextMenu()
}
#endif
+bool Chrome::requiresFullscreenForVideoPlayback()
+{
+ return m_client->requiresFullscreenForVideoPlayback();
+}
+
} // namespace WebCore
diff --git a/WebCore/page/Chrome.h b/WebCore/page/Chrome.h
index f2c5db4..93b8c4a 100644
--- a/WebCore/page/Chrome.h
+++ b/WebCore/page/Chrome.h
@@ -139,6 +139,8 @@ namespace WebCore {
void print(Frame*);
+ // FIXME: Remove once all ports are using client-based geolocation. https://bugs.webkit.org/show_bug.cgi?id=40373
+ // For client-based geolocation, these two methods have moved to GeolocationClient. https://bugs.webkit.org/show_bug.cgi?id=50061
void requestGeolocationPermissionForFrame(Frame*, Geolocation*);
void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*);
@@ -147,6 +149,8 @@ namespace WebCore {
void dispatchViewportDataDidChange(const ViewportArguments&) const;
+ bool requiresFullscreenForVideoPlayback();
+
#if PLATFORM(MAC)
void focusNSView(NSView*);
#endif
diff --git a/WebCore/page/ChromeClient.h b/WebCore/page/ChromeClient.h
index d224726..074cc81 100644
--- a/WebCore/page/ChromeClient.h
+++ b/WebCore/page/ChromeClient.h
@@ -206,11 +206,13 @@ namespace WebCore {
float value, float proportion, ScrollbarControlPartMask);
virtual bool paintCustomScrollCorner(GraphicsContext*, const FloatRect&);
+ // FIXME: Remove once all ports are using client-based geolocation. https://bugs.webkit.org/show_bug.cgi?id=40373
+ // For client-based geolocation, these two methods have moved to GeolocationClient. https://bugs.webkit.org/show_bug.cgi?id=50061
// This can be either a synchronous or asynchronous call. The ChromeClient can display UI asking the user for permission
// to use Geolocation.
virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) = 0;
virtual void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*) = 0;
-
+
virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) = 0;
// Asynchronous request to load an icon for specified filenames.
virtual void chooseIconForFiles(const Vector<String>&, FileChooser*) = 0;
@@ -254,6 +256,7 @@ namespace WebCore {
virtual bool supportsFullscreenForNode(const Node*) { return false; }
virtual void enterFullscreenForNode(Node*) { }
virtual void exitFullscreenForNode(Node*) { }
+ virtual bool requiresFullscreenForVideoPlayback() { return false; }
#if ENABLE(FULLSCREEN_API)
virtual bool supportsFullScreenForElement(const Element*) { return false; }
diff --git a/WebCore/page/Console.cpp b/WebCore/page/Console.cpp
index 34db538..219647d 100644
--- a/WebCore/page/Console.cpp
+++ b/WebCore/page/Console.cpp
@@ -137,7 +137,7 @@ void Console::addMessage(MessageSource source, MessageType type, MessageLevel le
addMessage(source, type, level, message, lineNumber, sourceURL, 0);
}
-void Console::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL, PassOwnPtr<ScriptCallStack> callStack)
+void Console::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack> callStack)
{
Page* page = this->page();
if (!page)
@@ -162,7 +162,7 @@ void Console::addMessage(MessageSource source, MessageType type, MessageLevel le
printf(" %s\n", message.utf8().data());
}
-void Console::addMessage(MessageType type, MessageLevel level, PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack, bool acceptNoArguments)
+void Console::addMessage(MessageType type, MessageLevel level, PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack, bool acceptNoArguments)
{
Page* page = this->page();
if (!page)
@@ -194,39 +194,39 @@ void Console::addMessage(MessageType type, MessageLevel level, PassOwnPtr<Script
#endif
}
-void Console::debug(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::debug(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
// In Firebug, console.debug has the same behavior as console.log. So we'll do the same.
log(arguments, callStack);
}
-void Console::error(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::error(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
addMessage(LogMessageType, ErrorMessageLevel, arguments, callStack);
}
-void Console::info(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::info(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
log(arguments, callStack);
}
-void Console::log(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::log(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
addMessage(LogMessageType, LogMessageLevel, arguments, callStack);
}
-void Console::dir(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::dir(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
addMessage(ObjectMessageType, LogMessageLevel, arguments, callStack);
}
-void Console::dirxml(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::dirxml(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
// The standard behavior of our console.log will print the DOM tree for nodes.
log(arguments, callStack);
}
-void Console::trace(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::trace(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
addMessage(TraceMessageType, LogMessageLevel, arguments, callStack, true);
@@ -240,7 +240,7 @@ void Console::trace(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCall
}
}
-void Console::assertCondition(bool condition, PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::assertCondition(bool condition, PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
if (condition)
return;
@@ -248,7 +248,7 @@ void Console::assertCondition(bool condition, PassOwnPtr<ScriptArguments> argume
addMessage(AssertMessageType, ErrorMessageLevel, arguments, callStack, true);
}
-void Console::count(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::count(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
#if ENABLE(INSPECTOR)
Page* page = this->page();
@@ -267,7 +267,7 @@ void Console::count(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCall
#endif
}
-void Console::markTimeline(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack>)
+void Console::markTimeline(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack>)
{
#if ENABLE(INSPECTOR)
Page* page = this->page();
@@ -312,7 +312,7 @@ String Console::lastWMLErrorMessage() const
#if ENABLE(JAVASCRIPT_DEBUGGER)
-void Console::profile(const String& title, ScriptState* state, PassOwnPtr<ScriptCallStack> callStack)
+void Console::profile(const String& title, ScriptState* state, PassRefPtr<ScriptCallStack> callStack)
{
Page* page = this->page();
if (!page)
@@ -341,7 +341,7 @@ void Console::profile(const String& title, ScriptState* state, PassOwnPtr<Script
#endif
}
-void Console::profileEnd(const String& title, ScriptState* state, PassOwnPtr<ScriptCallStack> callStack)
+void Console::profileEnd(const String& title, ScriptState* state, PassRefPtr<ScriptCallStack> callStack)
{
Page* page = this->page();
if (!page)
@@ -385,7 +385,7 @@ void Console::time(const String& title)
#endif
}
-void Console::timeEnd(const String& title, PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack> callStack)
+void Console::timeEnd(const String& title, PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack> callStack)
{
#if ENABLE(INSPECTOR)
Page* page = this->page();
@@ -411,7 +411,7 @@ void Console::timeEnd(const String& title, PassOwnPtr<ScriptArguments>, PassOwnP
#endif
}
-void Console::group(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::group(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
#if ENABLE(INSPECTOR)
Page* page = this->page();
@@ -425,7 +425,7 @@ void Console::group(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCall
#endif
}
-void Console::groupCollapsed(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::groupCollapsed(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
#if ENABLE(INSPECTOR)
Page* page = this->page();
@@ -463,7 +463,7 @@ bool Console::shouldCaptureFullStackTrace() const
#endif
}
-void Console::warn(PassOwnPtr<ScriptArguments> arguments, PassOwnPtr<ScriptCallStack> callStack)
+void Console::warn(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
{
addMessage(LogMessageType, WarningMessageLevel, arguments, callStack);
}
diff --git a/WebCore/page/Console.h b/WebCore/page/Console.h
index 92fee59..dd692a2 100644
--- a/WebCore/page/Console.h
+++ b/WebCore/page/Console.h
@@ -68,7 +68,8 @@ enum MessageType {
StartGroupCollapsedMessageType,
EndGroupMessageType,
AssertMessageType,
- UncaughtExceptionMessageType
+ UncaughtExceptionMessageType,
+ NetworkErrorMessageType
};
enum MessageLevel {
@@ -87,31 +88,31 @@ public:
void disconnectFrame();
void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL);
- void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL, PassOwnPtr<ScriptCallStack> callStack);
-
- void debug(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void error(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void info(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void log(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void warn(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void dir(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void dirxml(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void trace(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void assertCondition(bool condition, PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void count(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void markTimeline(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
+ void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack> callStack);
+
+ void debug(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void error(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void info(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void log(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void warn(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void dir(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void dirxml(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void trace(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void assertCondition(bool condition, PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void count(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void markTimeline(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
#if ENABLE(WML)
String lastWMLErrorMessage() const;
#endif
#if ENABLE(JAVASCRIPT_DEBUGGER)
const ProfilesArray& profiles() const { return m_profiles; }
- void profile(const String&, ScriptState*, PassOwnPtr<ScriptCallStack>);
- void profileEnd(const String&, ScriptState*, PassOwnPtr<ScriptCallStack>);
+ void profile(const String&, ScriptState*, PassRefPtr<ScriptCallStack>);
+ void profileEnd(const String&, ScriptState*, PassRefPtr<ScriptCallStack>);
#endif
void time(const String&);
- void timeEnd(const String&, PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void group(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
- void groupCollapsed(PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>);
+ void timeEnd(const String&, PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void group(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
+ void groupCollapsed(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
void groupEnd();
bool shouldCaptureFullStackTrace() const;
@@ -123,7 +124,7 @@ public:
private:
inline Page* page() const;
- void addMessage(MessageType, MessageLevel, PassOwnPtr<ScriptArguments>, PassOwnPtr<ScriptCallStack>, bool acceptNoArguments = false);
+ void addMessage(MessageType, MessageLevel, PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>, bool acceptNoArguments = false);
Console(Frame*);
diff --git a/WebCore/page/ContextMenuClient.h b/WebCore/page/ContextMenuClient.h
index f91536b..c9389c0 100644
--- a/WebCore/page/ContextMenuClient.h
+++ b/WebCore/page/ContextMenuClient.h
@@ -26,11 +26,12 @@
#ifndef ContextMenuClient_h
#define ContextMenuClient_h
+#include "ContextMenu.h"
#include "PlatformMenuDescription.h"
#include <wtf/Forward.h>
+#include <wtf/PassOwnPtr.h>
namespace WebCore {
- class ContextMenu;
class ContextMenuItem;
class Frame;
class HitTestResult;
@@ -41,7 +42,12 @@ namespace WebCore {
virtual ~ContextMenuClient() { }
virtual void contextMenuDestroyed() = 0;
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+ virtual PassOwnPtr<ContextMenu> customizeMenu(PassOwnPtr<ContextMenu>) = 0;
+#else
virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*) = 0;
+#endif
+
virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) = 0;
virtual void downloadURL(const KURL& url) = 0;
diff --git a/WebCore/page/ContextMenuController.cpp b/WebCore/page/ContextMenuController.cpp
index 1f71d09..65399de 100644
--- a/WebCore/page/ContextMenuController.cpp
+++ b/WebCore/page/ContextMenuController.cpp
@@ -33,6 +33,7 @@
#include "Chrome.h"
#include "ContextMenu.h"
#include "ContextMenuClient.h"
+#include "ContextMenuItem.h"
#include "ContextMenuProvider.h"
#include "Document.h"
#include "DocumentFragment.h"
@@ -50,6 +51,7 @@
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InspectorController.h"
+#include "LocalizedStrings.h"
#include "MouseEvent.h"
#include "NavigationAction.h"
#include "Node.h"
@@ -63,6 +65,10 @@
#include "TextIterator.h"
#include "WindowFeatures.h"
#include "markup.h"
+#include <wtf/unicode/Unicode.h>
+
+using namespace WTF;
+using namespace Unicode;
namespace WebCore {
@@ -90,10 +96,12 @@ void ContextMenuController::clearContextMenu()
void ContextMenuController::handleContextMenuEvent(Event* event)
{
- m_contextMenu.set(createContextMenu(event));
+ m_contextMenu = createContextMenu(event);
if (!m_contextMenu)
return;
- m_contextMenu->populate();
+
+ populate();
+
showContextMenu(event);
}
@@ -101,7 +109,7 @@ void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenu
{
m_menuProvider = menuProvider;
- m_contextMenu.set(createContextMenu(event));
+ m_contextMenu = createContextMenu(event);
if (!m_contextMenu) {
clearContextMenu();
return;
@@ -111,10 +119,11 @@ void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenu
showContextMenu(event);
}
-ContextMenu* ContextMenuController::createContextMenu(Event* event)
+PassOwnPtr<ContextMenu> ContextMenuController::createContextMenu(Event* event)
{
- if (!event->isMouseEvent())
+ if (!event->isMouseEvent())
return 0;
+
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
HitTestResult result(mouseEvent->absoluteLocation());
@@ -123,25 +132,34 @@ ContextMenu* ContextMenuController::createContextMenu(Event* event)
if (!result.innerNonSharedNode())
return 0;
- return new ContextMenu(result);
+
+ m_hitTestResult = result;
+
+ return new ContextMenu;
}
void ContextMenuController::showContextMenu(Event* event)
{
#if ENABLE(INSPECTOR)
if (m_page->inspectorController()->enabled())
- m_contextMenu->addInspectElementItem();
+ addInspectElementItem();
#endif
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+ m_contextMenu = m_client->customizeMenu(m_contextMenu.release());
+#else
PlatformMenuDescription customMenu = m_client->getCustomMenuFromDefaultItems(m_contextMenu.get());
m_contextMenu->setPlatformDescription(customMenu);
+#endif
event->setDefaultHandled();
}
static void openNewWindow(const KURL& urlToLoad, Frame* frame)
{
if (Page* oldPage = frame->page()) {
+ FrameLoadRequest request(frame->document()->securityOrigin(), ResourceRequest(urlToLoad, frame->loader()->outgoingReferrer()));
WindowFeatures features;
- if (Page* newPage = oldPage->chrome()->createWindow(frame, FrameLoadRequest(ResourceRequest(urlToLoad, frame->loader()->outgoingReferrer())), features, NavigationAction()))
+ if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, NavigationAction()))
newPage->chrome()->show();
}
}
@@ -161,54 +179,53 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
return;
}
- HitTestResult result = m_contextMenu->hitTestResult();
- Frame* frame = result.innerNonSharedNode()->document()->frame();
+ Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame();
if (!frame)
return;
switch (item->action()) {
case ContextMenuItemTagOpenLinkInNewWindow:
- openNewWindow(result.absoluteLinkURL(), frame);
+ openNewWindow(m_hitTestResult.absoluteLinkURL(), frame);
break;
case ContextMenuItemTagDownloadLinkToDisk:
// FIXME: Some day we should be able to do this from within WebCore.
- m_client->downloadURL(result.absoluteLinkURL());
+ m_client->downloadURL(m_hitTestResult.absoluteLinkURL());
break;
case ContextMenuItemTagCopyLinkToClipboard:
- frame->editor()->copyURL(result.absoluteLinkURL(), result.textContent());
+ frame->editor()->copyURL(m_hitTestResult.absoluteLinkURL(), m_hitTestResult.textContent());
break;
case ContextMenuItemTagOpenImageInNewWindow:
- openNewWindow(result.absoluteImageURL(), frame);
+ openNewWindow(m_hitTestResult.absoluteImageURL(), frame);
break;
case ContextMenuItemTagDownloadImageToDisk:
// FIXME: Some day we should be able to do this from within WebCore.
- m_client->downloadURL(result.absoluteImageURL());
+ m_client->downloadURL(m_hitTestResult.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);
+ frame->editor()->copyImage(m_hitTestResult);
break;
case ContextMenuItemTagOpenMediaInNewWindow:
- openNewWindow(result.absoluteMediaURL(), frame);
+ openNewWindow(m_hitTestResult.absoluteMediaURL(), frame);
break;
case ContextMenuItemTagCopyMediaLinkToClipboard:
- frame->editor()->copyURL(result.absoluteMediaURL(), result.textContent());
+ frame->editor()->copyURL(m_hitTestResult.absoluteMediaURL(), m_hitTestResult.textContent());
break;
case ContextMenuItemTagToggleMediaControls:
- result.toggleMediaControlsDisplay();
+ m_hitTestResult.toggleMediaControlsDisplay();
break;
case ContextMenuItemTagToggleMediaLoop:
- result.toggleMediaLoopPlayback();
+ m_hitTestResult.toggleMediaLoopPlayback();
break;
case ContextMenuItemTagEnterVideoFullscreen:
- result.enterFullscreenForVideo();
+ m_hitTestResult.enterFullscreenForVideo();
break;
case ContextMenuItemTagMediaPlayPause:
- result.toggleMediaPlayState();
+ m_hitTestResult.toggleMediaPlayState();
break;
case ContextMenuItemTagMediaMute:
- result.toggleMediaMuteState();
+ m_hitTestResult.toggleMediaMuteState();
break;
case ContextMenuItemTagOpenFrameInNewWindow: {
DocumentLoader* loader = frame->loader()->documentLoader();
@@ -272,10 +289,10 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
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, SendReferrer);
+ if (Frame* targetFrame = m_hitTestResult.targetFrame())
+ targetFrame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(m_hitTestResult.absoluteLinkURL(), frame->loader()->outgoingReferrer())), false, false, 0, 0, SendReferrer);
else
- openNewWindow(result.absoluteLinkURL(), frame);
+ openNewWindow(m_hitTestResult.absoluteLinkURL(), frame);
break;
case ContextMenuItemTagBold:
frame->editor()->command("ToggleBold").execute();
@@ -294,7 +311,7 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
ExceptionCode ec;
RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
if (!selectedRange || selectedRange->collapsed(ec)) {
- Document* document = result.innerNonSharedNode()->document();
+ Document* document = m_hitTestResult.innerNonSharedNode()->document();
selectedRange = document->createRange();
selectedRange->selectNode(document->documentElement(), ec);
}
@@ -384,13 +401,13 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
frame->editor()->toggleAutomaticSpellingCorrection();
break;
case ContextMenuItemTagChangeBack:
- frame->editor()->changeBackToReplacedString(result.replacedString());
+ frame->editor()->changeBackToReplacedString(m_hitTestResult.replacedString());
break;
#endif
#if ENABLE(INSPECTOR)
case ContextMenuItemTagInspectElement:
if (Page* page = frame->page())
- page->inspectorController()->inspect(result.innerNonSharedNode());
+ page->inspectorController()->inspect(m_hitTestResult.innerNonSharedNode());
break;
#endif
default:
@@ -398,6 +415,829 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
}
}
+void ContextMenuController::appendItem(ContextMenuItem& menuItem, ContextMenu* parentMenu)
+{
+ checkOrEnableIfNeeded(menuItem);
+ if (parentMenu)
+ parentMenu->appendItem(menuItem);
+}
+
+static PassOwnPtr<ContextMenuItem> separatorItem()
+{
+ return new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String());
+}
+
+void ContextMenuController::createAndAppendFontSubMenu(ContextMenuItem& fontMenuItem)
+{
+ ContextMenu fontMenu;
+
+#if PLATFORM(MAC)
+ ContextMenuItem showFonts(ActionType, ContextMenuItemTagShowFonts, contextMenuItemTagShowFonts());
+#endif
+ ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold());
+ ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic());
+ ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline());
+ ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline());
+#if PLATFORM(MAC)
+ ContextMenuItem styles(ActionType, ContextMenuItemTagStyles, contextMenuItemTagStyles());
+ ContextMenuItem showColors(ActionType, ContextMenuItemTagShowColors, contextMenuItemTagShowColors());
+#endif
+
+#if PLATFORM(MAC)
+ appendItem(showFonts, &fontMenu);
+#endif
+ appendItem(bold, &fontMenu);
+ appendItem(italic, &fontMenu);
+ appendItem(underline, &fontMenu);
+ appendItem(outline, &fontMenu);
+#if PLATFORM(MAC)
+ appendItem(styles, &fontMenu);
+ appendItem(*separatorItem(), &fontMenu);
+ appendItem(showColors, &fontMenu);
+#endif
+
+ fontMenuItem.setSubMenu(&fontMenu);
+}
+
+#if !defined(BUILDING_ON_TIGER)
+
+#if !PLATFORM(GTK)
+
+void ContextMenuController::createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem& spellingAndGrammarMenuItem)
+{
+ ContextMenu spellingAndGrammarMenu;
+
+ ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel,
+ contextMenuItemTagShowSpellingPanel(true));
+ ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling,
+ contextMenuItemTagCheckSpelling());
+ ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping,
+ contextMenuItemTagCheckSpellingWhileTyping());
+ ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling,
+ contextMenuItemTagCheckGrammarWithSpelling());
+#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
+ ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically,
+ contextMenuItemTagCorrectSpellingAutomatically());
+#endif
+
+ appendItem(showSpellingPanel, &spellingAndGrammarMenu);
+ appendItem(checkSpelling, &spellingAndGrammarMenu);
+#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
+ appendItem(*separatorItem(), &spellingAndGrammarMenu);
+#endif
+ appendItem(checkAsYouType, &spellingAndGrammarMenu);
+ appendItem(grammarWithSpelling, &spellingAndGrammarMenu);
+#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
+ appendItem(correctSpelling, &spellingAndGrammarMenu);
+#endif
+
+ spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu);
+}
+
+#endif // !PLATFORM(GTK)
+
+#else
+
+void ContextMenuController::createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem& spellingAndGrammarMenuItem)
+{
+ ContextMenu spellingMenu;
+
+ ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel,
+ contextMenuItemTagShowSpellingPanel(true));
+ ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling,
+ contextMenuItemTagCheckSpelling());
+ ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping,
+ contextMenuItemTagCheckSpellingWhileTyping());
+
+ appendItem(showSpellingPanel, &spellingMenu);
+ appendItem(checkSpelling, &spellingMenu);
+ appendItem(checkAsYouType, &spellingMenu);
+
+ spellingMenuItem.setSubMenu(&spellingMenu);
+}
+
+#endif
+
+#if PLATFORM(MAC)
+
+void ContextMenuController::createAndAppendSpeechSubMenu(ContextMenuItem& speechMenuItem)
+{
+ ContextMenu speechMenu;
+
+ ContextMenuItem start(ActionType, ContextMenuItemTagStartSpeaking, contextMenuItemTagStartSpeaking());
+ ContextMenuItem stop(ActionType, ContextMenuItemTagStopSpeaking, contextMenuItemTagStopSpeaking());
+
+ appendItem(start, &speechMenu);
+ appendItem(stop, &speechMenu);
+
+ speechMenuItem.setSubMenu(&speechMenu);
+}
+
+#endif
+
+#if !PLATFORM(GTK)
+
+void ContextMenuController::createAndAppendWritingDirectionSubMenu(ContextMenuItem& writingDirectionMenuItem)
+{
+ ContextMenu writingDirectionMenu;
+
+ ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection,
+ contextMenuItemTagDefaultDirection());
+ ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight());
+ ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft());
+
+ appendItem(defaultItem, &writingDirectionMenu);
+ appendItem(ltr, &writingDirectionMenu);
+ appendItem(rtl, &writingDirectionMenu);
+
+ writingDirectionMenuItem.setSubMenu(&writingDirectionMenu);
+}
+
+void ContextMenuController::createAndAppendTextDirectionSubMenu(ContextMenuItem& textDirectionMenuItem)
+{
+ ContextMenu textDirectionMenu;
+
+ ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection());
+ ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight());
+ ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft());
+
+ appendItem(defaultItem, &textDirectionMenu);
+ appendItem(ltr, &textDirectionMenu);
+ appendItem(rtl, &textDirectionMenu);
+
+ textDirectionMenuItem.setSubMenu(&textDirectionMenu);
+}
+
+#endif
+
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+void ContextMenuController::createAndAppendSubstitutionsSubMenu(ContextMenuItem& substitutionsMenuItem)
+{
+ ContextMenu substitutionsMenu;
+
+ ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true));
+ ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste());
+ ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes());
+ ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes());
+ ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks());
+ ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement());
+
+ appendItem(showSubstitutions, &substitutionsMenu);
+ appendItem(*separatorItem(), &substitutionsMenu);
+ appendItem(smartCopyPaste, &substitutionsMenu);
+ appendItem(smartQuotes, &substitutionsMenu);
+ appendItem(smartDashes, &substitutionsMenu);
+ appendItem(smartLinks, &substitutionsMenu);
+ appendItem(textReplacement, &substitutionsMenu);
+
+ substitutionsMenuItem.setSubMenu(&substitutionsMenu);
+}
+
+void ContextMenuController::createAndAppendTransformationsSubMenu(ContextMenuItem& transformationsMenuItem)
+{
+ ContextMenu transformationsMenu;
+
+ ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase());
+ ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase());
+ ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize());
+
+ appendItem(makeUpperCase, &transformationsMenu);
+ appendItem(makeLowerCase, &transformationsMenu);
+ appendItem(capitalize, &transformationsMenu);
+
+ transformationsMenuItem.setSubMenu(&transformationsMenu);
+}
+
+#endif
+
+static bool selectionContainsPossibleWord(Frame* frame)
+{
+ // Current algorithm: look for a character that's not just a separator.
+ for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) {
+ int length = it.length();
+ const UChar* characters = it.characters();
+ for (int i = 0; i < length; ++i)
+ if (!(category(characters[i]) & (Separator_Space | Separator_Line | Separator_Paragraph)))
+ return true;
+ }
+ return false;
+}
+
+void ContextMenuController::populate()
+{
+ ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink());
+ ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow,
+ contextMenuItemTagOpenLinkInNewWindow());
+ ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk,
+ contextMenuItemTagDownloadLinkToDisk());
+ ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard,
+ contextMenuItemTagCopyLinkToClipboard());
+ ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow,
+ contextMenuItemTagOpenImageInNewWindow());
+ ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk,
+ contextMenuItemTagDownloadImageToDisk());
+ ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard,
+ contextMenuItemTagCopyImageToClipboard());
+ ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String());
+ ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard,
+ String());
+ ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause,
+ contextMenuItemTagMediaPlay());
+ ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute,
+ contextMenuItemTagMediaMute());
+ ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls,
+ contextMenuItemTagToggleMediaControls());
+ ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop,
+ contextMenuItemTagToggleMediaLoop());
+ ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen,
+ contextMenuItemTagEnterVideoFullscreen());
+#if PLATFORM(MAC)
+ ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight,
+ contextMenuItemTagSearchInSpotlight());
+ ContextMenuItem LookInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary,
+ contextMenuItemTagLookUpInDictionary());
+#endif
+#if !PLATFORM(GTK)
+ ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb());
+#endif
+ ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy());
+ ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack());
+ ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward());
+ ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop());
+ ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload());
+ ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow,
+ contextMenuItemTagOpenFrameInNewWindow());
+ ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound,
+ contextMenuItemTagNoGuessesFound());
+ ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling,
+ contextMenuItemTagIgnoreSpelling());
+ ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling,
+ contextMenuItemTagLearnSpelling());
+ ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar,
+ contextMenuItemTagIgnoreGrammar());
+ ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut());
+ ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste());
+#if PLATFORM(GTK)
+ ContextMenuItem DeleteItem(ActionType, ContextMenuItemTagDelete, contextMenuItemTagDelete());
+ ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll());
+#endif
+
+ Node* node = m_hitTestResult.innerNonSharedNode();
+ if (!node)
+ return;
+#if PLATFORM(GTK)
+ if (!m_hitTestResult.isContentEditable() && (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()))
+ return;
+#endif
+ Frame* frame = node->document()->frame();
+ if (!frame)
+ return;
+
+ if (!m_hitTestResult.isContentEditable()) {
+ FrameLoader* loader = frame->loader();
+ KURL linkURL = m_hitTestResult.absoluteLinkURL();
+ if (!linkURL.isEmpty()) {
+ if (loader->canHandleRequest(ResourceRequest(linkURL))) {
+ appendItem(OpenLinkItem, m_contextMenu.get());
+ appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
+ appendItem(DownloadFileItem, m_contextMenu.get());
+ }
+ appendItem(CopyLinkItem, m_contextMenu.get());
+ }
+
+ KURL imageURL = m_hitTestResult.absoluteImageURL();
+ if (!imageURL.isEmpty()) {
+ if (!linkURL.isEmpty())
+ appendItem(*separatorItem(), m_contextMenu.get());
+
+ appendItem(OpenImageInNewWindowItem, m_contextMenu.get());
+ appendItem(DownloadImageItem, m_contextMenu.get());
+ if (imageURL.isLocalFile() || m_hitTestResult.image())
+ appendItem(CopyImageItem, m_contextMenu.get());
+ }
+
+ KURL mediaURL = m_hitTestResult.absoluteMediaURL();
+ if (!mediaURL.isEmpty()) {
+ if (!linkURL.isEmpty() || !imageURL.isEmpty())
+ appendItem(*separatorItem(), m_contextMenu.get());
+
+ appendItem(MediaPlayPause, m_contextMenu.get());
+ appendItem(MediaMute, m_contextMenu.get());
+ appendItem(ToggleMediaControls, m_contextMenu.get());
+ appendItem(ToggleMediaLoop, m_contextMenu.get());
+ appendItem(EnterVideoFullscreen, m_contextMenu.get());
+
+ appendItem(*separatorItem(), m_contextMenu.get());
+ appendItem(CopyMediaLinkItem, m_contextMenu.get());
+ appendItem(OpenMediaInNewWindowItem, m_contextMenu.get());
+ }
+
+ if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) {
+ if (m_hitTestResult.isSelected()) {
+ if (selectionContainsPossibleWord(frame)) {
+#if PLATFORM(MAC)
+ appendItem(SearchSpotlightItem, m_contextMenu.get());
+#endif
+#if !PLATFORM(GTK)
+ appendItem(SearchWebItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+#endif
+#if PLATFORM(MAC)
+ appendItem(LookInDictionaryItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+#endif
+ }
+ appendItem(CopyItem, m_contextMenu.get());
+#if PLATFORM(MAC)
+ appendItem(*separatorItem(), m_contextMenu.get());
+ ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
+ createAndAppendSpeechSubMenu(SpeechMenuItem);
+ appendItem(SpeechMenuItem, m_contextMenu.get());
+#endif
+ } else {
+#if ENABLE(INSPECTOR)
+ if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) {
+#endif
+ if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1))
+ appendItem(BackItem, m_contextMenu.get());
+
+ if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1))
+ appendItem(ForwardItem, m_contextMenu.get());
+
+ // use isLoadingInAPISense rather than isLoading because Stop/Reload are
+ // intended to match WebKit's API, not WebCore's internal notion of loading status
+ if (loader->documentLoader()->isLoadingInAPISense())
+ appendItem(StopItem, m_contextMenu.get());
+ else
+ appendItem(ReloadItem, m_contextMenu.get());
+#if ENABLE(INSPECTOR)
+ }
+#endif
+
+ if (frame->page() && frame != frame->page()->mainFrame())
+ appendItem(OpenFrameItem, m_contextMenu.get());
+ }
+ }
+ } else { // Make an editing context menu
+ SelectionController* selection = frame->selection();
+ bool inPasswordField = selection->isInPasswordField();
+ bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node);
+
+ if (!inPasswordField && spellCheckingEnabled) {
+ // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
+ // is never considered a misspelling and bad grammar at the same time)
+ bool misspelling;
+ bool badGrammar;
+ Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
+ if (misspelling || badGrammar) {
+ size_t size = guesses.size();
+ if (size == 0) {
+ // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
+ // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
+ if (misspelling) {
+ appendItem(NoGuessesItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+ }
+ } else {
+ for (unsigned i = 0; i < size; i++) {
+ const String &guess = guesses[i];
+ if (!guess.isEmpty()) {
+ ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
+ appendItem(item, m_contextMenu.get());
+ }
+ }
+ appendItem(*separatorItem(), m_contextMenu.get());
+ }
+
+ if (misspelling) {
+ appendItem(IgnoreSpellingItem, m_contextMenu.get());
+ appendItem(LearnSpellingItem, m_contextMenu.get());
+ } else
+ appendItem(IgnoreGrammarItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ } else {
+ // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
+ String replacedString = m_hitTestResult.replacedString();
+ if (!replacedString.isEmpty()) {
+ ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
+ appendItem(item, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+ }
+#endif
+ }
+ }
+
+ FrameLoader* loader = frame->loader();
+ KURL linkURL = m_hitTestResult.absoluteLinkURL();
+ if (!linkURL.isEmpty()) {
+ if (loader->canHandleRequest(ResourceRequest(linkURL))) {
+ appendItem(OpenLinkItem, m_contextMenu.get());
+ appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
+ appendItem(DownloadFileItem, m_contextMenu.get());
+ }
+ appendItem(CopyLinkItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+ }
+
+ if (m_hitTestResult.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) {
+#if PLATFORM(MAC)
+ appendItem(SearchSpotlightItem, m_contextMenu.get());
+#endif
+#if !PLATFORM(GTK)
+ appendItem(SearchWebItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+#endif
+
+#if PLATFORM(MAC)
+ appendItem(LookInDictionaryItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+#endif
+ }
+
+ appendItem(CutItem, m_contextMenu.get());
+ appendItem(CopyItem, m_contextMenu.get());
+ appendItem(PasteItem, m_contextMenu.get());
+#if PLATFORM(GTK)
+ appendItem(DeleteItem, m_contextMenu.get());
+ appendItem(*separatorItem(), m_contextMenu.get());
+ appendItem(SelectAllItem, m_contextMenu.get());
+#endif
+
+ if (!inPasswordField) {
+ appendItem(*separatorItem(), m_contextMenu.get());
+#ifndef BUILDING_ON_TIGER
+#if !PLATFORM(GTK)
+ ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu,
+ contextMenuItemTagSpellingMenu());
+ createAndAppendSpellingAndGrammarSubMenu(SpellingAndGrammarMenuItem);
+ appendItem(SpellingAndGrammarMenuItem, m_contextMenu.get());
+#endif
+#else
+ ContextMenuItem SpellingMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu,
+ contextMenuItemTagSpellingMenu());
+ createAndAppendSpellingSubMenu(SpellingMenuItem);
+ appendItem(SpellingMenuItem, m_contextMenu.get());
+#endif
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu,
+ contextMenuItemTagSubstitutionsMenu());
+ createAndAppendSubstitutionsSubMenu(substitutionsMenuItem);
+ appendItem(substitutionsMenuItem, m_contextMenu.get());
+ ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu,
+ contextMenuItemTagTransformationsMenu());
+ createAndAppendTransformationsSubMenu(transformationsMenuItem);
+ appendItem(transformationsMenuItem, m_contextMenu.get());
+#endif
+#if PLATFORM(GTK)
+ bool shouldShowFontMenu = frame->editor()->canEditRichly();
+#else
+ bool shouldShowFontMenu = true;
+#endif
+ if (shouldShowFontMenu) {
+ ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu,
+ contextMenuItemTagFontMenu());
+ createAndAppendFontSubMenu(FontMenuItem);
+ appendItem(FontMenuItem, m_contextMenu.get());
+ }
+#if PLATFORM(MAC)
+ ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
+ createAndAppendSpeechSubMenu(SpeechMenuItem);
+ appendItem(SpeechMenuItem, m_contextMenu.get());
+#endif
+#if !PLATFORM(GTK)
+ ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu,
+ contextMenuItemTagWritingDirectionMenu());
+ createAndAppendWritingDirectionSubMenu(WritingDirectionMenuItem);
+ appendItem(WritingDirectionMenuItem, m_contextMenu.get());
+ if (Page* page = frame->page()) {
+ if (Settings* settings = page->settings()) {
+ bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded
+ || (settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection());
+ if (includeTextDirectionSubmenu) {
+ ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu,
+ contextMenuItemTagTextDirectionMenu());
+ createAndAppendTextDirectionSubMenu(TextDirectionMenuItem);
+ appendItem(TextDirectionMenuItem, m_contextMenu.get());
+ }
+ }
+ }
+#endif
+ }
+ }
+}
+
+#if ENABLE(INSPECTOR)
+void ContextMenuController::addInspectElementItem()
+{
+ Node* node = m_hitTestResult.innerNonSharedNode();
+ if (!node)
+ return;
+
+ Frame* frame = node->document()->frame();
+ if (!frame)
+ return;
+
+ Page* page = frame->page();
+ if (!page)
+ return;
+
+ if (!page->inspectorController())
+ return;
+
+ ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement());
+ appendItem(*separatorItem(), m_contextMenu.get());
+ appendItem(InspectElementItem, m_contextMenu.get());
+}
+#endif // ENABLE(INSPECTOR)
+
+void ContextMenuController::checkOrEnableIfNeeded(ContextMenuItem& item) const
+{
+ if (item.type() == SeparatorType)
+ return;
+
+ Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame();
+ if (!frame)
+ return;
+
+ // Custom items already have proper checked and enabled values.
+ if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag)
+ return;
+
+ bool shouldEnable = true;
+ bool shouldCheck = false;
+
+ switch (item.action()) {
+ case ContextMenuItemTagCheckSpelling:
+ shouldEnable = frame->editor()->canEdit();
+ break;
+ case ContextMenuItemTagDefaultDirection:
+ shouldCheck = false;
+ shouldEnable = false;
+ break;
+ case ContextMenuItemTagLeftToRight:
+ case ContextMenuItemTagRightToLeft: {
+ ExceptionCode ec = 0;
+ RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
+ String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl";
+ style->setProperty(CSSPropertyDirection, direction, false, ec);
+ shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
+ shouldEnable = true;
+ break;
+ }
+ case ContextMenuItemTagTextDirectionDefault: {
+ Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural");
+ shouldCheck = command.state() == TrueTriState;
+ shouldEnable = command.isEnabled();
+ break;
+ }
+ case ContextMenuItemTagTextDirectionLeftToRight: {
+ Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight");
+ shouldCheck = command.state() == TrueTriState;
+ shouldEnable = command.isEnabled();
+ break;
+ }
+ case ContextMenuItemTagTextDirectionRightToLeft: {
+ Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft");
+ shouldCheck = command.state() == TrueTriState;
+ shouldEnable = command.isEnabled();
+ break;
+ }
+ case ContextMenuItemTagCopy:
+ shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy();
+ break;
+ case ContextMenuItemTagCut:
+ shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut();
+ break;
+ case ContextMenuItemTagIgnoreSpelling:
+ case ContextMenuItemTagLearnSpelling:
+ shouldEnable = frame->selection()->isRange();
+ break;
+ case ContextMenuItemTagPaste:
+ shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste();
+ break;
+#if PLATFORM(GTK)
+ case ContextMenuItemTagDelete:
+ shouldEnable = frame->editor()->canDelete();
+ break;
+ case ContextMenuItemTagSelectAll:
+ case ContextMenuItemTagInputMethods:
+ case ContextMenuItemTagUnicode:
+ shouldEnable = true;
+ break;
+#endif
+ case ContextMenuItemTagUnderline: {
+ ExceptionCode ec = 0;
+ RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
+ style->setProperty(CSSPropertyWebkitTextDecorationsInEffect, "underline", false, ec);
+ shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
+ shouldEnable = frame->editor()->canEditRichly();
+ break;
+ }
+ case ContextMenuItemTagLookUpInDictionary:
+ shouldEnable = frame->selection()->isRange();
+ break;
+ case ContextMenuItemTagCheckGrammarWithSpelling:
+#ifndef BUILDING_ON_TIGER
+ if (frame->editor()->isGrammarCheckingEnabled())
+ shouldCheck = true;
+ shouldEnable = true;
+#endif
+ break;
+ case ContextMenuItemTagItalic: {
+ ExceptionCode ec = 0;
+ RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
+ style->setProperty(CSSPropertyFontStyle, "italic", false, ec);
+ shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
+ shouldEnable = frame->editor()->canEditRichly();
+ break;
+ }
+ case ContextMenuItemTagBold: {
+ ExceptionCode ec = 0;
+ RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
+ style->setProperty(CSSPropertyFontWeight, "bold", false, ec);
+ shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
+ shouldEnable = frame->editor()->canEditRichly();
+ break;
+ }
+ case ContextMenuItemTagOutline:
+ shouldEnable = false;
+ break;
+ case ContextMenuItemTagShowSpellingPanel:
+#ifndef BUILDING_ON_TIGER
+ if (frame->editor()->spellingPanelIsShowing())
+ item.setTitle(contextMenuItemTagShowSpellingPanel(false));
+ else
+ item.setTitle(contextMenuItemTagShowSpellingPanel(true));
+#endif
+ shouldEnable = frame->editor()->canEdit();
+ break;
+ case ContextMenuItemTagNoGuessesFound:
+ shouldEnable = false;
+ break;
+ case ContextMenuItemTagCheckSpellingWhileTyping:
+ shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled();
+ break;
+#if PLATFORM(MAC)
+ case ContextMenuItemTagSubstitutionsMenu:
+ case ContextMenuItemTagTransformationsMenu:
+ break;
+ case ContextMenuItemTagShowSubstitutions:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ if (frame->editor()->substitutionsPanelIsShowing())
+ item.setTitle(contextMenuItemTagShowSubstitutions(false));
+ else
+ item.setTitle(contextMenuItemTagShowSubstitutions(true));
+ shouldEnable = frame->editor()->canEdit();
+#endif
+ break;
+ case ContextMenuItemTagMakeUpperCase:
+ case ContextMenuItemTagMakeLowerCase:
+ case ContextMenuItemTagCapitalize:
+ case ContextMenuItemTagChangeBack:
+ shouldEnable = frame->editor()->canEdit();
+ break;
+ case ContextMenuItemTagCorrectSpellingAutomatically:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticSpellingCorrectionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartCopyPaste:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->smartInsertDeleteEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartQuotes:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticQuoteSubstitutionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartDashes:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticDashSubstitutionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagSmartLinks:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticLinkDetectionEnabled();
+#endif
+ break;
+ case ContextMenuItemTagTextReplacement:
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ shouldCheck = frame->editor()->isAutomaticTextReplacementEnabled();
+#endif
+ break;
+ case ContextMenuItemTagStopSpeaking:
+ shouldEnable = client() && client()->isSpeaking();
+ break;
+#else // PLATFORM(MAC) ends here
+ case ContextMenuItemTagStopSpeaking:
+ break;
+#endif
+#if PLATFORM(GTK)
+ case ContextMenuItemTagGoBack:
+ shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(-1);
+ break;
+ case ContextMenuItemTagGoForward:
+ shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(1);
+ break;
+ case ContextMenuItemTagStop:
+ shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense();
+ break;
+ case ContextMenuItemTagReload:
+ shouldEnable = !frame->loader()->documentLoader()->isLoadingInAPISense();
+ break;
+ case ContextMenuItemTagFontMenu:
+ shouldEnable = frame->editor()->canEditRichly();
+ break;
+#else
+ case ContextMenuItemTagGoBack:
+ case ContextMenuItemTagGoForward:
+ case ContextMenuItemTagStop:
+ case ContextMenuItemTagReload:
+ case ContextMenuItemTagFontMenu:
+#endif
+ case ContextMenuItemTagNoAction:
+ case ContextMenuItemTagOpenLinkInNewWindow:
+ case ContextMenuItemTagDownloadLinkToDisk:
+ case ContextMenuItemTagCopyLinkToClipboard:
+ case ContextMenuItemTagOpenImageInNewWindow:
+ case ContextMenuItemTagDownloadImageToDisk:
+ case ContextMenuItemTagCopyImageToClipboard:
+ break;
+ case ContextMenuItemTagOpenMediaInNewWindow:
+ if (m_hitTestResult.mediaIsVideo())
+ item.setTitle(contextMenuItemTagOpenVideoInNewWindow());
+ else
+ item.setTitle(contextMenuItemTagOpenAudioInNewWindow());
+ break;
+ case ContextMenuItemTagCopyMediaLinkToClipboard:
+ if (m_hitTestResult.mediaIsVideo())
+ item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard());
+ else
+ item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard());
+ break;
+ case ContextMenuItemTagToggleMediaControls:
+ shouldCheck = m_hitTestResult.mediaControlsEnabled();
+ break;
+ case ContextMenuItemTagToggleMediaLoop:
+ shouldCheck = m_hitTestResult.mediaLoopEnabled();
+ break;
+ case ContextMenuItemTagEnterVideoFullscreen:
+ shouldEnable = m_hitTestResult.mediaSupportsFullscreen();
+ break;
+ case ContextMenuItemTagOpenFrameInNewWindow:
+ case ContextMenuItemTagSpellingGuess:
+ case ContextMenuItemTagOther:
+ case ContextMenuItemTagSearchInSpotlight:
+ case ContextMenuItemTagSearchWeb:
+ case ContextMenuItemTagOpenWithDefaultApplication:
+ case ContextMenuItemPDFActualSize:
+ case ContextMenuItemPDFZoomIn:
+ case ContextMenuItemPDFZoomOut:
+ case ContextMenuItemPDFAutoSize:
+ case ContextMenuItemPDFSinglePage:
+ case ContextMenuItemPDFFacingPages:
+ case ContextMenuItemPDFContinuous:
+ case ContextMenuItemPDFNextPage:
+ case ContextMenuItemPDFPreviousPage:
+ case ContextMenuItemTagOpenLink:
+ case ContextMenuItemTagIgnoreGrammar:
+ case ContextMenuItemTagSpellingMenu:
+ case ContextMenuItemTagShowFonts:
+ case ContextMenuItemTagStyles:
+ case ContextMenuItemTagShowColors:
+ case ContextMenuItemTagSpeechMenu:
+ case ContextMenuItemTagStartSpeaking:
+ case ContextMenuItemTagWritingDirectionMenu:
+ case ContextMenuItemTagTextDirectionMenu:
+ case ContextMenuItemTagPDFSinglePageScrolling:
+ case ContextMenuItemTagPDFFacingPagesScrolling:
+#if ENABLE(INSPECTOR)
+ case ContextMenuItemTagInspectElement:
+#endif
+ case ContextMenuItemBaseCustomTag:
+ case ContextMenuItemCustomTagNoAction:
+ case ContextMenuItemLastCustomTag:
+ case ContextMenuItemBaseApplicationTag:
+ break;
+ case ContextMenuItemTagMediaPlayPause:
+ if (m_hitTestResult.mediaPlaying())
+ item.setTitle(contextMenuItemTagMediaPause());
+ else
+ item.setTitle(contextMenuItemTagMediaPlay());
+ break;
+ case ContextMenuItemTagMediaMute:
+ shouldEnable = m_hitTestResult.mediaHasAudio();
+ shouldCheck = shouldEnable && m_hitTestResult.mediaMuted();
+ break;
+ }
+
+ item.setChecked(shouldCheck);
+ item.setEnabled(shouldEnable);
+}
+
} // namespace WebCore
#endif // ENABLE(CONTEXT_MENUS)
diff --git a/WebCore/page/ContextMenuController.h b/WebCore/page/ContextMenuController.h
index 833b909..ab92796 100644
--- a/WebCore/page/ContextMenuController.h
+++ b/WebCore/page/ContextMenuController.h
@@ -26,6 +26,7 @@
#ifndef ContextMenuController_h
#define ContextMenuController_h
+#include "HitTestResult.h"
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>
@@ -45,7 +46,7 @@ namespace WebCore {
ContextMenuController(Page*, ContextMenuClient*);
~ContextMenuController();
- ContextMenuClient* client() { return m_client; }
+ ContextMenuClient* client() const { return m_client; }
ContextMenu* contextMenu() const { return m_contextMenu.get(); }
void clearContextMenu();
@@ -53,16 +54,35 @@ namespace WebCore {
void handleContextMenuEvent(Event*);
void showContextMenu(Event*, PassRefPtr<ContextMenuProvider>);
+ void populate();
void contextMenuItemSelected(ContextMenuItem*);
+ void addInspectElementItem();
+
+ void checkOrEnableIfNeeded(ContextMenuItem&) const;
+
+ void setHitTestResult(const HitTestResult& result) { m_hitTestResult = result; }
+ const HitTestResult& hitTestResult() { return m_hitTestResult; }
private:
- ContextMenu* createContextMenu(Event*);
+ PassOwnPtr<ContextMenu> createContextMenu(Event*);
void showContextMenu(Event*);
+
+ void appendItem(ContextMenuItem&, ContextMenu* parentMenu);
+
+ void createAndAppendFontSubMenu(ContextMenuItem&);
+ void createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem&);
+ void createAndAppendSpellingSubMenu(ContextMenuItem&);
+ void createAndAppendSpeechSubMenu(ContextMenuItem& );
+ void createAndAppendWritingDirectionSubMenu(ContextMenuItem&);
+ void createAndAppendTextDirectionSubMenu(ContextMenuItem&);
+ void createAndAppendSubstitutionsSubMenu(ContextMenuItem&);
+ void createAndAppendTransformationsSubMenu(ContextMenuItem&);
Page* m_page;
ContextMenuClient* m_client;
OwnPtr<ContextMenu> m_contextMenu;
RefPtr<ContextMenuProvider> m_menuProvider;
+ HitTestResult m_hitTestResult;
};
}
diff --git a/WebCore/page/Coordinates.h b/WebCore/page/Coordinates.h
index 50003ce..6365548 100644
--- a/WebCore/page/Coordinates.h
+++ b/WebCore/page/Coordinates.h
@@ -32,12 +32,15 @@
namespace WebCore {
-typedef int ExceptionCode;
-
class Coordinates : public RefCounted<Coordinates> {
public:
static PassRefPtr<Coordinates> create(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new Coordinates(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); }
-
+
+ PassRefPtr<Coordinates> threadSafeCopy() const
+ {
+ return Coordinates::create(m_latitude, m_longitude, m_canProvideAltitude, m_altitude, m_accuracy, m_canProvideAltitudeAccuracy, m_altitudeAccuracy, m_canProvideHeading, m_heading, m_canProvideSpeed, m_speed);
+ }
+
double latitude() const { return m_latitude; }
double longitude() const { return m_longitude; }
double altitude() const { return m_altitude; }
diff --git a/WebCore/page/DOMSelection.cpp b/WebCore/page/DOMSelection.cpp
index 03172b5..944f13d 100644
--- a/WebCore/page/DOMSelection.cpp
+++ b/WebCore/page/DOMSelection.cpp
@@ -100,7 +100,7 @@ Node* DOMSelection::anchorNode() const
if (!m_frame)
return 0;
if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
- return shadowAncestor->parentNode();
+ return shadowAncestor->parentNodeGuaranteedHostFree();
return anchorPosition(visibleSelection()).node();
}
@@ -118,7 +118,7 @@ Node* DOMSelection::focusNode() const
if (!m_frame)
return 0;
if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
- return shadowAncestor->parentNode();
+ return shadowAncestor->parentNodeGuaranteedHostFree();
return focusPosition(visibleSelection()).node();
}
@@ -136,7 +136,7 @@ Node* DOMSelection::baseNode() const
if (!m_frame)
return 0;
if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
- return shadowAncestor->parentNode();
+ return shadowAncestor->parentNodeGuaranteedHostFree();
return basePosition(visibleSelection()).node();
}
@@ -154,7 +154,7 @@ Node* DOMSelection::extentNode() const
if (!m_frame)
return 0;
if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
- return shadowAncestor->parentNode();
+ return shadowAncestor->parentNodeGuaranteedHostFree();
return extentPosition(visibleSelection()).node();
}
@@ -370,7 +370,7 @@ PassRefPtr<Range> DOMSelection::getRangeAt(int index, ExceptionCode& ec)
ASSERT(rangeCount() == 1);
if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) {
- ContainerNode* container = shadowAncestor->parentNode();
+ ContainerNode* container = shadowAncestor->parentNodeGuaranteedHostFree();
int offset = shadowAncestor->nodeIndex();
return Range::create(shadowAncestor->document(), container, offset, container, offset);
}
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp
index 7ea69b5..b609508 100644
--- a/WebCore/page/DOMWindow.cpp
+++ b/WebCore/page/DOMWindow.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
*
* Redistribution and use in source and binary forms, with or without
@@ -29,15 +29,14 @@
#include "AbstractDatabase.h"
#include "BackForwardController.h"
-#include "Base64.h"
#include "BarInfo.h"
+#include "Base64.h"
#include "BeforeUnloadEvent.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSRuleList.h"
#include "CSSStyleSelector.h"
#include "Chrome.h"
#include "Console.h"
-#include "DocumentLoader.h"
#include "DOMApplicationCache.h"
#include "DOMSelection.h"
#include "DOMSettableTokenList.h"
@@ -48,8 +47,8 @@
#include "DatabaseCallback.h"
#include "DeviceMotionController.h"
#include "DeviceOrientationController.h"
-#include "PageTransitionEvent.h"
#include "Document.h"
+#include "DocumentLoader.h"
#include "Element.h"
#include "EventException.h"
#include "EventListener.h"
@@ -57,6 +56,7 @@
#include "ExceptionCode.h"
#include "FloatRect.h"
#include "Frame.h"
+#include "FrameLoadRequest.h"
#include "FrameLoader.h"
#include "FrameTree.h"
#include "FrameView.h"
@@ -75,6 +75,7 @@
#include "NotificationCenter.h"
#include "Page.h"
#include "PageGroup.h"
+#include "PageTransitionEvent.h"
#include "Performance.h"
#include "PlatformScreen.h"
#include "PlatformString.h"
@@ -88,6 +89,7 @@
#include "StyleMedia.h"
#include "SuddenTermination.h"
#include "WebKitPoint.h"
+#include "WindowFeatures.h"
#include <algorithm>
#include <wtf/CurrentTime.h>
#include <wtf/MathExtras.h>
@@ -340,40 +342,28 @@ void DOMWindow::adjustWindowRect(const FloatRect& screen, FloatRect& window, con
window.setY(max(screen.y(), min(window.y(), screen.bottom() - window.height())));
}
-void DOMWindow::parseModalDialogFeatures(const String& featuresArg, HashMap<String, String>& map)
-{
- Vector<String> features;
- featuresArg.split(';', features);
- Vector<String>::const_iterator end = features.end();
- for (Vector<String>::const_iterator it = features.begin(); it != end; ++it) {
- String s = *it;
- size_t pos = s.find('=');
- size_t colonPos = s.find(':');
- if (pos != notFound && colonPos != notFound)
- continue; // ignore any strings that have both = and :
- if (pos == notFound)
- pos = colonPos;
- if (pos == notFound) {
- // null string for value means key without value
- map.set(s.stripWhiteSpace().lower(), String());
- } else {
- String key = s.left(pos).stripWhiteSpace().lower();
- String val = s.substring(pos + 1).stripWhiteSpace().lower();
- size_t spacePos = val.find(' ');
- if (spacePos != notFound)
- val = val.left(spacePos);
- map.set(key, val);
- }
- }
+// FIXME: We can remove this function once V8 showModalDialog is changed to use DOMWindow.
+void DOMWindow::parseModalDialogFeatures(const String& string, HashMap<String, String>& map)
+{
+ WindowFeatures::parseDialogFeatures(string, map);
}
-bool DOMWindow::allowPopUp(Frame* activeFrame)
+bool DOMWindow::allowPopUp(Frame* firstFrame)
{
- ASSERT(activeFrame);
- Settings* settings = activeFrame->settings();
+ ASSERT(firstFrame);
+
+ if (ScriptController::processingUserGesture())
+ return true;
+
+ Settings* settings = firstFrame->settings();
return settings && settings->javaScriptCanOpenWindowsAutomatically();
}
+bool DOMWindow::allowPopUp()
+{
+ return m_frame && allowPopUp(m_frame);
+}
+
bool DOMWindow::canShowModalDialog(const Frame* frame)
{
if (!frame)
@@ -1644,6 +1634,7 @@ void DOMWindow::revokeObjectURL(const String& blobURLString)
}
#endif
+<<<<<<< HEAD
#if ENABLE(DOM_STORAGE) && defined(ANDROID)
void DOMWindow::clearDOMStorage()
{
@@ -1656,5 +1647,212 @@ void DOMWindow::clearDOMStorage()
m_localStorage = 0;
}
#endif
+=======
+void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow)
+{
+ Frame* activeFrame = activeWindow->frame();
+ if (!activeFrame)
+ return;
+
+ if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
+ return;
+
+ Frame* firstFrame = firstWindow->frame();
+ if (!firstFrame)
+ return;
+
+ KURL completedURL = firstFrame->document()->completeURL(urlString);
+ if (completedURL.isNull())
+ return;
+
+ if (isInsecureScriptAccess(activeWindow, urlString))
+ return;
+
+ // We want a new history item if we are processing a user gesture.
+ m_frame->navigationScheduler()->scheduleLocationChange(activeFrame->document()->securityOrigin(),
+ completedURL, activeFrame->loader()->outgoingReferrer(),
+ !activeFrame->script()->anyPageIsProcessingUserGesture(), false);
+}
+
+void DOMWindow::printErrorMessage(const String& message)
+{
+ if (message.isEmpty())
+ return;
+
+ Settings* settings = m_frame->settings();
+ if (!settings)
+ return;
+ if (settings->privateBrowsingEnabled())
+ return;
+
+ // FIXME: Add arguments so that we can provide a correct source URL and line number.
+ console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
+}
+
+String DOMWindow::crossDomainAccessErrorMessage(DOMWindow* activeWindow)
+{
+ const KURL& activeWindowURL = activeWindow->url();
+ if (activeWindowURL.isNull())
+ return String();
+
+ // FIXME: This error message should contain more specifics of why the same origin check has failed.
+ // Perhaps we should involve the security origin object in composing it.
+ // FIXME: This message, and other console messages, have extra newlines. Should remove them.
+ return makeString("Unsafe JavaScript attempt to access frame with URL ", m_url.string(),
+ " from frame with URL ", activeWindowURL.string(), ". Domains, protocols and ports must match.\n");
+}
+
+bool DOMWindow::isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString)
+{
+ if (!protocolIsJavaScript(urlString))
+ return false;
+
+ // FIXME: Is there some way to eliminate the need for a separate "activeWindow == this" check?
+ if (activeWindow == this)
+ return false;
+
+ // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script".
+ // Can we name the SecurityOrigin function better to make this more clear?
+ if (activeWindow->securityOrigin()->canAccess(securityOrigin()))
+ return false;
+
+ printErrorMessage(crossDomainAccessErrorMessage(activeWindow));
+ return true;
+}
+
+Frame* DOMWindow::createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures,
+ DOMWindow* activeWindow, Frame* firstFrame, Frame* openerFrame, PrepareDialogFunction function, void* functionContext)
+{
+ Frame* activeFrame = activeWindow->frame();
+
+ // FIXME: It's much better for client API if a new window starts with a URL, here where we
+ // know what URL we are going to open. Unfortunately, this code passes the empty string
+ // for the URL, but there's a reason for that. Before loading we have to set up the opener,
+ // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently
+ // do an isInsecureScriptAccess call using the window we create, which can't be done before
+ // creating it. We'd have to resolve all those issues to pass the URL instead of an empty string.
+
+ // For whatever reason, Firefox uses the first frame to determine the outgoingReferrer. We replicate that behavior here.
+ String referrer = firstFrame->loader()->outgoingReferrer();
+
+ ResourceRequest request(KURL(), referrer);
+ FrameLoader::addHTTPOriginIfNeeded(request, firstFrame->loader()->outgoingOrigin());
+ FrameLoadRequest frameRequest(activeWindow->securityOrigin(), request, frameName);
+
+ // We pass the opener frame for the lookupFrame in case the active frame is different from
+ // the opener frame, and the name references a frame relative to the opener frame.
+ bool created;
+ Frame* newFrame = WebCore::createWindow(activeFrame, openerFrame, frameRequest, windowFeatures, created);
+ if (!newFrame)
+ return 0;
+
+ newFrame->loader()->setOpener(openerFrame);
+ newFrame->page()->setOpenedByDOM();
+
+ if (newFrame->domWindow()->isInsecureScriptAccess(activeWindow, urlString))
+ return newFrame;
+
+ if (function)
+ function(newFrame->domWindow(), functionContext);
+
+ KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, "") : firstFrame->document()->completeURL(urlString);
+
+ if (created)
+ newFrame->loader()->changeLocation(activeWindow->securityOrigin(), completedURL, referrer, false, false);
+ else if (!urlString.isEmpty()) {
+ newFrame->navigationScheduler()->scheduleLocationChange(activeWindow->securityOrigin(), completedURL.string(), referrer,
+ !activeFrame->script()->anyPageIsProcessingUserGesture(), false);
+ }
+
+ return newFrame;
+}
+
+PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
+ DOMWindow* activeWindow, DOMWindow* firstWindow)
+{
+ if (!m_frame)
+ return 0;
+ Frame* activeFrame = activeWindow->frame();
+ if (!activeFrame)
+ return 0;
+ Frame* firstFrame = firstWindow->frame();
+ if (!firstFrame)
+ return 0;
+
+ if (!firstWindow->allowPopUp()) {
+ // Because FrameTree::find() returns true for empty strings, we must check for empty frame names.
+ // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
+ if (frameName.isEmpty() || !m_frame->tree()->find(frameName))
+ return 0;
+ }
+
+ // Get the target frame for the special cases of _top and _parent.
+ // In those cases, we schedule a location change right now and return early.
+ Frame* targetFrame = 0;
+ if (frameName == "_top")
+ targetFrame = m_frame->tree()->top();
+ else if (frameName == "_parent") {
+ if (Frame* parent = m_frame->tree()->parent())
+ targetFrame = parent;
+ else
+ targetFrame = m_frame;
+ }
+ if (targetFrame) {
+ if (!activeFrame->loader()->shouldAllowNavigation(targetFrame))
+ return 0;
+
+ if (isInsecureScriptAccess(activeWindow, urlString))
+ return targetFrame->domWindow();
+
+ if (urlString.isEmpty())
+ return targetFrame->domWindow();
+
+ // For whatever reason, Firefox uses the first window rather than the active window to
+ // determine the outgoing referrer. We replicate that behavior here.
+ targetFrame->navigationScheduler()->scheduleLocationChange(activeFrame->document()->securityOrigin(),
+ firstFrame->document()->completeURL(urlString).string(),
+ firstFrame->loader()->outgoingReferrer(),
+ !activeFrame->script()->anyPageIsProcessingUserGesture(), false);
+
+ return targetFrame->domWindow();
+ }
+
+ WindowFeatures windowFeatures(windowFeaturesString);
+ FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
+ windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
+ Page* page = m_frame->page();
+ DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
+ windowFeatures.x = windowRect.x();
+ windowFeatures.y = windowRect.y();
+ windowFeatures.height = windowRect.height();
+ windowFeatures.width = windowRect.width();
+
+ Frame* result = createWindow(urlString, frameName, windowFeatures, activeWindow, firstFrame, m_frame);
+ return result ? result->domWindow() : 0;
+}
+
+void DOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString,
+ DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction function, void* functionContext)
+{
+ if (!m_frame)
+ return;
+ Frame* activeFrame = activeWindow->frame();
+ if (!activeFrame)
+ return;
+ Frame* firstFrame = firstWindow->frame();
+ if (!firstFrame)
+ return;
+
+ if (!canShowModalDialogNow(m_frame) || !firstWindow->allowPopUp())
+ return;
+
+ Frame* dialogFrame = createWindow(urlString, emptyAtom, WindowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())),
+ activeWindow, firstFrame, m_frame, function, functionContext);
+ if (!dialogFrame)
+ return;
+
+ dialogFrame->page()->chrome()->runModal();
+}
+>>>>>>> webkit.org at r74534 (trunk)
} // namespace WebCore
diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h
index 0cbac78..5c1f680 100644
--- a/WebCore/page/DOMWindow.h
+++ b/WebCore/page/DOMWindow.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
*
* Redistribution and use in source and binary forms, with or without
@@ -27,35 +27,27 @@
#ifndef DOMWindow_h
#define DOMWindow_h
-#include "EventTarget.h"
#include "KURL.h"
#include "MessagePort.h"
-#include "PlatformString.h"
-#include "RegisteredEventListener.h"
#include "SecurityOrigin.h"
-#include <wtf/Forward.h>
-#include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
namespace WebCore {
class BarInfo;
- class BeforeUnloadEvent;
class Blob;
class CSSRuleList;
class CSSStyleDeclaration;
class Console;
+ class DOMApplicationCache;
class DOMSelection;
class Database;
class DatabaseCallback;
class Document;
class Element;
class ErrorCallback;
- class Event;
class EventListener;
class FileSystemCallback;
class FloatRect;
- class Frame;
class History;
class IDBFactory;
class Location;
@@ -63,25 +55,16 @@ namespace WebCore {
class Navigator;
class Node;
class NotificationCenter;
- class StyleMedia;
-
-#if ENABLE(WEB_TIMING)
class Performance;
-#endif
-
class PostMessageTimer;
class ScheduledAction;
- class SerializedScriptValue;
class Screen;
- class WebKitPoint;
-
-#if ENABLE(DOM_STORAGE)
+ class SerializedScriptValue;
class Storage;
-#endif
+ class StyleMedia;
+ class WebKitPoint;
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- class DOMApplicationCache;
-#endif
+ struct WindowFeatures;
typedef int ExceptionCode;
@@ -100,13 +83,6 @@ namespace WebCore {
PassRefPtr<MediaQueryList> matchMedia(const String&);
-#if ENABLE(ORIENTATION_EVENTS)
- // This is the interface orientation in degrees. Some examples are:
- // 0 is straight up; -90 is when the device is rotated 90 clockwise;
- // 90 is when rotated counter clockwise.
- int orientation() const;
-#endif
-
void setSecurityOrigin(SecurityOrigin* securityOrigin) { m_securityOrigin = securityOrigin; }
SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
@@ -119,13 +95,17 @@ namespace WebCore {
static void dispatchAllPendingUnloadEvents();
static void adjustWindowRect(const FloatRect& screen, FloatRect& window, const FloatRect& pendingChanges);
- static void parseModalDialogFeatures(const String& featuresArg, HashMap<String, String>& map);
- static bool allowPopUp(Frame* activeFrame);
+ // FIXME: We can remove this function once V8 showModalDialog is changed to use DOMWindow.
+ static void parseModalDialogFeatures(const String&, HashMap<String, String>&);
+
+ bool allowPopUp(); // Call on first window, not target window.
+ static bool allowPopUp(Frame* firstFrame);
static bool canShowModalDialog(const Frame*);
static bool canShowModalDialogNow(const Frame*);
// DOM Level 0
+
Screen* screen() const;
History* history() const;
BarInfo* locationbar() const;
@@ -136,10 +116,9 @@ namespace WebCore {
BarInfo* toolbar() const;
Navigator* navigator() const;
Navigator* clientInformation() const { return navigator(); }
-#if ENABLE(WEB_TIMING)
- Performance* webkitPerformance() const;
-#endif
+
Location* location() const;
+ void setLocation(const String& location, DOMWindow* activeWindow, DOMWindow* firstWindow);
DOMSelection* getSelection();
@@ -151,6 +130,13 @@ namespace WebCore {
void print();
void stop();
+ PassRefPtr<DOMWindow> open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
+ DOMWindow* activeWindow, DOMWindow* firstWindow);
+
+ typedef void (*PrepareDialogFunction)(DOMWindow*, void* context);
+ void showModalDialog(const String& urlString, const String& dialogFeaturesString,
+ DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction, void* functionContext);
+
void alert(const String& message);
bool confirm(const String& message);
String prompt(const String& message, const String& defaultValue);
@@ -185,11 +171,13 @@ namespace WebCore {
void setStatus(const String&);
String defaultStatus() const;
void setDefaultStatus(const String&);
+
// This attribute is an alias of defaultStatus and is necessary for legacy uses.
String defaultstatus() const { return defaultStatus(); }
void setDefaultstatus(const String& status) { setDefaultStatus(status); }
- // Self referential attributes
+ // Self-referential attributes
+
DOMWindow* self() const;
DOMWindow* window() const { return self(); }
DOMWindow* frames() const { return self(); }
@@ -199,17 +187,23 @@ namespace WebCore {
DOMWindow* top() const;
// DOM Level 2 AbstractView Interface
+
Document* document() const;
+
// CSSOM View Module
+
PassRefPtr<StyleMedia> styleMedia() const;
// DOM Level 2 Style Interface
+
PassRefPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const;
// WebKit extensions
+
PassRefPtr<CSSRuleList> getMatchedCSSRules(Element*, const String& pseudoElt, bool authorOnly = true) const;
double devicePixelRatio() const;
+<<<<<<< HEAD
PassRefPtr<WebKitPoint> webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const;
PassRefPtr<WebKitPoint> webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const;
@@ -226,32 +220,18 @@ namespace WebCore {
void clearDOMStorage();
#endif
#endif
+=======
+ PassRefPtr<WebKitPoint> webkitConvertPointFromPageToNode(Node*, const WebKitPoint*) const;
+ PassRefPtr<WebKitPoint> webkitConvertPointFromNodeToPage(Node*, const WebKitPoint*) const;
+>>>>>>> webkit.org at r74534 (trunk)
Console* console() const;
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- DOMApplicationCache* applicationCache() const;
-#endif
-
-#if ENABLE(NOTIFICATIONS)
- NotificationCenter* webkitNotifications() const;
-#endif
+ void printErrorMessage(const String&);
+ String crossDomainAccessErrorMessage(DOMWindow* activeWindow);
void pageDestroyed();
-#if ENABLE(INDEXED_DATABASE)
- IDBFactory* webkitIndexedDB() const;
-#endif
-
-#if ENABLE(FILE_SYSTEM)
- // They are placed here and in all capital letters to enforce compile-time enum checking.
- enum FileSystemType {
- TEMPORARY,
- PERSISTENT,
- };
- void requestFileSystem(int type, long long size, PassRefPtr<FileSystemCallback>, PassRefPtr<ErrorCallback>);
-#endif
-
void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
// FIXME: remove this when we update the ObjC bindings (bug #28774).
void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
@@ -350,33 +330,17 @@ namespace WebCore {
DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitbeginfullscreen);
DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitendfullscreen);
-#if ENABLE(ORIENTATION_EVENTS)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(orientationchange);
-#endif
-
-#if ENABLE(DEVICE_ORIENTATION)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(devicemotion);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(deviceorientation);
-#endif
-
DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(webkitanimationstart, webkitAnimationStart);
DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(webkitanimationiteration, webkitAnimationIteration);
DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(webkitanimationend, webkitAnimationEnd);
DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(webkittransitionend, webkitTransitionEnd);
-#if ENABLE(TOUCH_EVENTS)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
-#endif
void captureEvents();
void releaseEvents();
void finishedLoading();
- // These methods are used for GC marking. See JSDOMWindow::markChildren(MarkStack&) in
- // JSDOMWindowCustom.cpp.
+ // These functions 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(); }
History* optionalHistory() const { return m_history.get(); }
@@ -388,25 +352,78 @@ namespace WebCore {
BarInfo* optionalToolbar() const { return m_toolbar.get(); }
Console* optionalConsole() const { return m_console.get(); }
Navigator* optionalNavigator() const { return m_navigator.get(); }
-#if ENABLE(WEB_TIMING)
- Performance* optionalWebkitPerformance() const { return m_performance.get(); }
-#endif
Location* optionalLocation() const { return m_location.get(); }
StyleMedia* optionalMedia() const { return m_media.get(); }
+
+ using RefCounted<DOMWindow>::ref;
+ using RefCounted<DOMWindow>::deref;
+
+#if ENABLE(BLOB)
+ String createObjectURL(Blob*);
+ void revokeObjectURL(const String&);
+#endif
+
+#if ENABLE(DATABASE)
+ // HTML 5 client-side database
+ PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode&);
+#endif
+
+#if ENABLE(DEVICE_ORIENTATION)
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(devicemotion);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(deviceorientation);
+#endif
+
#if ENABLE(DOM_STORAGE)
+ // HTML 5 key/value storage
+ Storage* sessionStorage(ExceptionCode&) const;
+ Storage* localStorage(ExceptionCode&) const;
Storage* optionalSessionStorage() const { return m_sessionStorage.get(); }
Storage* optionalLocalStorage() const { return m_localStorage.get(); }
#endif
+
+#if ENABLE(FILE_SYSTEM)
+ // They are placed here and in all capital letters so they can be checked against the constants in the
+ // IDL at compile time.
+ enum FileSystemType {
+ TEMPORARY,
+ PERSISTENT,
+ };
+ void requestFileSystem(int type, long long size, PassRefPtr<FileSystemCallback>, PassRefPtr<ErrorCallback>);
+#endif
+
+#if ENABLE(INDEXED_DATABASE)
+ IDBFactory* webkitIndexedDB() const;
+#endif
+
+#if ENABLE(NOTIFICATIONS)
+ NotificationCenter* webkitNotifications() const;
+#endif
+
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ DOMApplicationCache* applicationCache() const;
DOMApplicationCache* optionalApplicationCache() const { return m_applicationCache.get(); }
#endif
-#if ENABLE(BLOB)
- String createObjectURL(Blob*);
- void revokeObjectURL(const String&);
+
+#if ENABLE(ORIENTATION_EVENTS)
+ // This is the interface orientation in degrees. Some examples are:
+ // 0 is straight up; -90 is when the device is rotated 90 clockwise;
+ // 90 is when rotated counter clockwise.
+ int orientation() const;
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(orientationchange);
#endif
- using RefCounted<DOMWindow>::ref;
- using RefCounted<DOMWindow>::deref;
+#if ENABLE(TOUCH_EVENTS)
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
+#endif
+
+#if ENABLE(WEB_TIMING)
+ Performance* webkitPerformance() const;
+ Performance* optionalWebkitPerformance() const { return m_performance.get(); }
+#endif
private:
DOMWindow(Frame*);
@@ -416,6 +433,11 @@ namespace WebCore {
virtual EventTargetData* eventTargetData();
virtual EventTargetData* ensureEventTargetData();
+ static Frame* createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures&,
+ DOMWindow* activeWindow, Frame* firstFrame, Frame* openerFrame,
+ PrepareDialogFunction = 0, void* functionContext = 0);
+ bool isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString);
+
RefPtr<SecurityOrigin> m_securityOrigin;
KURL m_url;
@@ -432,29 +454,34 @@ namespace WebCore {
mutable RefPtr<BarInfo> m_toolbar;
mutable RefPtr<Console> m_console;
mutable RefPtr<Navigator> m_navigator;
-#if ENABLE(WEB_TIMING)
- mutable RefPtr<Performance> m_performance;
-#endif
mutable RefPtr<Location> m_location;
mutable RefPtr<StyleMedia> m_media;
+
+ EventTargetData m_eventTargetData;
+
+ String m_status;
+ String m_defaultStatus;
+
#if ENABLE(DOM_STORAGE)
mutable RefPtr<Storage> m_sessionStorage;
mutable RefPtr<Storage> m_localStorage;
#endif
+
+#if ENABLE(INDEXED_DATABASE)
+ mutable RefPtr<IDBFactory> m_idbFactory;
+#endif
+
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
mutable RefPtr<DOMApplicationCache> m_applicationCache;
#endif
+
#if ENABLE(NOTIFICATIONS)
mutable RefPtr<NotificationCenter> m_notifications;
#endif
-#if ENABLE(INDEXED_DATABASE)
- mutable RefPtr<IDBFactory> m_idbFactory;
-#endif
-
- EventTargetData m_eventTargetData;
- String m_status;
- String m_defaultStatus;
+#if ENABLE(WEB_TIMING)
+ mutable RefPtr<Performance> m_performance;
+#endif
};
inline String DOMWindow::status() const
diff --git a/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl
index fe12287..eac57b1 100644
--- a/WebCore/page/DOMWindow.idl
+++ b/WebCore/page/DOMWindow.idl
@@ -486,7 +486,15 @@ module window {
attribute CanvasGradientConstructor CanvasGradient;
attribute CanvasRenderingContext2DConstructor CanvasRenderingContext2D;
attribute ImageDataConstructor ImageData;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLActiveInfoConstructor WebGLActiveInfo;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLBufferConstructor WebGLBuffer;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLFramebufferConstructor WebGLFramebuffer;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLProgramConstructor WebGLProgram;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLRenderbufferConstructor WebGLRenderbuffer;
attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLRenderingContextConstructor WebGLRenderingContext;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLShaderConstructor WebGLShader;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLTextureConstructor WebGLTexture;
+ attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLUniformLocationConstructor WebGLUniformLocation;
attribute TextMetricsConstructor TextMetrics;
attribute DOMStringMapConstructor DOMStringMap;
@@ -501,6 +509,9 @@ module window {
attribute [JSCCustomGetter,Conditional=3D_CANVAS|BLOB,EnabledAtRuntime] Float32ArrayConstructor Float32Array; // Usable with new operator
attribute [JSCCustomGetter,Conditional=3D_CANVAS|BLOB,EnabledAtRuntime] DataViewConstructor DataView; // Usable with new operator
+ attribute [JSCCustomGetter,Conditional=WEB_AUDIO] AudioContextConstructor webkitAudioContext; // Usable with new operator
+ attribute [Conditional=WEB_AUDIO] AudioPannerNodeConstructor webkitAudioPannerNode; // Needed for panning model constants
+
attribute EventConstructor Event;
attribute BeforeLoadEventConstructor BeforeLoadEvent;
attribute HashChangeEventConstructor HashChangeEvent;
diff --git a/WebCore/page/DragController.cpp b/WebCore/page/DragController.cpp
index eb90f85..8ee5a8d 100644
--- a/WebCore/page/DragController.cpp
+++ b/WebCore/page/DragController.cpp
@@ -255,7 +255,7 @@ static HTMLInputElement* asFileInput(Node* 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)->isFileUpload())
+ if (node->hasTagName(HTMLNames::inputTag) && node->isShadowRoot() && !static_cast<HTMLInputElement*>(node)->isFileUpload())
node = node->shadowParentNode();
if (!node || !node->hasTagName(HTMLNames::inputTag))
@@ -268,6 +268,7 @@ static HTMLInputElement* asFileInput(Node* node)
return inputElement;
}
+// This can return null if an empty document is loaded.
static Element* elementUnderMouse(Document* documentUnderMouse, const IntPoint& p)
{
Frame* frame = documentUnderMouse->frame();
@@ -284,7 +285,6 @@ static Element* elementUnderMouse(Document* documentUnderMouse, const IntPoint&
if (n)
n = n->shadowAncestorNode();
- ASSERT(n);
return static_cast<Element*>(n);
}
@@ -327,6 +327,8 @@ bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction a
IntPoint point = frameView->windowToContents(dragData->clientPosition());
Element* element = elementUnderMouse(m_documentUnderMouse.get(), point);
+ if (!element)
+ return false;
if (!asFileInput(element)) {
VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point);
m_page->dragCaretController()->setSelection(dragCaret);
@@ -386,6 +388,8 @@ bool DragController::concludeEditDrag(DragData* dragData)
IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition());
Element* element = elementUnderMouse(m_documentUnderMouse.get(), point);
+ if (!element)
+ return false;
Frame* innerFrame = element->ownerDocument()->frame();
ASSERT(innerFrame);
diff --git a/WebCore/page/EditorClient.h b/WebCore/page/EditorClient.h
index 61bdd41..1ec0c7e 100644
--- a/WebCore/page/EditorClient.h
+++ b/WebCore/page/EditorClient.h
@@ -66,6 +66,7 @@ class HTMLElement;
class KeyboardEvent;
class Node;
class Range;
+class SpellChecker;
class VisibleSelection;
class VisiblePosition;
@@ -190,8 +191,8 @@ public:
#endif
#if SUPPORT_AUTOCORRECTION_PANEL
- virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, Editor*) = 0;
- virtual void dismissCorrectionPanel(CorrectionWasRejectedOrNot) = 0;
+ virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, const Vector<String>& alternativeReplacementStrings, Editor*) = 0;
+ virtual void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel) = 0;
virtual bool isShowingCorrectionPanel() = 0;
#endif
@@ -199,9 +200,11 @@ public:
virtual void updateSpellingUIWithMisspelledWord(const String&) = 0;
virtual void showSpellingUI(bool show) = 0;
virtual bool spellingUIIsShowing() = 0;
- virtual void getGuessesForWord(const String&, Vector<String>& guesses) = 0;
+ // For spellcheckers that support multiple languages, it's often important to be able to identify the language in order to provide more accurate correction suggestions. Caller can pass in more text in "context" to aid such spellcheckers on language identification. Noramlly it's the text surrounding the "word" for which we are getting correction suggestions.
+ virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses) = 0;
virtual void willSetInputMethodState() = 0;
virtual void setInputMethodState(bool enabled) = 0;
+ virtual void requestCheckingOfString(SpellChecker*, int, const String&) = 0;
};
}
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index e044daa..bd39ed1 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -1004,22 +1004,71 @@ bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity g
return false;
}
+bool EventHandler::logicalScrollOverflow(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
+{
+ Node* node = startingNode;
+
+ if (!node)
+ node = m_frame->document()->focusedNode();
+
+ if (!node)
+ node = m_mousePressNode.get();
+
+ if (node) {
+ RenderObject* r = node->renderer();
+ if (r && !r->isListBox() && r->enclosingBox()->logicalScroll(direction, granularity)) {
+ setFrameWasScrolledByUser();
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
{
// The layout needs to be up to date to determine if we can scroll. We may be
// here because of an onLoad event, in which case the final layout hasn't been performed yet.
m_frame->document()->updateLayoutIgnorePendingStylesheets();
- bool handled = scrollOverflow(direction, granularity, startingNode);
- 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);
- }
+ if (scrollOverflow(direction, granularity, startingNode))
+ return true;
+ Frame* frame = m_frame;
+ FrameView* view = frame->view();
+ if (view && view->scroll(direction, granularity))
+ return true;
+ frame = frame->tree()->parent();
+ if (!frame)
+ return false;
+ return frame->eventHandler()->scrollRecursively(direction, granularity, m_frame->document()->ownerElement());
+}
- return handled;
+bool EventHandler::logicalScrollRecursively(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
+{
+ // The layout needs to be up to date to determine if we can scroll. We may be
+ // here because of an onLoad event, in which case the final layout hasn't been performed yet.
+ m_frame->document()->updateLayoutIgnorePendingStylesheets();
+ if (logicalScrollOverflow(direction, granularity, startingNode))
+ return true;
+ Frame* frame = m_frame;
+ FrameView* view = frame->view();
+
+ bool scrolled = false;
+#if PLATFORM(MAC)
+ // Mac also resets the scroll position in the inline direction.
+ if (granularity == ScrollByDocument && view && view->logicalScroll(ScrollInlineDirectionBackward, ScrollByDocument))
+ scrolled = true;
+#endif
+ if (view && view->logicalScroll(direction, granularity))
+ scrolled = true;
+
+ if (scrolled)
+ return true;
+
+ frame = frame->tree()->parent();
+ if (!frame)
+ return false;
+
+ return frame->eventHandler()->logicalScrollRecursively(direction, granularity, m_frame->document()->ownerElement());
}
IntPoint EventHandler::currentMousePosition() const
@@ -1348,7 +1397,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
// If a mouse event handler changes the input element type to one that has a widget associated,
// we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
// event target node can't still be the shadow node.
- if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag)) {
+ if (mev.targetNode()->isShadowRoot() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag)) {
HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
}
@@ -1876,20 +1925,16 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
// is expected by some sites that rely on onChange handlers running
// from form fields before the button click is processed.
Node* node = m_nodeUnderMouse.get();
- RenderObject* renderer = node ? node->renderer() : 0;
- // Walk up the render tree to search for a node to focus.
- // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
- // FIXME: Rework to use shadowParent. No need to traverse with the render tree.
- while (renderer) {
- node = renderer->node();
- if (node && node->isMouseFocusable()) {
- // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
- // node on mouse down if it's selected and inside a focused node. It will be
+ // Walk up the DOM tree to search for a node to focus.
+ while (node) {
+ if (node->isMouseFocusable()) {
+ // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
+ // node on mouse down if it's selected and inside a focused node. It will be
// focused if the user does a mouseup over it, however, because the mouseup
// will set a selection inside it, which will call setFocuseNodeIfNeeded.
ExceptionCode ec = 0;
- Node* n = node->isShadowNode() ? node->shadowParentNode() : node;
+ Node* n = node->isShadowRoot() ? node->shadowParentNode() : node;
if (m_frame->selection()->isRange()
&& m_frame->selection()->toNormalizedRange()->compareNode(n, ec) == Range::NODE_INSIDE
&& n->isDescendantOf(m_frame->document()->focusedNode()))
@@ -1897,8 +1942,7 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
break;
}
-
- renderer = renderer->parent();
+ node = node->parentOrHostNode();
}
// If focus shift is blocked, we eat the event. Note we should never clear swallowEvent
@@ -2702,8 +2746,8 @@ void EventHandler::defaultSpaceEventHandler(KeyboardEvent*)
void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
{
- ScrollDirection direction = event->shiftKey() ? ScrollUp : ScrollDown;
- if (scrollOverflow(direction, ScrollByPage)) {
+ ScrollLogicalDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
+ if (logicalScrollOverflow(direction, ScrollByPage)) {
event->setDefaultHandled();
return;
}
@@ -2712,7 +2756,7 @@ void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
if (!view)
return;
- if (view->scroll(direction, ScrollByPage))
+ if (view->logicalScroll(direction, ScrollByPage))
event->setDefaultHandled();
}
diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h
index ca19a0c..65695c2 100644
--- a/WebCore/page/EventHandler.h
+++ b/WebCore/page/EventHandler.h
@@ -133,8 +133,10 @@ public:
static Frame* subframeForTargetNode(Node*);
bool scrollOverflow(ScrollDirection, ScrollGranularity, Node* startingNode = 0);
+ bool logicalScrollOverflow(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
bool scrollRecursively(ScrollDirection, ScrollGranularity, Node* startingNode = 0);
+ bool logicalScrollRecursively(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
#if ENABLE(DRAG_SUPPORT)
bool shouldDragAutoNode(Node*, const IntPoint&) const; // -webkit-user-drag == auto
diff --git a/WebCore/page/EventSource.cpp b/WebCore/page/EventSource.cpp
index b0b07aa..39f15e9 100644
--- a/WebCore/page/EventSource.cpp
+++ b/WebCore/page/EventSource.cpp
@@ -180,7 +180,7 @@ ScriptExecutionContext* EventSource::scriptExecutionContext() const
void EventSource::didReceiveResponse(const ResourceResponse& response)
{
int statusCode = response.httpStatusCode();
- if (statusCode == 200 && response.httpHeaderField("Content-Type") == "text/event-stream") {
+ if (statusCode == 200 && response.mimeType() == "text/event-stream") {
m_state = OPEN;
dispatchEvent(Event::create(eventNames().openEvent, false, false));
} else {
diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp
index 5418c89..9ca18dd 100644
--- a/WebCore/page/FocusController.cpp
+++ b/WebCore/page/FocusController.cpp
@@ -40,9 +40,10 @@
#include "Frame.h"
#include "FrameTree.h"
#include "FrameView.h"
-#include "HitTestResult.h"
-#include "HTMLFrameOwnerElement.h"
+#include "HTMLAreaElement.h"
+#include "HTMLImageElement.h"
#include "HTMLNames.h"
+#include "HitTestResult.h"
#include "KeyboardEvent.h"
#include "Page.h"
#include "Range.h"
@@ -59,7 +60,6 @@ namespace WebCore {
using namespace HTMLNames;
using namespace std;
-static void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest);
static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool focused)
{
// If we have a focused node we should dispatch blur on it before we blur the window.
@@ -130,6 +130,9 @@ void FocusController::setFocused(bool focused)
m_isFocused = focused;
+ if (!m_isFocused)
+ focusedOrMainFrame()->eventHandler()->stopAutoscrollTimer();
+
if (!m_focusedFrame)
setFocusedFrame(m_page->mainFrame());
@@ -412,13 +415,13 @@ void FocusController::setActive(bool active)
dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), active);
}
-void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest)
+static void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest)
{
- if (!candidate.node->isElementNode() || !candidate.node->renderer())
+ if (!candidate.visibleNode->isElementNode() || !candidate.visibleNode->renderer())
return;
// Ignore iframes that don't have a src attribute
- if (candidate.node->isFrameOwnerElement() && !static_cast<HTMLFrameOwnerElement*>(candidate.node)->contentFrame())
+ if (frameOwnerElement(candidate) && (!frameOwnerElement(candidate)->contentFrame() || candidate.rect.isEmpty()))
return;
// Ignore off screen child nodes of containers that do not scroll (overflow:hidden)
@@ -444,12 +447,12 @@ void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& start
// If 2 nodes are intersecting, do hit test to find which node in on top.
int x = intersectionRect.x() + intersectionRect.width() / 2;
int y = intersectionRect.y() + intersectionRect.height() / 2;
- HitTestResult result = candidate.node->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true);
- if (candidate.node->contains(result.innerNode())) {
+ HitTestResult result = candidate.visibleNode->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true);
+ if (candidate.visibleNode->contains(result.innerNode())) {
closest = candidate;
return;
}
- if (closest.node->contains(result.innerNode()))
+ if (closest.visibleNode->contains(result.innerNode()))
return;
}
@@ -473,13 +476,13 @@ void FocusController::findFocusCandidateInContainer(Node* container, const IntRe
if (node == focusedNode)
continue;
- if (!node->renderer())
+ if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(direction, node))
continue;
- if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(direction, node))
+ FocusCandidate candidate = FocusCandidate(node, direction);
+ if (candidate.isNull())
continue;
- FocusCandidate candidate(node, direction);
candidate.enclosingScrollableBox = container;
updateFocusCandidateIfNeeded(direction, startingRect, candidate, closest);
}
@@ -500,23 +503,20 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
findFocusCandidateInContainer(container, newStartingRect, direction, event, focusCandidate);
if (focusCandidate.isNull()) {
- if (canScrollInDirection(direction, container)) {
- // Nothing to focus, scroll if possible.
- scrollInDirection(container, direction);
- return true;
- }
- // Return false will cause a re-try, skipping this container.
- return false;
+ // Nothing to focus, scroll if possible.
+ // NOTE: If no scrolling is performed (i.e. scrollInDirection returns false), the
+ // spatial navigation algorithm will skip this container.
+ return scrollInDirection(container, direction);
}
- if (focusCandidate.node->isFrameOwnerElement()) {
- HTMLFrameOwnerElement* frameElement = static_cast<HTMLFrameOwnerElement*>(focusCandidate.node);
+
+ if (HTMLFrameOwnerElement* frameElement = frameOwnerElement(focusCandidate)) {
// If we have an iframe without the src attribute, it will not have a contentFrame().
// We ASSERT here to make sure that
// updateFocusCandidateIfNeeded() will never consider such an iframe as a candidate.
ASSERT(frameElement->contentFrame());
if (focusCandidate.isOffscreenAfterScrolling) {
- scrollInDirection(focusCandidate.node->document(), direction);
+ scrollInDirection(focusCandidate.visibleNode->document(), direction);
return true;
}
// Navigate into a new frame.
@@ -527,13 +527,13 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
frameElement->contentFrame()->document()->updateLayoutIgnorePendingStylesheets();
if (!advanceFocusDirectionallyInContainer(frameElement->contentFrame()->document(), rect, direction, event)) {
// The new frame had nothing interesting, need to find another candidate.
- return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.node, true), direction, event);
+ return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), direction, event);
}
return true;
}
- if (canScrollInDirection(direction, focusCandidate.node)) {
+ if (canScrollInDirection(direction, focusCandidate.visibleNode)) {
if (focusCandidate.isOffscreenAfterScrolling) {
- scrollInDirection(focusCandidate.node, direction);
+ scrollInDirection(focusCandidate.visibleNode, direction);
return true;
}
// Navigate into a new scrollable container.
@@ -541,7 +541,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
Node* focusedNode = focusedOrMainFrame()->document()->focusedNode();
if (focusedNode && !hasOffscreenRect(focusedNode))
startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true);
- return advanceFocusDirectionallyInContainer(focusCandidate.node, startingRect, direction, event);
+ return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, direction, event);
}
if (focusCandidate.isOffscreenAfterScrolling) {
Node* container = focusCandidate.enclosingScrollableBox;
@@ -550,7 +550,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
}
// We found a new focus node, navigate to it.
- Element* element = toElement(focusCandidate.node);
+ Element* element = toElement(focusCandidate.focusableNode);
ASSERT(element);
element->focus(false);
@@ -571,9 +571,15 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa
// Figure out the starting rect.
IntRect startingRect;
- if (focusedNode && !hasOffscreenRect(focusedNode)) {
- container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedNode);
- startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true /* ignore border */);
+ if (focusedNode) {
+ if (!hasOffscreenRect(focusedNode)) {
+ container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedNode);
+ startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true /* ignore border */);
+ } else if (focusedNode->hasTagName(areaTag)) {
+ HTMLAreaElement* area = static_cast<HTMLAreaElement*>(focusedNode);
+ container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, area->imageElement());
+ startingRect = virtualRectForAreaElementAndDirection(direction, area);
+ }
}
bool consumed = false;
diff --git a/WebCore/page/FrameLoadRequest.h b/WebCore/page/FrameLoadRequest.h
index b84a1ec..aa7e4a8 100644
--- a/WebCore/page/FrameLoadRequest.h
+++ b/WebCore/page/FrameLoadRequest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,28 +27,34 @@
#define FrameLoadRequest_h
#include "ResourceRequest.h"
+#include "SecurityOrigin.h"
namespace WebCore {
struct FrameLoadRequest {
public:
- FrameLoadRequest()
+ explicit FrameLoadRequest(PassRefPtr<SecurityOrigin> requester)
+ : m_requester(requester)
{
}
- FrameLoadRequest(const ResourceRequest& resourceRequest)
- : m_resourceRequest(resourceRequest)
+ FrameLoadRequest(PassRefPtr<SecurityOrigin> requester, const ResourceRequest& resourceRequest)
+ : m_requester(requester)
+ , m_resourceRequest(resourceRequest)
{
}
- FrameLoadRequest(const ResourceRequest& resourceRequest, const String& frameName)
- : m_resourceRequest(resourceRequest)
+ FrameLoadRequest(PassRefPtr<SecurityOrigin> requester, const ResourceRequest& resourceRequest, const String& frameName)
+ : m_requester(requester)
+ , m_resourceRequest(resourceRequest)
, m_frameName(frameName)
{
}
bool isEmpty() const { return m_resourceRequest.isEmpty(); }
+ const SecurityOrigin* requester() const { return m_requester.get(); }
+
ResourceRequest& resourceRequest() { return m_resourceRequest; }
const ResourceRequest& resourceRequest() const { return m_resourceRequest; }
@@ -56,6 +62,7 @@ namespace WebCore {
void setFrameName(const String& frameName) { m_frameName = frameName; }
private:
+ RefPtr<SecurityOrigin> m_requester;
ResourceRequest m_resourceRequest;
String m_frameName;
};
diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp
index 3517688..cc4c181 100644
--- a/WebCore/page/FrameView.cpp
+++ b/WebCore/page/FrameView.cpp
@@ -447,15 +447,10 @@ void FrameView::adjustViewSize()
if (!root)
return;
- int prevScrollOriginX = scrollOriginX();
- ScrollView::setScrollOriginX(-root->leftLayoutOverflow());
- IntSize size = IntSize(root->rightLayoutOverflow() - root->leftLayoutOverflow(), root->bottomLayoutOverflow());
- // Take care of the case when contents remain but the RenderView's direction has changed.
- // In which case, we need to update scroller position, for example, from leftmost to
- // rightmost when direction changes from left-to-right to right-to-left.
- bool directionChanged = (!prevScrollOriginX || !scrollOriginX()) && (scrollOriginX() != prevScrollOriginX);
- if (size == contentsSize() && directionChanged)
- ScrollView::updateScrollbars();
+ IntSize size = IntSize(root->docWidth(), root->docHeight());
+
+ ScrollView::setScrollOrigin(IntPoint(-root->docLeft(), -root->docTop()), size == contentsSize());
+
setContentsSize(size);
}
@@ -500,6 +495,13 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S
void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
{
+ const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
+ if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
+ hMode = ScrollbarAlwaysOff;
+ vMode = ScrollbarAlwaysOff;
+ return;
+ }
+
if (m_canHaveScrollbars) {
hMode = ScrollbarAuto;
vMode = ScrollbarAuto;
@@ -515,7 +517,6 @@ void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, Scrollbar
Node* body = document->body();
if (body && body->renderer()) {
if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
- body->renderer()->setChildNeedsLayout(true);
vMode = ScrollbarAlwaysOff;
hMode = ScrollbarAlwaysOff;
} else if (body->hasTagName(bodyTag)) {
@@ -526,27 +527,15 @@ void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, Scrollbar
}
} else if (rootRenderer) {
#if ENABLE(SVG)
- if (documentElement->isSVGElement()) {
- if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
- rootRenderer->setChildNeedsLayout(true);
- } else
+ if (!documentElement->isSVGElement())
applyOverflowToViewport(rootRenderer, hMode, vMode);
#else
applyOverflowToViewport(rootRenderer, hMode, vMode);
#endif
}
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (m_firstLayout && !document->ownerElement())
- printf("Elapsed time before first layout: %d\n", document->elapsedTime());
-#endif
- }
-
- HTMLFrameOwnerElement* owner = m_frame->ownerElement();
- if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
- hMode = ScrollbarAlwaysOff;
- vMode = ScrollbarAlwaysOff;
- }
+ }
}
+
#if USE(ACCELERATED_COMPOSITING)
void FrameView::updateCompositingLayers()
@@ -776,9 +765,35 @@ void FrameView::layout(bool allowSubtree)
m_nestedLayoutCount++;
- ScrollbarMode hMode;
- ScrollbarMode vMode;
+ if (!m_layoutRoot) {
+ Document* document = m_frame->document();
+ Node* documentElement = document->documentElement();
+ RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
+ Node* body = document->body();
+ if (body && body->renderer()) {
+ if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
+ body->renderer()->setChildNeedsLayout(true);
+ } else if (body->hasTagName(bodyTag)) {
+ if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
+ body->renderer()->setChildNeedsLayout(true);
+ }
+ } else if (rootRenderer) {
+#if ENABLE(SVG)
+ if (documentElement->isSVGElement()) {
+ if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
+ rootRenderer->setChildNeedsLayout(true);
+ }
+#endif
+ }
+
+#ifdef INSTRUMENT_LAYOUT_SCHEDULING
+ if (m_firstLayout && !document->ownerElement())
+ printf("Elapsed time before first layout: %d\n", document->elapsedTime());
+#endif
+ }
+ ScrollbarMode hMode;
+ ScrollbarMode vMode;
calculateScrollbarModesForLayout(hMode, vMode);
m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
@@ -1272,11 +1287,8 @@ bool FrameView::scrollToAnchor(const String& name)
if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
if (viewElement.get()) {
- SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get());
- if (element->hasTagName(SVGNames::svgTag)) {
- RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element);
- svg->inheritViewAttributes(viewElement.get());
- }
+ RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
+ svg->inheritViewAttributes(viewElement.get());
}
}
}
@@ -2193,13 +2205,6 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
}
#endif
- ASSERT(!m_isPainting);
-
- m_isPainting = true;
-
- // m_nodeToDraw is used to draw only one element (and its descendants)
- RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
-
PaintBehavior oldPaintBehavior = m_paintBehavior;
if (m_paintBehavior == PaintBehaviorNormal)
document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
@@ -2207,11 +2212,25 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
if (document->printing())
m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
+ bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
+ bool isRootFrame = !document->ownerElement();
+ if (flatteningPaint && isRootFrame)
+ notifyWidgetsInAllFrames(WillPaintFlattened);
+
+ ASSERT(!m_isPainting);
+ m_isPainting = true;
+
+ // m_nodeToDraw is used to draw only one element (and its descendants)
+ RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
+
contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
-
- m_paintBehavior = oldPaintBehavior;
-
+
m_isPainting = false;
+
+ if (flatteningPaint && isRootFrame)
+ notifyWidgetsInAllFrames(DidPaintFlattened);
+
+ m_paintBehavior = oldPaintBehavior;
m_lastPaintTime = currentTime();
#if ENABLE(DASHBOARD_SUPPORT)
@@ -2296,7 +2315,7 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximu
if (root) {
int pageW = ceilf(pageSize.width());
root->setWidth(pageW);
- root->setPageHeight(pageSize.height());
+ root->setPageLogicalHeight(pageSize.height());
root->setNeedsLayoutAndPrefWidthsRecalc();
forceLayout();
@@ -2304,15 +2323,15 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximu
// page width when shrunk, we will lay out at maximum shrink and clip extra content.
// FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
// implementation should not do this!
- int rightmostPos = root->rightmostPosition();
- if (rightmostPos > pageSize.width()) {
- pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
+ int docWidth = root->docWidth();
+ if (docWidth > pageSize.width()) {
+ pageW = std::min<int>(docWidth, ceilf(pageSize.width() * maximumShrinkFactor));
if (pageSize.height())
- root->setPageHeight(pageW / pageSize.width() * pageSize.height());
+ root->setPageLogicalHeight(pageW / pageSize.width() * pageSize.height());
root->setWidth(pageW);
root->setNeedsLayoutAndPrefWidthsRecalc();
forceLayout();
- int docHeight = root->bottomLayoutOverflow();
+ int docHeight = root->docHeight();
root->clearLayoutOverflow();
root->addLayoutOverflow(IntRect(0, 0, pageW, docHeight)); // This is how we clip in case we overflow again.
}
@@ -2502,4 +2521,38 @@ void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(d
s_deferredRepaintDelayIncrementDuringLoading = p;
}
+bool FrameView::isVerticalDocument() const
+{
+ if (!m_frame)
+ return true;
+ Document* doc = m_frame->document();
+ if (!doc)
+ return true;
+ RenderObject* renderView = doc->renderer();
+ if (!renderView)
+ return true;
+ return renderView->style()->isHorizontalWritingMode();
+}
+
+bool FrameView::isFlippedDocument() const
+{
+ if (!m_frame)
+ return false;
+ Document* doc = m_frame->document();
+ if (!doc)
+ return false;
+ RenderObject* renderView = doc->renderer();
+ if (!renderView)
+ return false;
+ return renderView->style()->isFlippedBlocksWritingMode();
+}
+
+void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
+{
+ for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
+ if (RenderView* root = frame->contentRenderer())
+ root->notifyWidgets(notification);
+ }
+}
+
} // namespace WebCore
diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h
index 4135045..e94cf11 100644
--- a/WebCore/page/FrameView.h
+++ b/WebCore/page/FrameView.h
@@ -257,6 +257,9 @@ protected:
virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
virtual void scrollContentsSlowPath(const IntRect& updateRect);
+ virtual bool isVerticalDocument() const;
+ virtual bool isFlippedDocument() const;
+
private:
FrameView(Frame*);
@@ -312,6 +315,8 @@ private:
virtual void updateScrollCorner();
virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect);
+ void notifyWidgetsInAllFrames(WidgetNotification);
+
static double sCurrentPaintTimeStamp; // used for detecting decoded resource thrash in the cache
IntSize m_size;
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp
index cabfdef..354dde3 100644
--- a/WebCore/page/Geolocation.cpp
+++ b/WebCore/page/Geolocation.cpp
@@ -222,7 +222,6 @@ Geolocation::Geolocation(Frame* frame)
, m_service(GeolocationService::create(this))
#endif
, m_allowGeolocation(Unknown)
- , m_positionCache(new GeolocationPositionCache)
{
if (!m_frame)
return;
@@ -236,8 +235,13 @@ Geolocation::~Geolocation()
void Geolocation::disconnectFrame()
{
- if (m_frame && m_frame->page() && m_allowGeolocation == InProgress)
+ if (m_frame && m_frame->page() && m_allowGeolocation == InProgress) {
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+ m_frame->page()->geolocationController()->cancelPermissionRequest(this);
+#else
m_frame->page()->chrome()->cancelGeolocationPermissionRequestForFrame(m_frame, this);
+#endif
+ }
cancelAllRequests();
stopUpdating();
if (m_frame && m_frame->document())
@@ -356,7 +360,7 @@ void Geolocation::makeCachedPositionCallbacks()
GeoNotifierSet::const_iterator end = m_requestsAwaitingCachedPosition.end();
for (GeoNotifierSet::const_iterator iter = m_requestsAwaitingCachedPosition.begin(); iter != end; ++iter) {
GeoNotifier* notifier = iter->get();
- notifier->runSuccessCallback(m_positionCache->cachedPosition());
+ notifier->runSuccessCallback(m_positionCache.cachedPosition());
// If this is a one-shot request, stop it. Otherwise, if the watch still
// exists, start the service to get updates.
@@ -387,14 +391,14 @@ void Geolocation::requestTimedOut(GeoNotifier* notifier)
bool Geolocation::haveSuitableCachedPosition(PositionOptions* options)
{
- if (!m_positionCache->cachedPosition())
+ if (!m_positionCache.cachedPosition())
return false;
if (!options->hasMaximumAge())
return true;
if (!options->maximumAge())
return false;
DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime());
- return m_positionCache->cachedPosition()->timestamp() > currentTimeMillis - options->maximumAge();
+ return m_positionCache.cachedPosition()->timestamp() > currentTimeMillis - options->maximumAge();
}
void Geolocation::clearWatch(int watchId)
@@ -599,13 +603,17 @@ void Geolocation::requestPermission()
m_allowGeolocation = InProgress;
- // Ask the chrome: it maintains the geolocation challenge policy itself.
+ // Ask the embedder: it maintains the geolocation challenge policy itself.
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+ page->geolocationController()->requestPermission(this);
+#else
page->chrome()->requestGeolocationPermissionForFrame(m_frame, this);
+#endif
}
void Geolocation::positionChangedInternal()
{
- m_positionCache->setCachedPosition(lastPosition());
+ m_positionCache.setCachedPosition(lastPosition());
// Stop all currently running timers.
stopTimers();
diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h
index 306214b..d53c827 100644
--- a/WebCore/page/Geolocation.h
+++ b/WebCore/page/Geolocation.h
@@ -128,6 +128,23 @@ private:
NotifierToIdMap m_notifierToIdMap;
};
+ class PositionCacheWrapper {
+ public:
+ PositionCacheWrapper()
+ : m_cache(GeolocationPositionCache::instance())
+ {
+ m_cache->addUser();
+ }
+ ~PositionCacheWrapper()
+ {
+ m_cache->removeUser();
+ }
+ void setCachedPosition(Geoposition* cachedPosition) { m_cache->setCachedPosition(cachedPosition); }
+ Geoposition* cachedPosition() { return m_cache->cachedPosition(); }
+ private:
+ GeolocationPositionCache* m_cache;
+ };
+
bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); }
void sendError(GeoNotifierVector&, PositionError*);
@@ -190,7 +207,7 @@ private:
} m_allowGeolocation;
#if ENABLE(GEOLOCATION)
- OwnPtr<GeolocationPositionCache> m_positionCache;
+ PositionCacheWrapper m_positionCache;
#endif
GeoNotifierSet m_requestsAwaitingCachedPosition;
};
diff --git a/WebCore/page/GeolocationClient.h b/WebCore/page/GeolocationClient.h
index c646f91..44cb909 100644
--- a/WebCore/page/GeolocationClient.h
+++ b/WebCore/page/GeolocationClient.h
@@ -28,6 +28,7 @@
namespace WebCore {
+class Geolocation;
class GeolocationPosition;
class GeolocationClient {
@@ -43,6 +44,9 @@ public:
virtual void setEnableHighAccuracy(bool) = 0;
virtual GeolocationPosition* lastPosition() = 0;
+ virtual void requestPermission(Geolocation*) = 0;
+ virtual void cancelPermissionRequest(Geolocation*) = 0;
+
protected:
virtual ~GeolocationClient() { }
};
diff --git a/WebCore/page/GeolocationController.cpp b/WebCore/page/GeolocationController.cpp
index db4cc23..28d522d 100644
--- a/WebCore/page/GeolocationController.cpp
+++ b/WebCore/page/GeolocationController.cpp
@@ -78,6 +78,18 @@ void GeolocationController::removeObserver(Geolocation* observer)
}
}
+void GeolocationController::requestPermission(Geolocation* geolocation)
+{
+ if (m_client)
+ m_client->requestPermission(geolocation);
+}
+
+void GeolocationController::cancelPermissionRequest(Geolocation* geolocation)
+{
+ if (m_client)
+ m_client->cancelPermissionRequest(geolocation);
+}
+
void GeolocationController::positionChanged(GeolocationPosition* position)
{
m_lastPosition = position;
diff --git a/WebCore/page/GeolocationController.h b/WebCore/page/GeolocationController.h
index 2d8106d..7db1951 100644
--- a/WebCore/page/GeolocationController.h
+++ b/WebCore/page/GeolocationController.h
@@ -48,6 +48,9 @@ public:
void addObserver(Geolocation*, bool enableHighAccuracy);
void removeObserver(Geolocation*);
+ void requestPermission(Geolocation*);
+ void cancelPermissionRequest(Geolocation*);
+
void positionChanged(GeolocationPosition*);
void errorOccurred(GeolocationError*);
diff --git a/WebCore/page/GeolocationPositionCache.cpp b/WebCore/page/GeolocationPositionCache.cpp
index 06159f4..4a9c6b7 100644
--- a/WebCore/page/GeolocationPositionCache.cpp
+++ b/WebCore/page/GeolocationPositionCache.cpp
@@ -28,64 +28,118 @@
#if ENABLE(GEOLOCATION)
+#include "CrossThreadTask.h"
#include "Geoposition.h"
#include "SQLValue.h"
#include "SQLiteDatabase.h"
#include "SQLiteFileSystem.h"
#include "SQLiteStatement.h"
#include "SQLiteTransaction.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Threading.h>
+
+using namespace WTF;
namespace WebCore {
-static const char* databaseName = "CachedGeoposition.db";
+static int numUsers = 0;
-int GeolocationPositionCache::s_instances = 0;
-RefPtr<Geoposition>* GeolocationPositionCache::s_cachedPosition;
-String* GeolocationPositionCache::s_databaseFile = 0;
+GeolocationPositionCache* GeolocationPositionCache::instance()
+{
+ DEFINE_STATIC_LOCAL(GeolocationPositionCache*, instance, (0));
+ if (!instance)
+ instance = new GeolocationPositionCache();
+ return instance;
+}
GeolocationPositionCache::GeolocationPositionCache()
+ : m_threadId(0)
+{
+}
+
+void GeolocationPositionCache::addUser()
{
- if (!(s_instances++)) {
- s_cachedPosition = new RefPtr<Geoposition>;
- *s_cachedPosition = readFromDB();
+ ASSERT(numUsers >= 0);
+ if (!numUsers && !m_threadId) {
+ startBackgroundThread();
+ MutexLocker lock(m_cachedPositionMutex);
+ if (!m_cachedPosition)
+ triggerReadFromDatabase();
}
+ ++numUsers;
}
-GeolocationPositionCache::~GeolocationPositionCache()
+void GeolocationPositionCache::removeUser()
{
- if (!(--s_instances)) {
- if (*s_cachedPosition)
- writeToDB(s_cachedPosition->get());
- delete s_cachedPosition;
+ MutexLocker lock(m_cachedPositionMutex);
+ --numUsers;
+ ASSERT(numUsers >= 0);
+ if (!numUsers && m_cachedPosition)
+ triggerWriteToDatabase();
+}
+
+void GeolocationPositionCache::setDatabasePath(const String& path)
+{
+ static const char* databaseName = "CachedGeoposition.db";
+ String newFile = SQLiteFileSystem::appendDatabaseFileNameToPath(path, databaseName);
+ MutexLocker lock(m_databaseFileMutex);
+ if (m_databaseFile != newFile) {
+ m_databaseFile = newFile;
+ if (numUsers && !m_cachedPosition)
+ triggerReadFromDatabase();
}
}
void GeolocationPositionCache::setCachedPosition(Geoposition* cachedPosition)
{
- *s_cachedPosition = cachedPosition;
+ MutexLocker lock(m_cachedPositionMutex);
+ m_cachedPosition = cachedPosition;
}
Geoposition* GeolocationPositionCache::cachedPosition()
{
- return s_cachedPosition->get();
+ MutexLocker lock(m_cachedPositionMutex);
+ return m_cachedPosition.get();
+}
+
+void GeolocationPositionCache::startBackgroundThread()
+{
+ // FIXME: Consider sharing this thread with other background tasks.
+ m_threadId = createThread(threadEntryPoint, this, "WebCore: GeolocationPositionCache");
+}
+
+void* GeolocationPositionCache::threadEntryPoint(void* object)
+{
+ static_cast<GeolocationPositionCache*>(object)->threadEntryPointImpl();
+ return 0;
+}
+
+void GeolocationPositionCache::threadEntryPointImpl()
+{
+ while (OwnPtr<ScriptExecutionContext::Task> task = m_queue.waitForMessage()) {
+ // We don't need a ScriptExecutionContext in the callback, so pass 0 here.
+ task->performTask(0);
+ }
+}
+
+void GeolocationPositionCache::triggerReadFromDatabase()
+{
+ m_queue.append(createCallbackTask(&GeolocationPositionCache::readFromDatabase, this));
}
-void GeolocationPositionCache::setDatabasePath(const String& databasePath)
+void GeolocationPositionCache::readFromDatabase(ScriptExecutionContext*, GeolocationPositionCache* cache)
{
- if (!s_databaseFile)
- s_databaseFile = new String;
- *s_databaseFile = SQLiteFileSystem::appendDatabaseFileNameToPath(databasePath, databaseName);
- // If we don't have have a cached position, attempt to read one from the
- // DB at the new path.
- if (s_instances && !(*s_cachedPosition))
- *s_cachedPosition = readFromDB();
+ cache->readFromDatabaseImpl();
}
-PassRefPtr<Geoposition> GeolocationPositionCache::readFromDB()
+void GeolocationPositionCache::readFromDatabaseImpl()
{
SQLiteDatabase database;
- if (!s_databaseFile || !database.open(*s_databaseFile))
- return 0;
+ {
+ MutexLocker lock(m_databaseFileMutex);
+ if (!database.open(m_databaseFile))
+ return;
+ }
// Create the table here, such that even if we've just created the
// DB, the commands below should succeed.
@@ -98,14 +152,14 @@ PassRefPtr<Geoposition> GeolocationPositionCache::readFromDB()
"heading REAL, "
"speed REAL, "
"timestamp INTEGER NOT NULL)"))
- return 0;
+ return;
SQLiteStatement statement(database, "SELECT * FROM CachedPosition");
if (statement.prepare() != SQLResultOk)
- return 0;
+ return;
if (statement.step() != SQLResultRow)
- return 0;
+ return;
bool providesAltitude = statement.getColumnValue(2).type() != SQLValue::NullValue;
bool providesAltitudeAccuracy = statement.getColumnValue(4).type() != SQLValue::NullValue;
@@ -118,16 +172,40 @@ PassRefPtr<Geoposition> GeolocationPositionCache::readFromDB()
providesAltitudeAccuracy, statement.getColumnDouble(4), // altitudeAccuracy
providesHeading, statement.getColumnDouble(5), // heading
providesSpeed, statement.getColumnDouble(6)); // speed
- return Geoposition::create(coordinates.release(), statement.getColumnInt64(7)); // timestamp
+ DOMTimeStamp timestamp = statement.getColumnInt64(7); // timestamp
+
+ // A position may have been set since we called triggerReadFromDatabase().
+ MutexLocker lock(m_cachedPositionMutex);
+ if (m_cachedPosition)
+ return;
+ m_cachedPosition = Geoposition::create(coordinates.release(), timestamp);
}
-void GeolocationPositionCache::writeToDB(const Geoposition* position)
+void GeolocationPositionCache::triggerWriteToDatabase()
{
- ASSERT(position);
+ m_queue.append(createCallbackTask(writeToDatabase, this));
+}
+void GeolocationPositionCache::writeToDatabase(ScriptExecutionContext*, GeolocationPositionCache* cache)
+{
+ cache->writeToDatabaseImpl();
+}
+
+void GeolocationPositionCache::writeToDatabaseImpl()
+{
SQLiteDatabase database;
- if (!s_databaseFile || !database.open(*s_databaseFile))
- return;
+ {
+ MutexLocker lock(m_databaseFileMutex);
+ if (!database.open(m_databaseFile))
+ return;
+ }
+
+ RefPtr<Geoposition> cachedPosition;
+ {
+ MutexLocker lock(m_cachedPositionMutex);
+ if (m_cachedPosition)
+ cachedPosition = m_cachedPosition->threadSafeCopy();
+ }
SQLiteTransaction transaction(database);
@@ -147,26 +225,27 @@ void GeolocationPositionCache::writeToDB(const Geoposition* position)
if (statement.prepare() != SQLResultOk)
return;
- statement.bindDouble(1, position->coords()->latitude());
- statement.bindDouble(2, position->coords()->longitude());
- if (position->coords()->canProvideAltitude())
- statement.bindDouble(3, position->coords()->altitude());
+ statement.bindDouble(1, cachedPosition->coords()->latitude());
+ statement.bindDouble(2, cachedPosition->coords()->longitude());
+ if (cachedPosition->coords()->canProvideAltitude())
+ statement.bindDouble(3, cachedPosition->coords()->altitude());
else
statement.bindNull(3);
- statement.bindDouble(4, position->coords()->accuracy());
- if (position->coords()->canProvideAltitudeAccuracy())
- statement.bindDouble(5, position->coords()->altitudeAccuracy());
+ statement.bindDouble(4, cachedPosition->coords()->accuracy());
+ if (cachedPosition->coords()->canProvideAltitudeAccuracy())
+ statement.bindDouble(5, cachedPosition->coords()->altitudeAccuracy());
else
statement.bindNull(5);
- if (position->coords()->canProvideHeading())
- statement.bindDouble(6, position->coords()->heading());
+ if (cachedPosition->coords()->canProvideHeading())
+ statement.bindDouble(6, cachedPosition->coords()->heading());
else
statement.bindNull(6);
- if (position->coords()->canProvideSpeed())
- statement.bindDouble(7, position->coords()->speed());
+ if (cachedPosition->coords()->canProvideSpeed())
+ statement.bindDouble(7, cachedPosition->coords()->speed());
else
statement.bindNull(7);
- statement.bindInt64(8, position->timestamp());
+ statement.bindInt64(8, cachedPosition->timestamp());
+
if (!statement.executeCommand())
return;
diff --git a/WebCore/page/GeolocationPositionCache.h b/WebCore/page/GeolocationPositionCache.h
index dd57180..1398850 100644
--- a/WebCore/page/GeolocationPositionCache.h
+++ b/WebCore/page/GeolocationPositionCache.h
@@ -26,31 +26,53 @@
#ifndef GeolocationPositionCache_h
#define GeolocationPositionCache_h
+#include "PlatformString.h"
+#include "ScriptExecutionContext.h"
+
#include <wtf/Forward.h>
+#include <wtf/MessageQueue.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
-
namespace WebCore {
class Geoposition;
+// Maintains a cached position for Geolocation. Takes care of writing and
+// reading the position to a database on a background thread. The Geolocation
+// spec does not require a cached position to be maintained, so we take a
+// best-effort approach where we do not wait for database reads or writes.
class GeolocationPositionCache {
- public:
- GeolocationPositionCache();
- ~GeolocationPositionCache();
+public:
+ static GeolocationPositionCache* instance();
+
+ void addUser();
+ void removeUser();
+ void setDatabasePath(const String&);
void setCachedPosition(Geoposition*);
Geoposition* cachedPosition();
- static void setDatabasePath(const String&);
- private:
- static PassRefPtr<Geoposition> readFromDB();
- static void writeToDB(const Geoposition*);
+private:
+ GeolocationPositionCache();
+
+ void startBackgroundThread();
+ static void* threadEntryPoint(void* object);
+ void threadEntryPointImpl();
+
+ void triggerReadFromDatabase();
+ static void readFromDatabase(ScriptExecutionContext*, GeolocationPositionCache*);
+ void readFromDatabaseImpl();
+ void triggerWriteToDatabase();
+ static void writeToDatabase(ScriptExecutionContext*, GeolocationPositionCache*);
+ void writeToDatabaseImpl();
- static int s_instances;
- static RefPtr<Geoposition>* s_cachedPosition;
- static String* s_databaseFile;
+ RefPtr<Geoposition> m_cachedPosition;
+ Mutex m_cachedPositionMutex;
+ ThreadIdentifier m_threadId;
+ MessageQueue<ScriptExecutionContext::Task> m_queue;
+ String m_databaseFile;
+ Mutex m_databaseFileMutex;
};
} // namespace WebCore
diff --git a/WebCore/page/Geoposition.h b/WebCore/page/Geoposition.h
index 8b215b1..83d865a 100644
--- a/WebCore/page/Geoposition.h
+++ b/WebCore/page/Geoposition.h
@@ -33,8 +33,6 @@
namespace WebCore {
-typedef int ExceptionCode;
-
class Geoposition : public RefCounted<Geoposition> {
public:
static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp)
@@ -42,6 +40,11 @@ public:
return adoptRef(new Geoposition(coordinates, timestamp));
}
+ PassRefPtr<Geoposition> threadSafeCopy() const
+ {
+ return Geoposition::create(m_coordinates->threadSafeCopy(), m_timestamp);
+ }
+
DOMTimeStamp timestamp() const { return m_timestamp; }
Coordinates* coords() const { return m_coordinates.get(); }
@@ -50,6 +53,7 @@ private:
: m_coordinates(coordinates)
, m_timestamp(timestamp)
{
+ ASSERT(m_coordinates);
}
RefPtr<Coordinates> m_coordinates;
diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp
index 5453e1e..6d583b4 100644
--- a/WebCore/page/Page.cpp
+++ b/WebCore/page/Page.cpp
@@ -525,25 +525,31 @@ static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity, FindDirection direction, bool shouldWrap)
{
+ return findString(target, (caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0) | (direction == FindDirectionBackward ? Backwards : 0) | (shouldWrap ? WrapAround : 0));
+}
+
+bool Page::findString(const String& target, FindOptions options)
+{
if (target.isEmpty() || !mainFrame())
return false;
+ bool shouldWrap = options & WrapAround;
Frame* frame = focusController()->focusedOrMainFrame();
Frame* startFrame = frame;
do {
- if (frame->editor()->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, false, true)) {
+ if (frame->editor()->findString(target, (options & ~WrapAround) | StartInSelection)) {
if (frame != startFrame)
startFrame->selection()->clear();
focusController()->setFocusedFrame(frame);
return true;
}
- frame = incrementFrame(frame, direction == FindDirectionForward, shouldWrap);
+ frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
} while (frame && frame != startFrame);
// Search contents of startFrame, on the other side of the selection that we did earlier.
// We cheat a bit and just research with wrap on
if (shouldWrap && !startFrame->selection()->isNone()) {
- bool found = startFrame->editor()->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, true, true);
+ bool found = startFrame->editor()->findString(target, options | WrapAround | StartInSelection);
focusController()->setFocusedFrame(frame);
return found;
}
@@ -553,6 +559,11 @@ bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity,
unsigned int Page::markAllMatchesForText(const String& target, TextCaseSensitivity caseSensitivity, bool shouldHighlight, unsigned limit)
{
+ return markAllMatchesForText(target, caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0, shouldHighlight, limit);
+}
+
+unsigned int Page::markAllMatchesForText(const String& target, FindOptions options, bool shouldHighlight, unsigned limit)
+{
if (target.isEmpty() || !mainFrame())
return 0;
@@ -561,7 +572,7 @@ unsigned int Page::markAllMatchesForText(const String& target, TextCaseSensitivi
Frame* frame = mainFrame();
do {
frame->editor()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
- matches += frame->editor()->countMatchesForText(target, caseSensitivity == TextCaseSensitive, limit ? (limit - matches) : 0, true);
+ matches += frame->editor()->countMatchesForText(target, options, limit ? (limit - matches) : 0, true);
frame = incrementFrame(frame, true, false);
} while (frame);
@@ -872,6 +883,12 @@ SpeechInput* Page::speechInput()
}
#endif
+void Page::dnsPrefetchingStateChanged()
+{
+ for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
+ frame->document()->initDNSPrefetch();
+}
+
void Page::privateBrowsingStateChanged()
{
bool privateBrowsingEnabled = m_settings->privateBrowsingEnabled();
diff --git a/WebCore/page/Page.h b/WebCore/page/Page.h
index e074814..7413bb6 100644
--- a/WebCore/page/Page.h
+++ b/WebCore/page/Page.h
@@ -22,6 +22,7 @@
#define Page_h
#include "FrameLoaderTypes.h"
+#include "FindOptions.h"
#include "PlatformString.h"
#include "ViewportArguments.h"
#include <wtf/Forward.h>
@@ -198,8 +199,12 @@ namespace WebCore {
void setTabKeyCyclesThroughElements(bool b) { m_tabKeyCyclesThroughElements = b; }
bool tabKeyCyclesThroughElements() const { return m_tabKeyCyclesThroughElements; }
+ bool findString(const String&, FindOptions);
+ // FIXME: Switch callers over to the FindOptions version and retire this one.
bool findString(const String&, TextCaseSensitivity, FindDirection, bool shouldWrap);
- unsigned int markAllMatchesForText(const String&, TextCaseSensitivity, bool shouldHighlight, unsigned);
+ unsigned markAllMatchesForText(const String&, FindOptions, bool shouldHighlight, unsigned);
+ // FIXME: Switch callers over to the FindOptions version and retire this one.
+ unsigned markAllMatchesForText(const String&, TextCaseSensitivity, bool shouldHighlight, unsigned);
void unmarkAllTextMatches();
#if PLATFORM(MAC)
@@ -233,6 +238,7 @@ namespace WebCore {
void userStyleSheetLocationChanged();
const String& userStyleSheet() const;
+ void dnsPrefetchingStateChanged();
void privateBrowsingStateChanged();
void didStartPlugin(HaltablePlugin*);
diff --git a/WebCore/page/PerformanceNavigation.cpp b/WebCore/page/PerformanceNavigation.cpp
index d570561..597af20 100644
--- a/WebCore/page/PerformanceNavigation.cpp
+++ b/WebCore/page/PerformanceNavigation.cpp
@@ -57,20 +57,20 @@ void PerformanceNavigation::disconnectFrame()
unsigned short PerformanceNavigation::type() const
{
if (!m_frame)
- return NAVIGATE;
+ return TYPE_NAVIGATE;
DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
if (!documentLoader)
- return NAVIGATE;
+ return TYPE_NAVIGATE;
WebCore::NavigationType navigationType = documentLoader->triggeringAction().type();
switch (navigationType) {
case NavigationTypeReload:
- return RELOAD;
+ return TYPE_RELOAD;
case NavigationTypeBackForward:
- return BACK_FORWARD;
+ return TYPE_BACK_FORWARD;
default:
- return NAVIGATE;
+ return TYPE_NAVIGATE;
}
}
diff --git a/WebCore/page/PerformanceNavigation.h b/WebCore/page/PerformanceNavigation.h
index 2ba9b9c..bdf6eaa 100644
--- a/WebCore/page/PerformanceNavigation.h
+++ b/WebCore/page/PerformanceNavigation.h
@@ -48,9 +48,10 @@ public:
void disconnectFrame();
enum PerformanceNavigationType {
- NAVIGATE,
- RELOAD,
- BACK_FORWARD
+ TYPE_NAVIGATE,
+ TYPE_RELOAD,
+ TYPE_BACK_FORWARD,
+ TYPE_RESERVED = 255
};
unsigned short type() const;
diff --git a/WebCore/page/PerformanceNavigation.idl b/WebCore/page/PerformanceNavigation.idl
index 5c06050..d16bcba 100644
--- a/WebCore/page/PerformanceNavigation.idl
+++ b/WebCore/page/PerformanceNavigation.idl
@@ -30,11 +30,12 @@
module window {
- // See: http://dev.w3.org/2006/webapi/WebTiming/
+ // See: http://www.w3.org/TR/navigation-timing/
interface [Conditional=WEB_TIMING, OmitConstructor] PerformanceNavigation {
- const unsigned short NAVIGATE = 0;
- const unsigned short RELOAD = 1;
- const unsigned short BACK_FORWARD = 2;
+ const unsigned short TYPE_NAVIGATE = 0;
+ const unsigned short TYPE_RELOAD = 1;
+ const unsigned short TYPE_BACK_FORWARD = 2;
+ const unsigned short TYPE_RESERVED = 255;
readonly attribute unsigned short type;
readonly attribute unsigned short redirectCount;
diff --git a/WebCore/page/PerformanceTiming.cpp b/WebCore/page/PerformanceTiming.cpp
index 82b7027..47f9278 100644
--- a/WebCore/page/PerformanceTiming.cpp
+++ b/WebCore/page/PerformanceTiming.cpp
@@ -184,7 +184,7 @@ unsigned long long PerformanceTiming::connectStart() const
if (connectStart < 0 || loader->response().connectionReused())
return domainLookupEnd();
- // ResourceLoadTiming's connect phase includes DNS and SSL, however Web Timing's
+ // ResourceLoadTiming's connect phase includes DNS, however Navigation Timing's
// connect phase should not. So if there is DNS time, trim it from the start.
if (timing->dnsEnd >= 0 && timing->dnsEnd > connectStart)
connectStart = timing->dnsEnd;
@@ -208,14 +208,26 @@ unsigned long long PerformanceTiming::connectEnd() const
if (connectEnd < 0 || loader->response().connectionReused())
return connectStart();
- // ResourceLoadTiming's connect phase includes DNS and SSL, however Web Timing's
- // connect phase should not. So if there is SSL time, trim it from the end.
- if (timing->sslStart >= 0 && timing->sslStart < connectEnd)
- connectEnd = timing->sslStart;
-
return resourceLoadTimeRelativeToAbsolute(connectEnd);
}
+unsigned long long PerformanceTiming::sslHandshakeStart() const
+{
+ DocumentLoader* loader = documentLoader();
+ if (!loader)
+ return 0;
+
+ ResourceLoadTiming* timing = loader->response().resourceLoadTiming();
+ if (!timing)
+ return 0;
+
+ int sslStart = timing->sslStart;
+ if (sslStart < 0)
+ return 0;
+
+ return resourceLoadTimeRelativeToAbsolute(sslStart);
+}
+
unsigned long long PerformanceTiming::requestStart() const
{
ResourceLoadTiming* timing = resourceLoadTiming();
@@ -269,22 +281,22 @@ unsigned long long PerformanceTiming::domInteractive() const
return toIntegerMilliseconds(timing->domInteractive);
}
-unsigned long long PerformanceTiming::domContentLoadedStart() const
+unsigned long long PerformanceTiming::domContentLoadedEventStart() const
{
const DocumentTiming* timing = documentTiming();
if (!timing)
return 0;
- return toIntegerMilliseconds(timing->domContentLoadedStart);
+ return toIntegerMilliseconds(timing->domContentLoadedEventStart);
}
-unsigned long long PerformanceTiming::domContentLoadedEnd() const
+unsigned long long PerformanceTiming::domContentLoadedEventEnd() const
{
const DocumentTiming* timing = documentTiming();
if (!timing)
return 0;
- return toIntegerMilliseconds(timing->domContentLoadedEnd);
+ return toIntegerMilliseconds(timing->domContentLoadedEventEnd);
}
unsigned long long PerformanceTiming::domComplete() const
diff --git a/WebCore/page/PerformanceTiming.h b/WebCore/page/PerformanceTiming.h
index 3b5e8b4..9c35672 100644
--- a/WebCore/page/PerformanceTiming.h
+++ b/WebCore/page/PerformanceTiming.h
@@ -61,13 +61,14 @@ public:
unsigned long long domainLookupEnd() const;
unsigned long long connectStart() const;
unsigned long long connectEnd() const;
+ unsigned long long sslHandshakeStart() const;
unsigned long long requestStart() const;
unsigned long long responseStart() const;
unsigned long long responseEnd() const;
unsigned long long domLoading() const;
unsigned long long domInteractive() const;
- unsigned long long domContentLoadedStart() const;
- unsigned long long domContentLoadedEnd() const;
+ unsigned long long domContentLoadedEventStart() const;
+ unsigned long long domContentLoadedEventEnd() const;
unsigned long long domComplete() const;
unsigned long long loadEventStart() const;
unsigned long long loadEventEnd() const;
diff --git a/WebCore/page/PerformanceTiming.idl b/WebCore/page/PerformanceTiming.idl
index a13b8d7..a0f08e2 100644
--- a/WebCore/page/PerformanceTiming.idl
+++ b/WebCore/page/PerformanceTiming.idl
@@ -42,13 +42,14 @@ module window {
readonly attribute unsigned long long domainLookupEnd;
readonly attribute unsigned long long connectStart;
readonly attribute unsigned long long connectEnd;
+ readonly attribute unsigned long long sslHandshakeStart;
readonly attribute unsigned long long requestStart;
readonly attribute unsigned long long responseStart;
readonly attribute unsigned long long responseEnd;
readonly attribute unsigned long long domLoading;
readonly attribute unsigned long long domInteractive;
- readonly attribute unsigned long long domContentLoadedStart;
- readonly attribute unsigned long long domContentLoadedEnd;
+ readonly attribute unsigned long long domContentLoadedEventStart;
+ readonly attribute unsigned long long domContentLoadedEventEnd;
readonly attribute unsigned long long domComplete;
readonly attribute unsigned long long loadEventStart;
readonly attribute unsigned long long loadEventEnd;
diff --git a/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp
index 82af42a..a753c6d 100644
--- a/WebCore/page/SecurityOrigin.cpp
+++ b/WebCore/page/SecurityOrigin.cpp
@@ -319,17 +319,6 @@ bool SecurityOrigin::canDisplay(const KURL& url) const
return canLoadLocalResources();
}
-bool SecurityOrigin::deprecatedCanDisplay(const String& referrer, const KURL& url)
-{
- if (!restrictAccessToLocal())
- return true;
-
- if (!SchemeRegistry::shouldTreatURLAsLocal(url.string()))
- return true;
-
- return SchemeRegistry::shouldTreatURLAsLocal(referrer);
-}
-
void SecurityOrigin::grantLoadLocalResources()
{
// This function exists only to support backwards compatibility with older
diff --git a/WebCore/page/SecurityOrigin.h b/WebCore/page/SecurityOrigin.h
index db6c44e..6bdb28c 100644
--- a/WebCore/page/SecurityOrigin.h
+++ b/WebCore/page/SecurityOrigin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007,2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,14 +29,9 @@
#ifndef SecurityOrigin_h
#define SecurityOrigin_h
-#include <wtf/HashSet.h>
-#include <wtf/RefCounted.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/Threading.h>
-#include <wtf/text/StringHash.h>
-
#include "FrameLoaderTypes.h"
#include "PlatformString.h"
+#include <wtf/ThreadSafeShared.h>
namespace WebCore {
@@ -94,9 +89,6 @@ public:
// display content from the user's files system.
bool canDisplay(const KURL&) const;
- // FIXME: Remove this function. This function exists only to service FrameLoader.
- static bool deprecatedCanDisplay(const String& referrer, const KURL& targetURL);
-
// Returns true if this SecurityOrigin can load local resources, such
// as images, iframes, and style sheets, and can link to local URLs.
// For example, call this function before creating an iframe to a
diff --git a/WebCore/page/Settings.cpp b/WebCore/page/Settings.cpp
index d150033..8b174be 100644
--- a/WebCore/page/Settings.cpp
+++ b/WebCore/page/Settings.cpp
@@ -172,10 +172,11 @@ Settings::Settings(Page* page)
, m_loadDeferringEnabled(true)
, m_tiledBackingStoreEnabled(false)
, m_paginateDuringLayoutEnabled(false)
- , m_dnsPrefetchingEnabled(true)
+ , m_dnsPrefetchingEnabled(false)
#if ENABLE(FULLSCREEN_API)
, m_fullScreenAPIEnabled(false)
#endif
+ , m_asynchronousSpellCheckingEnabled(false)
, m_memoryInfoEnabled(false)
, m_interactiveFormValidation(false)
, m_usePreHTML5ParserQuirks(false)
@@ -759,7 +760,11 @@ void Settings::setUsesEncodingDetector(bool usesEncodingDetector)
void Settings::setDNSPrefetchingEnabled(bool dnsPrefetchingEnabled)
{
+ if (m_dnsPrefetchingEnabled == dnsPrefetchingEnabled)
+ return;
+
m_dnsPrefetchingEnabled = dnsPrefetchingEnabled;
+ m_page->dnsPrefetchingStateChanged();
}
void Settings::setAllowScriptsToCloseWindows(bool allowScriptsToCloseWindows)
diff --git a/WebCore/page/Settings.h b/WebCore/page/Settings.h
index e4cccb1..f6b2e2d 100644
--- a/WebCore/page/Settings.h
+++ b/WebCore/page/Settings.h
@@ -399,6 +399,9 @@ namespace WebCore {
bool fullScreenEnabled() const { return m_fullScreenAPIEnabled; }
#endif
+ void setAsynchronousSpellCheckingEnabled(bool flag) { m_asynchronousSpellCheckingEnabled = flag; }
+ bool asynchronousSpellCheckingEnabled() const { return m_asynchronousSpellCheckingEnabled; }
+
void setMemoryInfoEnabled(bool flag) { m_memoryInfoEnabled = flag; }
bool memoryInfoEnabled() const { return m_memoryInfoEnabled; }
@@ -549,6 +552,7 @@ namespace WebCore {
#if ENABLE(FULLSCREEN_API)
bool m_fullScreenAPIEnabled : 1;
#endif
+ bool m_asynchronousSpellCheckingEnabled: 1;
bool m_memoryInfoEnabled: 1;
bool m_interactiveFormValidation: 1;
bool m_usePreHTML5ParserQuirks: 1;
diff --git a/WebCore/page/SpatialNavigation.cpp b/WebCore/page/SpatialNavigation.cpp
index c7bdb51..5cb3c95 100644
--- a/WebCore/page/SpatialNavigation.cpp
+++ b/WebCore/page/SpatialNavigation.cpp
@@ -32,7 +32,10 @@
#include "Frame.h"
#include "FrameTree.h"
#include "FrameView.h"
-#include "HTMLFrameOwnerElement.h"
+#include "HTMLAreaElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLMapElement.h"
+#include "HTMLNames.h"
#include "IntRect.h"
#include "Node.h"
#include "Page.h"
@@ -47,21 +50,41 @@ static bool areRectsPartiallyAligned(FocusDirection, const IntRect&, const IntRe
static bool areRectsMoreThanFullScreenApart(FocusDirection direction, const IntRect& curRect, const IntRect& targetRect, const IntSize& viewSize);
static bool isRectInDirection(FocusDirection, const IntRect&, const IntRect&);
static void deflateIfOverlapped(IntRect&, IntRect&);
-static IntRect rectToAbsoluteCoordinates(Frame* initialFrame, const IntRect& rect);
+static IntRect rectToAbsoluteCoordinates(Frame* initialFrame, const IntRect&);
static void entryAndExitPointsForDirection(FocusDirection direction, const IntRect& startingRect, const IntRect& potentialRect, IntPoint& exitPoint, IntPoint& entryPoint);
+static bool isScrollableContainerNode(const Node*);
-
-FocusCandidate::FocusCandidate(Node* n, FocusDirection direction)
- : node(n)
+FocusCandidate::FocusCandidate(Node* node, FocusDirection direction)
+ : visibleNode(0)
+ , focusableNode(0)
, enclosingScrollableBox(0)
, distance(maxDistance())
, parentDistance(maxDistance())
, alignment(None)
, parentAlignment(None)
- , rect(nodeRectInAbsoluteCoordinates(n, true /* ignore border */))
- , isOffscreen(hasOffscreenRect(n))
- , isOffscreenAfterScrolling(hasOffscreenRect(n, direction))
+ , isOffscreen(true)
+ , isOffscreenAfterScrolling(true)
{
+ ASSERT(node);
+ if (node->hasTagName(HTMLNames::areaTag)) {
+ HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
+ HTMLImageElement* image = area->imageElement();
+ if (!image || !image->renderer())
+ return;
+
+ visibleNode = image;
+ rect = virtualRectForAreaElementAndDirection(direction, area);
+ } else {
+ if (!node->renderer())
+ return;
+
+ visibleNode = node;
+ rect = nodeRectInAbsoluteCoordinates(node, true /* ignore border */);
+ }
+
+ focusableNode = node;
+ isOffscreen = hasOffscreenRect(visibleNode);
+ isOffscreenAfterScrolling = hasOffscreenRect(visibleNode, direction);
}
bool isSpatialNavigationEnabled(const Frame* frame)
@@ -311,7 +334,7 @@ bool hasOffscreenRect(Node* node, FocusDirection direction)
bool scrollInDirection(Frame* frame, FocusDirection direction)
{
- ASSERT(frame && canScrollInDirection(direction, frame->document()));
+ ASSERT(frame);
if (frame && canScrollInDirection(direction, frame->document())) {
int dx = 0;
@@ -342,13 +365,14 @@ bool scrollInDirection(Frame* frame, FocusDirection direction)
bool scrollInDirection(Node* container, FocusDirection direction)
{
+ ASSERT(container);
if (container->isDocumentNode())
return scrollInDirection(static_cast<Document*>(container)->frame(), direction);
if (!container->renderBox())
return false;
- if (container && canScrollInDirection(direction, container)) {
+ if (canScrollInDirection(direction, container)) {
int dx = 0;
int dy = 0;
switch (direction) {
@@ -374,6 +398,7 @@ bool scrollInDirection(Node* container, FocusDirection direction)
container->renderBox()->enclosingLayer()->scrollByRecursively(dx, dy);
return true;
}
+
return false;
}
@@ -567,11 +592,11 @@ void entryAndExitPointsForDirection(FocusDirection direction, const IntRect& sta
}
}
-void distanceDataForNode(FocusDirection direction, FocusCandidate& current, FocusCandidate& candidate)
+void distanceDataForNode(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate)
{
if (candidate.isNull())
return;
- if (!candidate.node->renderer())
+ if (!candidate.visibleNode->renderer())
return;
IntRect nodeRect = candidate.rect;
IntRect currentRect = current.rect;
@@ -618,15 +643,15 @@ void distanceDataForNode(FocusDirection direction, FocusCandidate& current, Focu
float distance = euclidianDistance + sameAxisDistance + 2 * otherAxisDistance;
candidate.distance = roundf(distance);
- IntSize viewSize = candidate.node->document()->page()->mainFrame()->view()->visibleContentRect().size();
+ IntSize viewSize = candidate.visibleNode->document()->page()->mainFrame()->view()->visibleContentRect().size();
candidate.alignment = alignmentForRects(direction, currentRect, nodeRect, viewSize);
}
bool canBeScrolledIntoView(FocusDirection direction, const FocusCandidate& candidate)
{
- ASSERT(candidate.node && candidate.isOffscreen);
+ ASSERT(candidate.visibleNode && candidate.isOffscreen);
IntRect candidateRect = candidate.rect;
- for (Node* parentNode = candidate.node->parent(); parentNode; parentNode = parentNode->parent()) {
+ for (Node* parentNode = candidate.visibleNode->parentNode(); parentNode; parentNode = parentNode->parentNode()) {
IntRect parentRect = nodeRectInAbsoluteCoordinates(parentNode);
if (!candidateRect.intersects(parentRect)) {
if (((direction == FocusDirectionLeft || direction == FocusDirectionRight) && parentNode->renderer()->style()->overflowX() == OHIDDEN)
@@ -643,23 +668,23 @@ bool canBeScrolledIntoView(FocusDirection direction, const FocusCandidate& candi
// Compose a virtual starting rect if there is no focused node or if it is off screen.
// The virtual rect is the edge of the container or frame. We select which
// edge depending on the direction of the navigation.
-IntRect virtualRectForDirection(FocusDirection direction, const IntRect& startingRect)
+IntRect virtualRectForDirection(FocusDirection direction, const IntRect& startingRect, int width)
{
IntRect virtualStartingRect = startingRect;
switch (direction) {
case FocusDirectionLeft:
- virtualStartingRect.setX(virtualStartingRect.right());
- virtualStartingRect.setWidth(0);
+ virtualStartingRect.setX(virtualStartingRect.right() - width);
+ virtualStartingRect.setWidth(width);
break;
case FocusDirectionUp:
- virtualStartingRect.setY(virtualStartingRect.bottom());
- virtualStartingRect.setHeight(0);
+ virtualStartingRect.setY(virtualStartingRect.bottom() - width);
+ virtualStartingRect.setHeight(width);
break;
case FocusDirectionRight:
- virtualStartingRect.setWidth(0);
+ virtualStartingRect.setWidth(width);
break;
case FocusDirectionDown:
- virtualStartingRect.setHeight(0);
+ virtualStartingRect.setHeight(width);
break;
default:
ASSERT_NOT_REACHED();
@@ -668,5 +693,19 @@ IntRect virtualRectForDirection(FocusDirection direction, const IntRect& startin
return virtualStartingRect;
}
+IntRect virtualRectForAreaElementAndDirection(FocusDirection direction, HTMLAreaElement* area)
+{
+ ASSERT(area);
+ ASSERT(area->imageElement());
+ // Area elements tend to overlap more than other focusable elements. We flatten the rect of the area elements
+ // to minimize the effect of overlapping areas.
+ IntRect rect = virtualRectForDirection(direction, rectToAbsoluteCoordinates(area->document()->frame(), area->getRect(area->imageElement()->renderer())), 1);
+ return rect;
+}
+
+HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate& candidate)
+{
+ return candidate.isFrameOwnerElement() ? static_cast<HTMLFrameOwnerElement*>(candidate.visibleNode) : 0;
+};
} // namespace WebCore
diff --git a/WebCore/page/SpatialNavigation.h b/WebCore/page/SpatialNavigation.h
index 153d0ac..a6dcf24 100644
--- a/WebCore/page/SpatialNavigation.h
+++ b/WebCore/page/SpatialNavigation.h
@@ -22,6 +22,7 @@
#define SpatialNavigation_h
#include "FocusDirection.h"
+#include "HTMLFrameOwnerElement.h"
#include "IntRect.h"
#include "Node.h"
@@ -31,6 +32,7 @@ namespace WebCore {
class Element;
class Frame;
+class HTMLAreaElement;
class IntRect;
class RenderObject;
@@ -99,7 +101,8 @@ enum RectsAlignment {
struct FocusCandidate {
FocusCandidate()
- : node(0)
+ : visibleNode(0)
+ , focusableNode(0)
, enclosingScrollableBox(0)
, distance(maxDistance())
, parentDistance(maxDistance())
@@ -111,11 +114,17 @@ struct FocusCandidate {
}
FocusCandidate(Node* n, FocusDirection);
- bool isNull() const { return !node; }
- bool inScrollableContainer() const { return node && enclosingScrollableBox; }
- Document* document() const { return node ? node->document() : 0; }
+ explicit FocusCandidate(HTMLAreaElement* area, FocusDirection);
+ bool isNull() const { return !visibleNode; }
+ bool inScrollableContainer() const { return visibleNode && enclosingScrollableBox; }
+ bool isFrameOwnerElement() const { return visibleNode && visibleNode->isFrameOwnerElement(); }
+ Document* document() const { return visibleNode ? visibleNode->document() : 0; }
- Node* node;
+ // We handle differently visibleNode and FocusableNode to properly handle the areas of imagemaps,
+ // where visibleNode would represent the image element and focusableNode would represent the area element.
+ // In all other cases, visibleNode and focusableNode are one and the same.
+ Node* visibleNode;
+ Node* focusableNode;
Node* enclosingScrollableBox;
long long distance;
long long parentDistance;
@@ -126,19 +135,20 @@ struct FocusCandidate {
bool isOffscreenAfterScrolling;
};
+bool hasOffscreenRect(Node*, FocusDirection direction = FocusDirectionNone);
bool scrollInDirection(Frame*, FocusDirection);
bool scrollInDirection(Node* container, FocusDirection);
-bool hasOffscreenRect(Node*, FocusDirection direction = FocusDirectionNone);
-bool isScrollableContainerNode(const Node*);
-bool isNodeDeepDescendantOfDocument(Node*, Document*);
-Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(FocusDirection, Node* node);
bool canScrollInDirection(FocusDirection, const Node* container);
bool canScrollInDirection(FocusDirection, const Frame*);
+bool canBeScrolledIntoView(FocusDirection, const FocusCandidate&);
+void distanceDataForNode(FocusDirection, const FocusCandidate& current, FocusCandidate& candidate);
+Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(FocusDirection, Node*);
IntRect nodeRectInAbsoluteCoordinates(Node*, bool ignoreBorder = false);
IntRect frameRectInAbsoluteCoordinates(Frame*);
-void distanceDataForNode(FocusDirection, FocusCandidate& current, FocusCandidate& candidate);
-bool canBeScrolledIntoView(FocusDirection, const FocusCandidate&);
-IntRect virtualRectForDirection(FocusDirection, const IntRect& startingRect);
+IntRect virtualRectForDirection(FocusDirection, const IntRect& startingRect, int width = 0);
+IntRect virtualRectForAreaElementAndDirection(FocusDirection, HTMLAreaElement*);
+HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate&);
+
} // namspace WebCore
#endif // SpatialNavigation_h
diff --git a/WebCore/page/WindowFeatures.cpp b/WebCore/page/WindowFeatures.cpp
index 82e36b9..a229ae1 100644
--- a/WebCore/page/WindowFeatures.cpp
+++ b/WebCore/page/WindowFeatures.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2000 Harri Porten (porten@kde.org)
* Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reseved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reseved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
*
* This library is free software; you can redistribute it and/or
@@ -23,16 +23,16 @@
#include "config.h"
#include "WindowFeatures.h"
+#include "FloatRect.h"
#include "PlatformString.h"
#include <wtf/Assertions.h>
-#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
-// Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
-static bool isSeparator(UChar c)
+// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when parsing window features.
+static bool isWindowFeaturesSeparator(UChar c)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
}
@@ -80,7 +80,7 @@ WindowFeatures::WindowFeatures(const String& features)
String buffer = features.lower();
while (i < length) {
// skip to first non-separator, but don't skip past the end of the string
- while (isSeparator(buffer[i])) {
+ while (isWindowFeaturesSeparator(buffer[i])) {
if (i >= length)
break;
i++;
@@ -88,7 +88,7 @@ WindowFeatures::WindowFeatures(const String& features)
keyBegin = i;
// skip to first separator
- while (!isSeparator(buffer[i]))
+ while (!isWindowFeaturesSeparator(buffer[i]))
i++;
keyEnd = i;
@@ -100,7 +100,7 @@ WindowFeatures::WindowFeatures(const String& features)
}
// skip to first non-separator, but don't skip past a ',' or the end of the string
- while (isSeparator(buffer[i])) {
+ while (isWindowFeaturesSeparator(buffer[i])) {
if (buffer[i] == ',' || i >= length)
break;
i++;
@@ -108,7 +108,7 @@ WindowFeatures::WindowFeatures(const String& features)
valueBegin = i;
// skip to first separator
- while (!isSeparator(buffer[i]))
+ while (!isWindowFeaturesSeparator(buffer[i]))
i++;
valueEnd = i;
@@ -125,12 +125,14 @@ void WindowFeatures::setWindowFeature(const String& keyString, const String& val
int value;
// Listing a key with no value is shorthand for key=yes
- if (valueString.length() == 0 || valueString == "yes")
+ if (valueString.isEmpty() || valueString == "yes")
value = 1;
else
value = valueString.toInt();
- // We ignore a keyString of "resizable", which is consistent with Firefox.
+ // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
+ // This is consistent with Firefox, but could also be handled at another level.
+
if (keyString == "left" || keyString == "screenx") {
xSet = true;
x = value;
@@ -159,32 +161,106 @@ void WindowFeatures::setWindowFeature(const String& keyString, const String& val
additionalFeatures.append(keyString);
}
-bool WindowFeatures::boolFeature(const HashMap<String, String>& features, const char* key, bool defaultValue)
+WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
+ : widthSet(true)
+ , heightSet(true)
+ , menuBarVisible(false)
+ , toolBarVisible(false)
+ , locationBarVisible(false)
+ , fullscreen(false)
+ , dialog(true)
{
- HashMap<String, String>::const_iterator it = features.find(key);
+ DialogFeaturesMap features;
+ parseDialogFeatures(dialogFeaturesString, features);
+
+ const bool trusted = false;
+
+ // The following features from Microsoft's documentation are not implemented:
+ // - default font settings
+ // - width, height, left, and top specified in units other than "px"
+ // - edge (sunken or raised, default is raised)
+ // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
+ // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
+ // - unadorned: trusted && boolFeature(features, "unadorned");
+
+ width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
+ height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE
+
+ x = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.right() - width, -1);
+ xSet = x > 0;
+ y = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.bottom() - height, -1);
+ ySet = y > 0;
+
+ if (boolFeature(features, "center", true)) {
+ if (!xSet) {
+ x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
+ xSet = true;
+ }
+ if (!ySet) {
+ y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
+ ySet = true;
+ }
+ }
+
+ resizable = boolFeature(features, "resizable");
+ scrollbarsVisible = boolFeature(features, "scroll", true);
+ statusBarVisible = boolFeature(features, "status", !trusted);
+}
+
+bool WindowFeatures::boolFeature(const DialogFeaturesMap& features, const char* key, bool defaultValue)
+{
+ DialogFeaturesMap::const_iterator it = features.find(key);
if (it == features.end())
return defaultValue;
const String& value = it->second;
return value.isNull() || value == "1" || value == "yes" || value == "on";
}
-float WindowFeatures::floatFeature(const HashMap<String, String>& features, const char* key, float min, float max, float defaultValue)
+float WindowFeatures::floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max, float defaultValue)
{
- HashMap<String, String>::const_iterator it = features.find(key);
+ DialogFeaturesMap::const_iterator it = features.find(key);
if (it == features.end())
return defaultValue;
- // FIXME: Can't distinguish "0q" from string with no digits in it -- both return d == 0 and ok == false.
- // Would be good to tell them apart somehow since string with no digits should be default value and
- // "0q" should be minimum value.
+ // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
+ // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
bool ok;
- double d = it->second.toDouble(&ok);
- if ((d == 0 && !ok) || isnan(d))
+ double parsedNumber = it->second.toDouble(&ok);
+ if ((parsedNumber == 0 && !ok) || isnan(parsedNumber))
return defaultValue;
- if (d < min || max <= min)
+ if (parsedNumber < min || max <= min)
return min;
- if (d > max)
+ if (parsedNumber > max)
return max;
- return static_cast<int>(d);
+ // FIXME: Seems strange to cast a double to int and then convert back to a float. Why is this a good idea?
+ return static_cast<int>(parsedNumber);
+}
+
+void WindowFeatures::parseDialogFeatures(const String& string, DialogFeaturesMap& map)
+{
+ Vector<String> vector;
+ string.split(';', vector);
+ size_t size = vector.size();
+ for (size_t i = 0; i < size; ++i) {
+ const String& featureString = vector[i];
+
+ size_t separatorPosition = featureString.find('=');
+ size_t colonPosition = featureString.find(':');
+ if (separatorPosition != notFound && colonPosition != notFound)
+ continue; // ignore strings that have both = and :
+ if (separatorPosition == notFound)
+ separatorPosition = colonPosition;
+
+ String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
+
+ // Null string for value indicates key without value.
+ String value;
+ if (separatorPosition != notFound) {
+ value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
+ value = value.left(value.find(' '));
+ }
+
+ map.set(key, value);
+ }
}
} // namespace WebCore
diff --git a/WebCore/page/WindowFeatures.h b/WebCore/page/WindowFeatures.h
index a414552..ea5768f 100644
--- a/WebCore/page/WindowFeatures.h
+++ b/WebCore/page/WindowFeatures.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2007, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,7 +34,10 @@
namespace WebCore {
+ class FloatRect;
+
struct WindowFeatures {
+ // FIXME: We can delete this constructor once V8 showModalDialog is changed to use DOMWindow.
WindowFeatures()
: xSet(false)
, ySet(false)
@@ -51,12 +54,8 @@ namespace WebCore {
{
}
- WindowFeatures(const String& features);
-
- void setWindowFeature(const String& keyString, const String& valueString);
-
- static bool boolFeature(const HashMap<String, String>& features, const char* key, bool defaultValue = false);
- static float floatFeature(const HashMap<String, String>& features, const char* key, float min, float max, float defaultValue);
+ WindowFeatures(const String& windowFeaturesString);
+ WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect);
float x;
bool xSet;
@@ -78,6 +77,15 @@ namespace WebCore {
bool dialog;
Vector<String> additionalFeatures;
+
+ // FIXME: We can make these functions private non-member functions once V8 showModalDialog is changed to use DOMWindow.
+ typedef HashMap<String, String> DialogFeaturesMap;
+ static void parseDialogFeatures(const String&, HashMap<String, String>&);
+ static bool boolFeature(const DialogFeaturesMap&, const char* key, bool defaultValue = false);
+ static float floatFeature(const DialogFeaturesMap&, const char* key, float min, float max, float defaultValue);
+
+ private:
+ void setWindowFeature(const String& keyString, const String& valueString);
};
} // namespace WebCore
diff --git a/WebCore/page/XSSAuditor.cpp b/WebCore/page/XSSAuditor.cpp
index 1940d52..1b0e83f 100644
--- a/WebCore/page/XSSAuditor.cpp
+++ b/WebCore/page/XSSAuditor.cpp
@@ -339,7 +339,7 @@ bool XSSAuditor::findInRequest(const FindTask& task) const
case XSSProtectionBlockEnabled:
if (blockFrame) {
blockFrame->loader()->stopAllLoaders();
- blockFrame->navigationScheduler()->scheduleLocationChange(blankURL(), String());
+ blockFrame->navigationScheduler()->scheduleLocationChange(blockFrame->document()->securityOrigin(), blankURL(), String());
}
break;
default:
diff --git a/WebCore/page/animation/AnimationBase.cpp b/WebCore/page/animation/AnimationBase.cpp
index 66172f7..1ba39d9 100644
--- a/WebCore/page/animation/AnimationBase.cpp
+++ b/WebCore/page/animation/AnimationBase.cpp
@@ -357,15 +357,19 @@ public:
ShadowData defaultShadowData(0, 0, 0, 0, Normal, Color::transparent);
ShadowData* newShadowData = 0;
+ ShadowData* lastShadow = 0;
while (shadowA || shadowB) {
const ShadowData* srcShadow = shadowA ? shadowA : &defaultShadowData;
const ShadowData* dstShadow = shadowB ? shadowB : &defaultShadowData;
- if (!newShadowData)
- newShadowData = blendFunc(anim, srcShadow, dstShadow, progress);
+ ShadowData* blendedShadow = blendFunc(anim, srcShadow, dstShadow, progress);
+ if (!lastShadow)
+ newShadowData = blendedShadow;
else
- newShadowData->setNext(blendFunc(anim, srcShadow, dstShadow, progress));
+ lastShadow->setNext(blendedShadow);
+
+ lastShadow = blendedShadow;
shadowA = shadowA ? shadowA->next() : 0;
shadowB = shadowB ? shadowB->next() : 0;
@@ -574,6 +578,8 @@ public:
(*it)->blend(anim, dst, a, b, progress);
}
+ const Vector<PropertyWrapperBase*> propertyWrappers() const { return m_propertyWrappers; }
+
private:
Vector<PropertyWrapperBase*> m_propertyWrappers;
};
@@ -731,7 +737,8 @@ static void addShorthandProperties()
CSSPropertyWebkitMask, // for mask-position
CSSPropertyWebkitMaskPosition,
CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft,
- CSSPropertyBorderColor,
+ CSSPropertyBorderColor,
+ CSSPropertyBorderRadius,
CSSPropertyBorderWidth,
CSSPropertyBorder,
CSSPropertyBorderSpacing,
@@ -862,6 +869,39 @@ bool AnimationBase::animationOfPropertyIsAccelerated(int prop)
}
#endif
+static bool gatherEnclosingShorthandProperties(int property, PropertyWrapperBase* wrapper, HashSet<int>& propertySet)
+{
+ if (!wrapper->isShorthandWrapper())
+ return false;
+
+ ShorthandPropertyWrapper* shorthandWrapper = static_cast<ShorthandPropertyWrapper*>(wrapper);
+
+ bool contained = false;
+ for (size_t i = 0; i < shorthandWrapper->propertyWrappers().size(); ++i) {
+ PropertyWrapperBase* currWrapper = shorthandWrapper->propertyWrappers()[i];
+
+ if (gatherEnclosingShorthandProperties(property, currWrapper, propertySet) || currWrapper->property() == property)
+ contained = true;
+ }
+
+ if (contained)
+ propertySet.add(wrapper->property());
+
+ return contained;
+}
+
+// Note: this is inefficient. It's only called from pauseTransitionAtTime().
+HashSet<int> AnimationBase::animatableShorthandsAffectingProperty(int property)
+{
+ ensurePropertyMap();
+
+ HashSet<int> foundProperties;
+ for (int i = 0; i < getNumProperties(); ++i)
+ gatherEnclosingShorthandProperties(property, (*gPropertyWrappers)[i], foundProperties);
+
+ return foundProperties;
+}
+
void AnimationBase::setNeedsStyleRecalc(Node* node)
{
ASSERT(!node || (node->document() && !node->document()->inPageCache()));
diff --git a/WebCore/page/animation/AnimationBase.h b/WebCore/page/animation/AnimationBase.h
index eb9bd12..877d649 100644
--- a/WebCore/page/animation/AnimationBase.h
+++ b/WebCore/page/animation/AnimationBase.h
@@ -31,6 +31,7 @@
#include "RenderStyleConstants.h"
#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
#include <wtf/text/AtomicString.h>
namespace WebCore {
@@ -180,6 +181,8 @@ public:
static bool animationOfPropertyIsAccelerated(int prop);
#endif
+ static HashSet<int> animatableShorthandsAffectingProperty(int property);
+
protected:
virtual void overrideAnimations() { }
virtual void resumeOverriddenAnimations() { }
diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp
index 613aee6..e1281dd 100644
--- a/WebCore/page/animation/AnimationController.cpp
+++ b/WebCore/page/animation/AnimationController.cpp
@@ -53,9 +53,9 @@ AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
, m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet)
, m_styleAvailableWaiters(0)
, m_lastStyleAvailableWaiter(0)
- , m_responseWaiters(0)
- , m_lastResponseWaiter(0)
- , m_waitingForResponse(false)
+ , m_startTimeResponseWaiters(0)
+ , m_lastStartTimeResponseWaiter(0)
+ , m_waitingForStartTimeResponse(false)
{
}
@@ -145,16 +145,16 @@ void AnimationControllerPrivate::fireEventsAndUpdateStyle()
bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_nodeChangesToDispatch.isEmpty();
// fire all the events
- Vector<EventToDispatch> eventsToDispatch = m_eventsToDispatch;
- m_eventsToDispatch.clear();
- Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = eventsToDispatch.end();
- for (Vector<EventToDispatch>::const_iterator it = eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
+ 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->dispatchEvent(WebKitTransitionEvent::create(it->eventType, it->name, it->elapsedTime));
else
it->element->dispatchEvent(WebKitAnimationEvent::create(it->eventType, it->name, it->elapsedTime));
}
+ m_eventsToDispatch.clear();
+
// call setChanged on all the elements
Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end();
for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it)
@@ -323,13 +323,13 @@ double AnimationControllerPrivate::beginAnimationUpdateTime()
void AnimationControllerPrivate::endAnimationUpdate()
{
styleAvailable();
- if (!m_waitingForResponse)
+ if (!m_waitingForStartTimeResponse)
startTimeResponse(beginAnimationUpdateTime());
}
void AnimationControllerPrivate::receivedStartTimeResponse(double time)
{
- m_waitingForResponse = false;
+ m_waitingForStartTimeResponse = false;
startTimeResponse(time);
}
@@ -432,48 +432,51 @@ void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* a
ASSERT(!animation->next());
if (willGetResponse)
- m_waitingForResponse = true;
+ m_waitingForStartTimeResponse = true;
- if (m_responseWaiters)
- m_lastResponseWaiter->setNext(animation);
+ if (m_startTimeResponseWaiters)
+ m_lastStartTimeResponseWaiter->setNext(animation);
else
- m_responseWaiters = animation;
+ m_startTimeResponseWaiters = animation;
- m_lastResponseWaiter = animation;
+ m_lastStartTimeResponseWaiter = animation;
animation->setNext(0);
}
void AnimationControllerPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animationToRemove)
{
AnimationBase* prevAnimation = 0;
- for (AnimationBase* animation = m_responseWaiters; animation; animation = animation->next()) {
+ for (AnimationBase* animation = m_startTimeResponseWaiters; animation; animation = animation->next()) {
if (animation == animationToRemove) {
if (prevAnimation)
prevAnimation->setNext(animation->next());
else
- m_responseWaiters = animation->next();
+ m_startTimeResponseWaiters = animation->next();
- if (m_lastResponseWaiter == animation)
- m_lastResponseWaiter = prevAnimation;
+ if (m_lastStartTimeResponseWaiter == animation)
+ m_lastStartTimeResponseWaiter = prevAnimation;
animationToRemove->setNext(0);
}
prevAnimation = animation;
}
+
+ if (!m_startTimeResponseWaiters)
+ m_waitingForStartTimeResponse = false;
}
void AnimationControllerPrivate::startTimeResponse(double time)
{
// Go through list of waiters and send them on their way
- for (AnimationBase* animation = m_responseWaiters; animation; ) {
+ for (AnimationBase* animation = m_startTimeResponseWaiters; animation; ) {
AnimationBase* nextAnimation = animation->next();
animation->setNext(0);
animation->onAnimationStartResponse(time);
animation = nextAnimation;
}
- m_responseWaiters = 0;
- m_lastResponseWaiter = 0;
+ m_startTimeResponseWaiters = 0;
+ m_lastStartTimeResponseWaiter = 0;
}
AnimationController::AnimationController(Frame* frame)
diff --git a/WebCore/page/animation/AnimationControllerPrivate.h b/WebCore/page/animation/AnimationControllerPrivate.h
index 893c717..6812e09 100644
--- a/WebCore/page/animation/AnimationControllerPrivate.h
+++ b/WebCore/page/animation/AnimationControllerPrivate.h
@@ -54,12 +54,11 @@ public:
AnimationControllerPrivate(Frame*);
~AnimationControllerPrivate();
+ void updateAnimationTimer(bool callSetChanged = false);
+
PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject*);
bool clear(RenderObject*);
- void animationTimerFired(Timer<AnimationControllerPrivate>*);
- void updateAnimationTimer(bool callSetChanged = false);
-
void updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*);
void startUpdateStyleIfNeededDispatcher();
void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime);
@@ -92,11 +91,13 @@ public:
void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse);
void removeFromStartTimeResponseWaitList(AnimationBase*);
- void startTimeResponse(double t);
private:
+ void animationTimerFired(Timer<AnimationControllerPrivate>*);
+
void styleAvailable();
void fireEventsAndUpdateStyle();
+ void startTimeResponse(double t);
typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap;
@@ -120,9 +121,9 @@ private:
AnimationBase* m_styleAvailableWaiters;
AnimationBase* m_lastStyleAvailableWaiter;
- AnimationBase* m_responseWaiters;
- AnimationBase* m_lastResponseWaiter;
- bool m_waitingForResponse;
+ AnimationBase* m_startTimeResponseWaiters;
+ AnimationBase* m_lastStartTimeResponseWaiter;
+ bool m_waitingForStartTimeResponse;
};
} // namespace WebCore
diff --git a/WebCore/page/animation/CompositeAnimation.cpp b/WebCore/page/animation/CompositeAnimation.cpp
index 9d021b4..602491e 100644
--- a/WebCore/page/animation/CompositeAnimation.cpp
+++ b/WebCore/page/animation/CompositeAnimation.cpp
@@ -30,6 +30,7 @@
#include "CompositeAnimation.h"
#include "AnimationControllerPrivate.h"
+#include "CSSPropertyLonghand.h"
#include "CSSPropertyNames.h"
#include "ImplicitAnimation.h"
#include "KeyframeAnimation.h"
@@ -509,7 +510,20 @@ bool CompositeAnimation::pauseTransitionAtTime(int property, double t)
return false;
ImplicitAnimation* implAnim = m_transitions.get(property).get();
- if (!implAnim || !implAnim->running())
+ if (!implAnim) {
+ // Check to see if this property is being animated via a shorthand.
+ // This code is only used for testing, so performance is not critical here.
+ HashSet<int> shorthandProperties = AnimationBase::animatableShorthandsAffectingProperty(property);
+ bool anyPaused = false;
+ HashSet<int>::const_iterator end = shorthandProperties.end();
+ for (HashSet<int>::const_iterator it = shorthandProperties.begin(); it != end; ++it) {
+ if (pauseTransitionAtTime(*it, t))
+ anyPaused = true;
+ }
+ return anyPaused;
+ }
+
+ if (!implAnim->running())
return false;
if ((t >= 0.0) && (t <= implAnim->duration())) {
diff --git a/WebCore/page/mac/DragControllerMac.mm b/WebCore/page/mac/DragControllerMac.mm
index a09c418..05c8e09 100644
--- a/WebCore/page/mac/DragControllerMac.mm
+++ b/WebCore/page/mac/DragControllerMac.mm
@@ -53,8 +53,8 @@ DragOperation DragController::dragOperation(DragData* dragData)
if ([NSApp modalWindow] || !dragData->containsURL())
return DragOperationNone;
- if (!m_documentUnderMouse || ![[m_page->mainFrame()->view()->getOuterView() window] attachedSheet]
- && [dragData->platformData() draggingSource] != m_page->mainFrame()->view()->getOuterView())
+ if (!m_documentUnderMouse || (![[m_page->mainFrame()->view()->getOuterView() window] attachedSheet]
+ && [dragData->platformData() draggingSource] != m_page->mainFrame()->view()->getOuterView()))
return DragOperationCopy;
return DragOperationNone;
diff --git a/WebCore/page/mac/EventHandlerMac.mm b/WebCore/page/mac/EventHandlerMac.mm
index 2db713f..2d4d86b 100644
--- a/WebCore/page/mac/EventHandlerMac.mm
+++ b/WebCore/page/mac/EventHandlerMac.mm
@@ -759,7 +759,7 @@ bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
Document* document = m_frame->document();
// RSS view needs arrow key keypress events.
- if (applicationIsSafari() && document->url().protocolIs("feed") || document->url().protocolIs("feeds"))
+ if (applicationIsSafari() && (document->url().protocolIs("feed") || document->url().protocolIs("feeds")))
return true;
Settings* settings = m_frame->settings();
if (!settings)
diff --git a/WebCore/page/mac/WebCoreFrameView.h b/WebCore/page/mac/WebCoreFrameView.h
index 8b25102..b76350d 100644
--- a/WebCore/page/mac/WebCoreFrameView.h
+++ b/WebCore/page/mac/WebCoreFrameView.h
@@ -33,8 +33,8 @@ namespace WebCore {
- (void)setScrollingModes:(WebCore::ScrollbarMode)hMode vertical:(WebCore::ScrollbarMode)vMode andLock:(BOOL)lock;
- (void)scrollingModes:(WebCore::ScrollbarMode*)hMode vertical:(WebCore::ScrollbarMode*)vMode;
- (void)setScrollBarsSuppressed:(BOOL)suppressed repaintOnUnsuppress:(BOOL)repaint;
-- (void)setScrollOriginX:(int)scrollOriginX;
-- (int)scrollOriginX;
+- (void)setScrollOrigin:(NSPoint)origin updatePosition:(BOOL)updatePosition;
+- (NSPoint)scrollOrigin;
@end
@protocol WebCoreFrameView