diff options
author | Ben Murdoch <benm@google.com> | 2011-06-02 12:07:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-10 10:47:21 +0100 |
commit | 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch) | |
tree | e4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebKit2/UIProcess | |
parent | 87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff) | |
download | external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2 |
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebKit2/UIProcess')
125 files changed, 4044 insertions, 947 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKAPICast.h b/Source/WebKit2/UIProcess/API/C/WKAPICast.h index a440c6f..81c2f5f 100644 --- a/Source/WebKit2/UIProcess/API/C/WKAPICast.h +++ b/Source/WebKit2/UIProcess/API/C/WKAPICast.h @@ -37,11 +37,13 @@ #include "WKPage.h" #include "WKPreferencesPrivate.h" #include "WKProtectionSpaceTypes.h" +#include "WKResourceCacheManager.h" #include "WKSharedAPICast.h" #include <WebCore/CookieJar.h> #include <WebCore/Credential.h> #include <WebCore/FrameLoaderTypes.h> #include <WebCore/ProtectionSpace.h> +#include <WebCore/Settings.h> namespace WebKit { @@ -182,6 +184,44 @@ inline WKFontSmoothingLevel toAPI(FontSmoothingLevel level) return kWKFontSmoothingLevelMedium; } +inline WKEditableLinkBehavior toAPI(WebCore::EditableLinkBehavior behavior) +{ + switch (behavior) { + case WebCore::EditableLinkDefaultBehavior: + return kWKEditableLinkBehaviorDefault; + case WebCore::EditableLinkAlwaysLive: + return kWKEditableLinkBehaviorAlwaysLive; + case WebCore::EditableLinkOnlyLiveWithShiftKey: + return kWKEditableLinkBehaviorOnlyLiveWithShiftKey; + case WebCore::EditableLinkLiveWhenNotFocused: + return kWKEditableLinkBehaviorLiveWhenNotFocused; + case WebCore::EditableLinkNeverLive: + return kWKEditableLinkBehaviorNeverLive; + } + + ASSERT_NOT_REACHED(); + return kWKEditableLinkBehaviorNeverLive; +} + +inline WebCore::EditableLinkBehavior toEditableLinkBehavior(WKEditableLinkBehavior wkBehavior) +{ + switch (wkBehavior) { + case kWKEditableLinkBehaviorDefault: + return WebCore::EditableLinkDefaultBehavior; + case kWKEditableLinkBehaviorAlwaysLive: + return WebCore::EditableLinkAlwaysLive; + case kWKEditableLinkBehaviorOnlyLiveWithShiftKey: + return WebCore::EditableLinkOnlyLiveWithShiftKey; + case kWKEditableLinkBehaviorLiveWhenNotFocused: + return WebCore::EditableLinkLiveWhenNotFocused; + case kWKEditableLinkBehaviorNeverLive: + return WebCore::EditableLinkNeverLive; + } + + ASSERT_NOT_REACHED(); + return WebCore::EditableLinkNeverLive; +} + inline WKProtectionSpaceServerType toAPI(WebCore::ProtectionSpaceServerType type) { switch (type) { @@ -246,9 +286,9 @@ inline WebCore::CredentialPersistence toCredentialPersistence(WKCredentialPersis inline ResourceCachesToClear toResourceCachesToClear(WKResourceCachesToClear wkResourceCachesToClear) { switch (wkResourceCachesToClear) { - case kWKAllResourceCaches: + case WKResourceCachesToClearAll: return AllResourceCaches; - case kWKInMemoryResourceCachesOnly: + case WKResourceCachesToClearInMemoryOnly: return InMemoryResourceCachesOnly; } diff --git a/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.cpp b/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.cpp index 5f6a222..00dc6da 100644 --- a/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.cpp @@ -45,3 +45,8 @@ WKStringRef WKBackForwardListItemCopyTitle(WKBackForwardListItemRef itemRef) { return toCopiedAPI(toImpl(itemRef)->title()); } + +WKURLRef WKBackForwardListItemCopyOriginalURL(WKBackForwardListItemRef itemRef) +{ + return toCopiedURLAPI(toImpl(itemRef)->originalURL()); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.h b/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.h index b0bf1de..3810d15 100644 --- a/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.h +++ b/Source/WebKit2/UIProcess/API/C/WKBackForwardListItem.h @@ -36,6 +36,7 @@ WK_EXPORT WKTypeID WKBackForwardListItemGetTypeID(); WK_EXPORT WKURLRef WKBackForwardListItemCopyURL(WKBackForwardListItemRef item); WK_EXPORT WKStringRef WKBackForwardListItemCopyTitle(WKBackForwardListItemRef item); +WK_EXPORT WKURLRef WKBackForwardListItemCopyOriginalURL(WKBackForwardListItemRef item); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.cpp b/Source/WebKit2/UIProcess/API/C/WKContext.cpp index bf196b7..063f3ea 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKContext.cpp @@ -84,9 +84,9 @@ void WKContextSetDownloadClient(WKContextRef contextRef, const WKContextDownload toImpl(contextRef)->initializeDownloadClient(wkClient); } -void WKContextDownloadURLRequest(WKContextRef contextRef, const WKURLRequestRef requestRef) +WKDownloadRef WKContextDownloadURLRequest(WKContextRef contextRef, const WKURLRequestRef requestRef) { - toImpl(contextRef)->download(0, toImpl(requestRef)->resourceRequest()); + return toAPI(toImpl(contextRef)->download(0, toImpl(requestRef)->resourceRequest())); } void WKContextSetInitializationUserDataForInjectedBundle(WKContextRef contextRef, WKTypeRef userDataRef) @@ -148,16 +148,6 @@ void WKContextSetDomainRelaxationForbiddenForURLScheme(WKContextRef contextRef, toImpl(contextRef)->setDomainRelaxationForbiddenForURLScheme(toImpl(urlScheme)->string()); } -void WKContextClearResourceCaches(WKContextRef contextRef, WKResourceCachesToClear cachesToClear) -{ - toImpl(contextRef)->clearResourceCaches(toResourceCachesToClear(cachesToClear)); -} - -void WKContextClearApplicationCache(WKContextRef contextRef) -{ - toImpl(contextRef)->clearApplicationCache(); -} - WKCookieManagerRef WKContextGetCookieManager(WKContextRef contextRef) { return toAPI(toImpl(contextRef)->cookieManagerProxy()); @@ -227,3 +217,18 @@ void WKContextSetLocalStorageDirectory(WKContextRef contextRef, WKStringRef loca { toImpl(contextRef)->setLocalStorageDirectory(toImpl(localStorageDirectory)->string()); } + +void WKContextDisableProcessTermination(WKContextRef contextRef) +{ + toImpl(contextRef)->disableProcessTermination(); +} + +void WKContextEnableProcessTermination(WKContextRef contextRef) +{ + toImpl(contextRef)->enableProcessTermination(); +} + +void _WKContextSetHTTPPipeliningEnabled(WKContextRef contextRef, bool enabled) +{ + toImpl(contextRef)->setHTTPPipeliningEnabled(enabled); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.h b/Source/WebKit2/UIProcess/API/C/WKContext.h index 606574f..6e8e4c0 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.h +++ b/Source/WebKit2/UIProcess/API/C/WKContext.h @@ -39,12 +39,6 @@ enum { }; typedef uint32_t WKCacheModel; -enum { - kWKAllResourceCaches = 0, - kWKInMemoryResourceCachesOnly = 1 -}; -typedef uint32_t WKResourceCachesToClear; - // Injected Bundle Client typedef void (*WKContextDidReceiveMessageFromInjectedBundleCallback)(WKContextRef page, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo); typedef void (*WKContextDidReceiveSynchronousMessageFromInjectedBundleCallback)(WKContextRef page, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void *clientInfo); @@ -115,7 +109,7 @@ WK_EXPORT void WKContextSetInjectedBundleClient(WKContextRef context, const WKCo WK_EXPORT void WKContextSetHistoryClient(WKContextRef context, const WKContextHistoryClient* client); WK_EXPORT void WKContextSetDownloadClient(WKContextRef context, const WKContextDownloadClient* client); -WK_EXPORT void WKContextDownloadURLRequest(WKContextRef context, const WKURLRequestRef request); +WK_EXPORT WKDownloadRef WKContextDownloadURLRequest(WKContextRef context, const WKURLRequestRef request); WK_EXPORT void WKContextSetInitializationUserDataForInjectedBundle(WKContextRef context, WKTypeRef userData); WK_EXPORT void WKContextPostMessageToInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody); @@ -125,9 +119,6 @@ WK_EXPORT void WKContextAddVisitedLink(WKContextRef context, WKStringRef visited WK_EXPORT void WKContextSetCacheModel(WKContextRef context, WKCacheModel cacheModel); WK_EXPORT WKCacheModel WKContextGetCacheModel(WKContextRef context); -WK_EXPORT void WKContextClearResourceCaches(WKContextRef context, WKResourceCachesToClear cachesToClear); -WK_EXPORT void WKContextClearApplicationCache(WKContextRef context); - WK_EXPORT void WKContextStartMemorySampler(WKContextRef context, WKDoubleRef interval); WK_EXPORT void WKContextStopMemorySampler(WKContextRef context); diff --git a/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h b/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h index 5fd7dd3..153ef3e 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h @@ -61,6 +61,13 @@ WK_EXPORT void WKContextSetIconDatabasePath(WKContextRef context, WKStringRef ic WK_EXPORT void WKContextSetDatabaseDirectory(WKContextRef context, WKStringRef databaseDirectory); WK_EXPORT void WKContextSetLocalStorageDirectory(WKContextRef context, WKStringRef localStorageDirectory); +// FIXME: This is a workaround for testing purposes only and should be removed once a better +// solution has been found for testing. +WK_EXPORT void WKContextDisableProcessTermination(WKContextRef context); +WK_EXPORT void WKContextEnableProcessTermination(WKContextRef context); + +WK_EXPORT void _WKContextSetHTTPPipeliningEnabled(WKContextRef context, bool enabled); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKFrame.h b/Source/WebKit2/UIProcess/API/C/WKFrame.h index 334a27b..eec939e 100644 --- a/Source/WebKit2/UIProcess/API/C/WKFrame.h +++ b/Source/WebKit2/UIProcess/API/C/WKFrame.h @@ -36,12 +36,12 @@ extern "C" { #endif -enum WKFrameLoadState { +enum { kWKFrameLoadStateProvisional = 0, kWKFrameLoadStateCommitted = 1, kWKFrameLoadStateFinished = 2 }; -typedef enum WKFrameLoadState WKFrameLoadState; +typedef uint32_t WKFrameLoadState; WK_EXPORT WKTypeID WKFrameGetTypeID(); diff --git a/Source/WebKit2/UIProcess/API/C/WKIconDatabase.cpp b/Source/WebKit2/UIProcess/API/C/WKIconDatabase.cpp index c8e87a0..8e9327f 100644 --- a/Source/WebKit2/UIProcess/API/C/WKIconDatabase.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKIconDatabase.cpp @@ -36,6 +36,13 @@ WKTypeID WKIconDatabaseGetTypeID() return toAPI(WebIconDatabase::APIType); } +void WKIconDatabaseSetIconDatabaseClient(WKIconDatabaseRef iconDatabaseRef, const WKIconDatabaseClient* wkClient) +{ + if (wkClient && wkClient->version) + return; + toImpl(iconDatabaseRef)->initializeIconDatabaseClient(wkClient); +} + void WKIconDatabaseRetainIconForURL(WKIconDatabaseRef iconDatabaseRef, WKURLRef pageURLRef) { toImpl(iconDatabaseRef)->retainIconForPageURL(toWTFString(pageURLRef)); @@ -50,3 +57,18 @@ void WKIconDatabaseEnableDatabaseCleanup(WKIconDatabaseRef iconDatabaseRef) { toImpl(iconDatabaseRef)->enableDatabaseCleanup(); } + +void WKIconDatabaseRemoveAllIcons(WKIconDatabaseRef iconDatabaseRef) +{ + toImpl(iconDatabaseRef)->removeAllIcons(); +} + +void WKIconDatabaseCheckIntegrityBeforeOpening(WKIconDatabaseRef iconDatabaseRef) +{ + toImpl(iconDatabaseRef)->checkIntegrityBeforeOpening(); +} + +void WKIconDatabaseClose(WKIconDatabaseRef iconDatabaseRef) +{ + toImpl(iconDatabaseRef)->close(); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKIconDatabase.h b/Source/WebKit2/UIProcess/API/C/WKIconDatabase.h index 1ea1860..ece3399 100644 --- a/Source/WebKit2/UIProcess/API/C/WKIconDatabase.h +++ b/Source/WebKit2/UIProcess/API/C/WKIconDatabase.h @@ -32,12 +32,31 @@ extern "C" { #endif +// IconDatabase Client. +typedef void (*WKIconDatabaseDidChangeIconForPageURLCallback)(WKIconDatabaseRef iconDatabase, WKURLRef pageURL, const void* clientInfo); +typedef void (*WKIconDatabaseDidRemoveAllIconsCallback)(WKIconDatabaseRef iconDatabase, const void* clientInfo); + +struct WKIconDatabaseClient { + int version; + const void * clientInfo; + WKIconDatabaseDidChangeIconForPageURLCallback didChangeIconForPageURL; + WKIconDatabaseDidRemoveAllIconsCallback didRemoveAllIcons; +}; +typedef struct WKIconDatabaseClient WKIconDatabaseClient; + WK_EXPORT WKTypeID WKIconDatabaseGetTypeID(); +WK_EXPORT void WKIconDatabaseSetIconDatabaseClient(WKIconDatabaseRef iconDatabase, const WKIconDatabaseClient* client); + WK_EXPORT void WKIconDatabaseRetainIconForURL(WKIconDatabaseRef iconDatabase, WKURLRef pageURL); WK_EXPORT void WKIconDatabaseReleaseIconForURL(WKIconDatabaseRef iconDatabase, WKURLRef pageURL); WK_EXPORT void WKIconDatabaseEnableDatabaseCleanup(WKIconDatabaseRef iconDatabase); +WK_EXPORT void WKIconDatabaseRemoveAllIcons(WKIconDatabaseRef iconDatabase); +WK_EXPORT void WKIconDatabaseCheckIntegrityBeforeOpening(WKIconDatabaseRef iconDatabase); + +WK_EXPORT void WKIconDatabaseClose(WKIconDatabaseRef iconDatabase); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.cpp b/Source/WebKit2/UIProcess/API/C/WKPage.cpp index 7061e39..18bc5a7 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPage.cpp @@ -32,6 +32,7 @@ #include "WebBackForwardList.h" #include "WebData.h" #include "WebPageProxy.h" +#include "WebProcessProxy.h" #ifdef __BLOCKS__ #include <Block.h> @@ -46,7 +47,7 @@ WKTypeID WKPageGetTypeID() WKContextRef WKPageGetContext(WKPageRef pageRef) { - return toAPI(toImpl(pageRef)->context()); + return toAPI(toImpl(pageRef)->process()->context()); } WKPageGroupRef WKPageGetPageGroup(WKPageRef pageRef) diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.h b/Source/WebKit2/UIProcess/API/C/WKPage.h index 03f49f7..72405a3 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.h +++ b/Source/WebKit2/UIProcess/API/C/WKPage.h @@ -41,6 +41,12 @@ extern "C" { #endif +enum { + kWKFocusDirectionBackward = 0, + kWKFocusDirectionForward = 1 +}; +typedef uint32_t WKFocusDirection; + typedef void (*WKPageCallback)(WKPageRef page, const void* clientInfo); // FrameLoad Client @@ -149,6 +155,9 @@ typedef WKPageRef (*WKPageCreateNewPageCallback)(WKPageRef page, WKDictionaryRef typedef void (*WKPageRunJavaScriptAlertCallback)(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void *clientInfo); typedef bool (*WKPageRunJavaScriptConfirmCallback)(WKPageRef page, WKStringRef message, WKFrameRef frame, const void *clientInfo); typedef WKStringRef (*WKPageRunJavaScriptPromptCallback)(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, const void *clientInfo); +typedef void (*WKPageTakeFocusCallback)(WKPageRef page, WKFocusDirection direction, const void *clientInfo); +typedef void (*WKPageFocusCallback)(WKPageRef page, const void *clientInfo); +typedef void (*WKPageUnfocusCallback)(WKPageRef page, const void *clientInfo); typedef void (*WKPageSetStatusTextCallback)(WKPageRef page, WKStringRef text, const void *clientInfo); typedef void (*WKPageMouseDidMoveOverElementCallback)(WKPageRef page, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo); typedef void (*WKPageMissingPluginButtonClickedCallback)(WKPageRef page, WKStringRef mimeType, WKStringRef url, WKStringRef pluginsPageURL, const void* clientInfo); @@ -181,6 +190,9 @@ struct WKPageUIClient { WKPageCreateNewPageCallback createNewPage; WKPageCallback showPage; WKPageCallback close; + WKPageTakeFocusCallback takeFocus; + WKPageFocusCallback focus; + WKPageUnfocusCallback unfocus; WKPageRunJavaScriptAlertCallback runJavaScriptAlert; WKPageRunJavaScriptConfirmCallback runJavaScriptConfirm; WKPageRunJavaScriptPromptCallback runJavaScriptPrompt; diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp index 0122531..449a1e8 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp @@ -29,6 +29,7 @@ #include "WKAPICast.h" #include "WebPreferences.h" +#include <WebCore/Settings.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> @@ -71,6 +72,16 @@ bool WKPreferencesGetLoadsImagesAutomatically(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->loadsImagesAutomatically(); } +void WKPreferencesSetLoadsSiteIconsIgnoringImageLoadingPreference(WKPreferencesRef preferencesRef, bool loadsSiteIconsIgnoringImageLoadingPreference) +{ + toImpl(preferencesRef)->setLoadsSiteIconsIgnoringImageLoadingPreference(loadsSiteIconsIgnoringImageLoadingPreference); +} + +bool WKPreferencesGetLoadsSiteIconsIgnoringImageLoadingPreference(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->loadsSiteIconsIgnoringImageLoadingPreference(); +} + void WKPreferencesSetOfflineWebApplicationCacheEnabled(WKPreferencesRef preferencesRef, bool offlineWebApplicationCacheEnabled) { toImpl(preferencesRef)->setOfflineWebApplicationCacheEnabled(offlineWebApplicationCacheEnabled); @@ -251,6 +262,16 @@ uint32_t WKPreferencesGetMinimumFontSize(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->minimumFontSize(); } +void WKPreferencesSetEditableLinkBehavior(WKPreferencesRef preferencesRef, WKEditableLinkBehavior wkBehavior) +{ + toImpl(preferencesRef)->setEditableLinkBehavior(toEditableLinkBehavior(wkBehavior)); +} + +WKEditableLinkBehavior WKPreferencesGetEditableLinkBehavior(WKPreferencesRef preferencesRef) +{ + return toAPI(static_cast<WebCore::EditableLinkBehavior>(toImpl(preferencesRef)->editableLinkBehavior())); +} + void WKPreferencesSetDefaultTextEncodingName(WKPreferencesRef preferencesRef, WKStringRef name) { toImpl(preferencesRef)->setDefaultTextEncodingName(toWTFString(name)); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.h b/Source/WebKit2/UIProcess/API/C/WKPreferences.h index f2486bf..930f23d 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.h @@ -50,6 +50,10 @@ WK_EXPORT void WKPreferencesSetLoadsImagesAutomatically(WKPreferencesRef prefere WK_EXPORT bool WKPreferencesGetLoadsImagesAutomatically(WKPreferencesRef preferences); // Defaults to false. +WK_EXPORT void WKPreferencesSetLoadsSiteIconsIgnoringImageLoadingPreference(WKPreferencesRef preferences, bool loadsSiteIconsIgnoringImageLoadingPreference); +WK_EXPORT bool WKPreferencesGetLoadsSiteIconsIgnoringImageLoadingPreference(WKPreferencesRef preferences); + +// Defaults to false. WK_EXPORT void WKPreferencesSetOfflineWebApplicationCacheEnabled(WKPreferencesRef preferences, bool offlineWebApplicationCacheEnabled); WK_EXPORT bool WKPreferencesGetOfflineWebApplicationCacheEnabled(WKPreferencesRef preferences); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h index ddf1b9a..d67db14 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h @@ -43,10 +43,23 @@ enum WKFontSmoothingLevel { }; typedef enum WKFontSmoothingLevel WKFontSmoothingLevel; +enum WKEditableLinkBehavior { + kWKEditableLinkBehaviorDefault, + kWKEditableLinkBehaviorAlwaysLive, + kWKEditableLinkBehaviorOnlyLiveWithShiftKey, + kWKEditableLinkBehaviorLiveWhenNotFocused, + kWKEditableLinkBehaviorNeverLive +}; +typedef enum WKEditableLinkBehavior WKEditableLinkBehavior; + // Defaults to kWKFontSmoothingLevelMedium. WK_EXPORT void WKPreferencesSetFontSmoothingLevel(WKPreferencesRef, WKFontSmoothingLevel); WK_EXPORT WKFontSmoothingLevel WKPreferencesGetFontSmoothingLevel(WKPreferencesRef); +// Defaults to EditableLinkNeverLive. +WK_EXPORT void WKPreferencesSetEditableLinkBehavior(WKPreferencesRef preferencesRef, WKEditableLinkBehavior); +WK_EXPORT WKEditableLinkBehavior WKPreferencesGetEditableLinkBehavior(WKPreferencesRef preferencesRef); + // Defaults to false. WK_EXPORT void WKPreferencesSetAcceleratedDrawingEnabled(WKPreferencesRef, bool); WK_EXPORT bool WKPreferencesGetAcceleratedDrawingEnabled(WKPreferencesRef); diff --git a/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.cpp b/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.cpp index 483beeb..a5711e0 100644 --- a/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.cpp @@ -41,12 +41,12 @@ void WKResourceCacheManagerGetCacheOrigins(WKResourceCacheManagerRef cacheManage toImpl(cacheManagerRef)->getCacheOrigins(ArrayCallback::create(context, callback)); } -void WKResourceCacheManagerClearCacheForOrigin(WKResourceCacheManagerRef cacheManagerRef, WKSecurityOriginRef originRef) +void WKResourceCacheManagerClearCacheForOrigin(WKResourceCacheManagerRef cacheManagerRef, WKSecurityOriginRef originRef, WKResourceCachesToClear cachesToClear) { - toImpl(cacheManagerRef)->clearCacheForOrigin(toImpl(originRef)); + toImpl(cacheManagerRef)->clearCacheForOrigin(toImpl(originRef), toResourceCachesToClear(cachesToClear)); } -void WKResourceCacheManagerClearCacheForAllOrigins(WKResourceCacheManagerRef cacheManagerRef) +void WKResourceCacheManagerClearCacheForAllOrigins(WKResourceCacheManagerRef cacheManagerRef, WKResourceCachesToClear cachesToClear) { - toImpl(cacheManagerRef)->clearCacheForAllOrigins(); + toImpl(cacheManagerRef)->clearCacheForAllOrigins(toResourceCachesToClear(cachesToClear)); } diff --git a/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.h b/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.h index 479169d..80c4531 100644 --- a/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.h +++ b/Source/WebKit2/UIProcess/API/C/WKResourceCacheManager.h @@ -32,13 +32,19 @@ extern "C" { #endif +enum { + WKResourceCachesToClearAll = 0, + WKResourceCachesToClearInMemoryOnly = 1 +}; +typedef uint32_t WKResourceCachesToClear; + WK_EXPORT WKTypeID WKResourceCacheManagerGetTypeID(); typedef void (*WKResourceCacheManagerGetCacheOriginsFunction)(WKArrayRef, WKErrorRef, void*); WK_EXPORT void WKResourceCacheManagerGetCacheOrigins(WKResourceCacheManagerRef contextRef, void* context, WKResourceCacheManagerGetCacheOriginsFunction function); -WK_EXPORT void WKResourceCacheManagerClearCacheForOrigin(WKResourceCacheManagerRef cacheManger, WKSecurityOriginRef origin); -WK_EXPORT void WKResourceCacheManagerClearCacheForAllOrigins(WKResourceCacheManagerRef cacheManager); +WK_EXPORT void WKResourceCacheManagerClearCacheForOrigin(WKResourceCacheManagerRef cacheManger, WKSecurityOriginRef origin, WKResourceCachesToClear cachesToClear); +WK_EXPORT void WKResourceCacheManagerClearCacheForAllOrigins(WKResourceCacheManagerRef cacheManager, WKResourceCachesToClear cachesToClear); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.cpp b/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.cpp index 5e50dd8..40e4a0e 100644 --- a/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.cpp +++ b/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.cpp @@ -34,8 +34,8 @@ using namespace WebKit; using namespace WebCore; -CGImageRef WKIconDatabaseGetCGImageForURL(WKIconDatabaseRef iconDatabaseRef, WKURLRef urlRef) +CGImageRef WKIconDatabaseTryGetCGImageForURL(WKIconDatabaseRef iconDatabaseRef, WKURLRef urlRef, WKSize size) { Image* image = toImpl(iconDatabaseRef)->imageForPageURL(toWTFString(urlRef)); - return image ? image->getCGImageRef() : 0; + return image ? image->getFirstCGImageRefOfSize(IntSize(static_cast<int>(size.width), static_cast<int>(size.height))) : 0; } diff --git a/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.h b/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.h index 48cf5bf..62ae82e 100644 --- a/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.h +++ b/Source/WebKit2/UIProcess/API/C/cg/WKIconDatabaseCG.h @@ -28,12 +28,13 @@ #include <CoreGraphics/CGImage.h> #include <WebKit2/WKBase.h> +#include <WebKit2/WKGeometry.h> #ifdef __cplusplus extern "C" { #endif -WK_EXPORT CGImageRef WKIconDatabaseGetCGImageForURL(WKIconDatabaseRef iconDatabase, WKURLRef urlString); +WK_EXPORT CGImageRef WKIconDatabaseTryGetCGImageForURL(WKIconDatabaseRef iconDatabase, WKURLRef urlString, WKSize size); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/C/win/WKAPICastWin.h b/Source/WebKit2/UIProcess/API/C/win/WKAPICastWin.h index 09cf06f..24891f5 100644 --- a/Source/WebKit2/UIProcess/API/C/win/WKAPICastWin.h +++ b/Source/WebKit2/UIProcess/API/C/win/WKAPICastWin.h @@ -30,14 +30,25 @@ #error "Please #include \"WKAPICast.h\" instead of this file directly." #endif +#include "WebGrammarDetail.h" +#include <WebCore/TextCheckerClient.h> + namespace WebKit { class WebView; class WebEditCommandProxy; +class WebTextChecker; WK_ADD_API_MAPPING(WKViewRef, WebView) WK_ADD_API_MAPPING(WKEditCommandRef, WebEditCommandProxy) +WK_ADD_API_MAPPING(WKTextCheckerRef, WebTextChecker) +WK_ADD_API_MAPPING(WKGrammarDetailRef, WebGrammarDetail) +inline ProxyingRefPtr<WebGrammarDetail> toAPI(const WebCore::GrammarDetail& grammarDetail) +{ + return ProxyingRefPtr<WebGrammarDetail>(WebGrammarDetail::create(grammarDetail)); } +} // namespace WebKit + #endif // WKAPICastWin_h diff --git a/Source/WebKit2/UIProcess/API/C/win/WKGrammarDetail.cpp b/Source/WebKit2/UIProcess/API/C/win/WKGrammarDetail.cpp new file mode 100644 index 0000000..5ab0fc4 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/win/WKGrammarDetail.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WKGrammarDetail.h" + +#include "APIObject.h" +#include "ImmutableArray.h" +#include "WKAPICast.h" +#include "WebGrammarDetail.h" + +using namespace WebKit; + +WKTypeID WKGrammarDetailGetTypeID() +{ + return toAPI(APIObject::TypeGrammarDetail); +} + +WKGrammarDetailRef WKGrammarDetailCreate(int location, int length, WKArrayRef guesses, WKStringRef userDescription) +{ + RefPtr<WebGrammarDetail> detail = WebGrammarDetail::create(location, length, toImpl(guesses), toWTFString(userDescription)); + return toAPI(detail.release().releaseRef()); +} + +int WKGrammarDetailGetLocation(WKGrammarDetailRef grammarDetailRef) +{ + return toImpl(grammarDetailRef)->location(); +} + +int WKGrammarDetailGetLength(WKGrammarDetailRef grammarDetailRef) +{ + return toImpl(grammarDetailRef)->length(); +} + +WKArrayRef WKGrammarDetailCopyGuesses(WKGrammarDetailRef grammarDetailRef) +{ + return toAPI(toImpl(grammarDetailRef)->guesses().leakRef()); +} + +WKStringRef WKGrammarDetailCopyUserDescription(WKGrammarDetailRef grammarDetailRef) +{ + return toCopiedAPI(toImpl(grammarDetailRef)->userDescription()); +} diff --git a/Source/WebKit2/UIProcess/API/C/win/WKGrammarDetail.h b/Source/WebKit2/UIProcess/API/C/win/WKGrammarDetail.h new file mode 100644 index 0000000..c187ce6 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/win/WKGrammarDetail.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WKGrammarDetail_h +#define WKGrammarDetail_h + +#include <WebKit2/WKBase.h> + +#ifdef __cplusplus +extern "C" { +#endif + +WK_EXPORT WKTypeID WKGrammarDetailGetTypeID(); +WK_EXPORT WKGrammarDetailRef WKGrammarDetailCreate(int location, int length, WKArrayRef guesses, WKStringRef userDescription); + +WK_EXPORT int WKGrammarDetailGetLocation(WKGrammarDetailRef grammarDetailRef); +WK_EXPORT int WKGrammarDetailGetLength(WKGrammarDetailRef grammarDetailRef); +WK_EXPORT WKArrayRef WKGrammarDetailCopyGuesses(WKGrammarDetailRef grammarDetailRef); +WK_EXPORT WKStringRef WKGrammarDetailCopyUserDescription(WKGrammarDetailRef grammarDetailRef); + +#ifdef __cplusplus +} +#endif + +#endif /* WKGrammarDetail_h */ diff --git a/Source/WebKit2/UIProcess/API/C/win/WKTextChecker.cpp b/Source/WebKit2/UIProcess/API/C/win/WKTextChecker.cpp new file mode 100644 index 0000000..3329da2 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/win/WKTextChecker.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WKTextChecker.h" + +#include "WKAPICast.h" +#include "WebPageProxy.h" +#include "WebTextChecker.h" + +using namespace WebKit; + +void WKTextCheckerSetClient(const WKTextCheckerClient* wkClient) +{ + if (wkClient && wkClient->version) + return; + WebTextChecker::shared()->setClient(wkClient); +} + +void WKTextCheckerContinuousSpellCheckingEnabledStateChanged(bool enabled) +{ + WebTextChecker::shared()->continuousSpellCheckingEnabledStateChanged(enabled); +} + +void WKTextCheckerGrammarCheckingEnabledStateChanged(bool enabled) +{ + WebTextChecker::shared()->grammarCheckingEnabledStateChanged(enabled); +} + +void WKTextCheckerCheckSpelling(WKPageRef page, bool startBeforeSelection) +{ + WebTextChecker::shared()->checkSpelling(toImpl(page), startBeforeSelection); +} + +void WKTextCheckerChangeSpellingToWord(WKPageRef page, WKStringRef word) +{ + WebTextChecker::shared()->changeSpellingToWord(toImpl(page), toWTFString(word)); +} diff --git a/Source/WebKit2/UIProcess/API/C/win/WKTextChecker.h b/Source/WebKit2/UIProcess/API/C/win/WKTextChecker.h new file mode 100644 index 0000000..31a855d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/win/WKTextChecker.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WKTextChecker_h +#define WKTextChecker_h + +#include <WebKit2/WKBase.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// TextChecker Client +typedef bool (*WKTextCheckerContinousSpellCheckingAllowed)(const void *clientInfo); +typedef bool (*WKTextCheckerContinousSpellCheckingEnabled)(const void *clientInfo); +typedef void (*WKTextCheckerSetContinousSpellCheckingEnabled)(bool enabled, const void *clientInfo); +typedef bool (*WKTextCheckerGrammarCheckingEnabled)(const void *clientInfo); +typedef void (*WKTextCheckerSetGrammarCheckingEnabled)(bool enabled, const void *clientInfo); +typedef uint64_t (*WKTextCheckerUniqueSpellDocumentTag)(WKPageRef page, const void *clientInfo); +typedef void (*WKTextCheckerCloseSpellDocumentWithTag)(uint64_t tag, const void *clientInfo); +typedef void (*WKTextCheckerCheckSpellingOfString)(uint64_t tag, WKStringRef text, int32_t* misspellingLocation, int32_t* misspellingLength, const void *clientInfo); +typedef void (*WKTextCheckerCheckGrammarOfString)(uint64_t tag, WKStringRef text, WKArrayRef* grammarDetails, int32_t* badGrammarLocation, int32_t* badGrammarLength, const void *clientInfo); +typedef bool (*WKTextCheckerSpellingUIIsShowing)(const void *clientInfo); +typedef void (*WKTextCheckerToggleSpellingUIIsShowing)(const void *clientInfo); +typedef void (*WKTextCheckerUpdateSpellingUIWithMisspelledWord)(uint64_t tag, WKStringRef misspelledWord, const void *clientInfo); +typedef void (*WKTextCheckerUpdateSpellingUIWithGrammarString)(uint64_t tag, WKStringRef badGrammarPhrase, WKGrammarDetailRef grammarDetail, const void *clientInfo); +typedef WKArrayRef (*WKTextCheckerGuessesForWord)(uint64_t tag, WKStringRef word, const void *clientInfo); +typedef void (*WKTextCheckerLearnWord)(uint64_t tag, WKStringRef word, const void *clientInfo); +typedef void (*WKTextCheckerIgnoreWord)(uint64_t tag, WKStringRef word, const void *clientInfo); + +struct WKTextCheckerClient { + int version; + const void * clientInfo; + WKTextCheckerContinousSpellCheckingAllowed continuousSpellCheckingAllowed; + WKTextCheckerContinousSpellCheckingEnabled continuousSpellCheckingEnabled; + WKTextCheckerSetContinousSpellCheckingEnabled setContinuousSpellCheckingEnabled; + WKTextCheckerGrammarCheckingEnabled grammarCheckingEnabled; + WKTextCheckerSetGrammarCheckingEnabled setGrammarCheckingEnabled; + WKTextCheckerUniqueSpellDocumentTag uniqueSpellDocumentTag; + WKTextCheckerCloseSpellDocumentWithTag closeSpellDocumentWithTag; + WKTextCheckerCheckSpellingOfString checkSpellingOfString; + WKTextCheckerCheckGrammarOfString checkGrammarOfString; + WKTextCheckerSpellingUIIsShowing spellingUIIsShowing; + WKTextCheckerToggleSpellingUIIsShowing toggleSpellingUIIsShowing; + WKTextCheckerUpdateSpellingUIWithMisspelledWord updateSpellingUIWithMisspelledWord; + WKTextCheckerUpdateSpellingUIWithGrammarString updateSpellingUIWithGrammarString; + WKTextCheckerGuessesForWord guessesForWord; + WKTextCheckerLearnWord learnWord; + WKTextCheckerIgnoreWord ignoreWord; +}; +typedef struct WKTextCheckerClient WKTextCheckerClient; + +WK_EXPORT void WKTextCheckerSetClient(const WKTextCheckerClient* client); + +WK_EXPORT void WKTextCheckerContinuousSpellCheckingEnabledStateChanged(bool); +WK_EXPORT void WKTextCheckerGrammarCheckingEnabledStateChanged(bool); + +WK_EXPORT void WKTextCheckerCheckSpelling(WKPageRef page, bool startBeforeSelection); +WK_EXPORT void WKTextCheckerChangeSpellingToWord(WKPageRef page, WKStringRef word); + +#ifdef __cplusplus +} +#endif + +#endif /* WKTextChecker_h */ diff --git a/Source/WebKit2/UIProcess/API/C/win/WKView.h b/Source/WebKit2/UIProcess/API/C/win/WKView.h index c8ac44c..8b5e5b2 100644 --- a/Source/WebKit2/UIProcess/API/C/win/WKView.h +++ b/Source/WebKit2/UIProcess/API/C/win/WKView.h @@ -43,12 +43,16 @@ typedef uint32_t WKViewUndoType; typedef void (*WKViewRegisterEditCommandCallback)(WKViewRef, WKEditCommandRef, WKViewUndoType undoOrRedo, const void *clientInfo); typedef void (*WKViewClearAllEditCommandsCallback)(WKViewRef, const void *clientInfo); +typedef bool (*WKViewCanUndoRedoCallback)(WKViewRef, WKViewUndoType undoOrRedo, const void *clientInfo); +typedef void (*WKViewExecuteUndoRedoCallback)(WKViewRef, WKViewUndoType undoOrRedo, const void *clientInfo); struct WKViewUndoClient { int version; const void * clientInfo; WKViewRegisterEditCommandCallback registerEditCommand; WKViewClearAllEditCommandsCallback clearAllEditCommands; + WKViewCanUndoRedoCallback canUndoRedo; + WKViewExecuteUndoRedoCallback executeUndoRedo; }; typedef struct WKViewUndoClient WKViewUndoClient; diff --git a/Source/WebKit2/UIProcess/API/cpp/WKRetainPtr.h b/Source/WebKit2/UIProcess/API/cpp/WKRetainPtr.h index cb2a63e..ae5ba65 100644 --- a/Source/WebKit2/UIProcess/API/cpp/WKRetainPtr.h +++ b/Source/WebKit2/UIProcess/API/cpp/WKRetainPtr.h @@ -204,9 +204,15 @@ template<typename T, typename U> inline bool operator!=(T* a, const WKRetainPtr< return a != b.get(); } +template<typename T> inline WKRetainPtr<T> adoptWK(T o) +{ + return WKRetainPtr<T>(AdoptWK, o); +} + } // namespace WebKit using WebKit::WKRetainPtr; using WebKit::AdoptWK; +using WebKit::adoptWK; #endif // WKRetainPtr_h diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.h b/Source/WebKit2/UIProcess/API/mac/PDFViewController.h index dc30f56..041aa7b 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.h +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.h @@ -26,6 +26,7 @@ #ifndef PDFViewController_h #define PDFViewController_h +#include "WebFindOptions.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> @@ -64,6 +65,10 @@ public: NSPrintOperation *makePrintOperation(NSPrintInfo *); void openPDFInFinder(); void savePDFToDownloadsFolder(); + void linkClicked(const String& url); + + void findString(const String&, FindOptions, unsigned maxMatchCount); + void countStringMatches(const String&, FindOptions, unsigned maxMatchCount); private: explicit PDFViewController(WKView *wkView); diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm index 5c64000..436a08a 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm @@ -30,10 +30,12 @@ #import "WKAPICast.h" #import "WKView.h" #import "WebData.h" +#import "WebEventFactory.h" #import "WebPageGroup.h" #import "WebPageProxy.h" #import "WebPreferences.h" #import <PDFKit/PDFKit.h> +#import <WebCore/LocalizedStrings.h> #import <wtf/text/WTFString.h> // Redeclarations of PDFKit notifications. We can't use the API since we use a weak link to the framework. @@ -51,7 +53,51 @@ using namespace WebKit; @end extern "C" NSString *_NSPathForSystemFramework(NSString *framework); + +// MARK: C UTILITY FUNCTIONS + +static void _applicationInfoForMIMEType(NSString *type, NSString **name, NSImage **image) +{ + ASSERT(name); + ASSERT(image); + CFURLRef appURL = 0; + + OSStatus error = LSCopyApplicationForMIMEType((CFStringRef)type, kLSRolesAll, &appURL); + if (error != noErr) + return; + + NSString *appPath = [(NSURL *)appURL path]; + if (appURL) + CFRelease(appURL); + + *image = [[NSWorkspace sharedWorkspace] iconForFile:appPath]; + [*image setSize:NSMakeSize(16, 16)]; + + *name = [[NSFileManager defaultManager] displayNameAtPath:appPath]; +} + +// FIXME 4182876: We can eliminate this function in favor if -isEqual: if [PDFSelection isEqual:] is overridden +// to compare contents. +static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selectionB) +{ + NSArray *aPages = [selectionA pages]; + NSArray *bPages = [selectionB pages]; + + if (![aPages isEqual:bPages]) + return NO; + + NSUInteger count = [aPages count]; + for (NSUInteger i = 0; i < count; ++i) { + NSRect aBounds = [selectionA boundsForPage:[aPages objectAtIndex:i]]; + NSRect bBounds = [selectionB boundsForPage:[bPages objectAtIndex:i]]; + if (!NSEqualRects(aBounds, bBounds)) + return NO; + } + + return YES; +} + @interface WKPDFView : NSView { PDFViewController* _pdfViewController; @@ -68,7 +114,7 @@ extern "C" NSString *_NSPathForSystemFramework(NSString *framework); - (void)setDocument:(PDFDocument *)pdfDocument; - (void)_applyPDFPreferences; - +- (PDFSelection *)_nextMatchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag fromSelection:(PDFSelection *)initialSelection startInSelection:(BOOL)startInSelection; @end @implementation WKPDFView @@ -159,6 +205,64 @@ extern "C" NSString *_NSPathForSystemFramework(NSString *framework); [self _updatePreferencesSoon]; } +- (void)_openWithFinder:(id)sender +{ + _pdfViewController->openPDFInFinder(); +} + +- (PDFSelection *)_nextMatchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag fromSelection:(PDFSelection *)initialSelection startInSelection:(BOOL)startInSelection +{ + if (![string length]) + return nil; + + int options = 0; + if (!forward) + options |= NSBackwardsSearch; + + if (!caseFlag) + options |= NSCaseInsensitiveSearch; + + PDFDocument *document = [_pdfView document]; + + PDFSelection *selectionForInitialSearch = [initialSelection copy]; + if (startInSelection) { + // Initially we want to include the selected text in the search. So we must modify the starting search + // selection to fit PDFDocument's search requirements: selection must have a length >= 1, begin before + // the current selection (if searching forwards) or after (if searching backwards). + int initialSelectionLength = [[initialSelection string] length]; + if (forward) { + [selectionForInitialSearch extendSelectionAtStart:1]; + [selectionForInitialSearch extendSelectionAtEnd:-initialSelectionLength]; + } else { + [selectionForInitialSearch extendSelectionAtEnd:1]; + [selectionForInitialSearch extendSelectionAtStart:-initialSelectionLength]; + } + } + PDFSelection *foundSelection = [document findString:string fromSelection:selectionForInitialSearch withOptions:options]; + [selectionForInitialSearch release]; + + // If we first searched in the selection, and we found the selection, search again from just past the selection + if (startInSelection && _PDFSelectionsAreEqual(foundSelection, initialSelection)) + foundSelection = [document findString:string fromSelection:initialSelection withOptions:options]; + + if (!foundSelection && wrapFlag) + foundSelection = [document findString:string fromSelection:nil withOptions:options]; + + return foundSelection; +} + +- (NSUInteger)_countMatches:(NSString *)string caseSensitive:(BOOL)caseFlag +{ + if (![string length]) + return 0; + + int options = caseFlag ? 0 : NSCaseInsensitiveSearch; + + return [[[_pdfView document] findString:string withOptions:options] count]; +} + +// MARK: NSView overrides + - (void)viewDidMoveToWindow { if (![self window]) @@ -181,7 +285,69 @@ extern "C" NSString *_NSPathForSystemFramework(NSString *framework); [notificationCenter removeObserver:self name:_webkit_PDFViewPageChangedNotification object:_pdfView]; } -// PDFView delegate methods +- (NSView *)hitTest:(NSPoint)point +{ + // Override hitTest so we can override menuForEvent. + NSEvent *event = [NSApp currentEvent]; + NSEventType type = [event type]; + if (type == NSRightMouseDown || (type == NSLeftMouseDown && ([event modifierFlags] & NSControlKeyMask))) + return self; + + return [super hitTest:point]; +} + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + NSMenu *menu = [[NSMenu alloc] initWithTitle:@""]; + + NSEnumerator *menuItemEnumerator = [[[_pdfView menuForEvent:theEvent] itemArray] objectEnumerator]; + while (NSMenuItem *item = [menuItemEnumerator nextObject]) { + NSMenuItem *itemCopy = [item copy]; + [menu addItem:itemCopy]; + [itemCopy release]; + + if ([item action] != @selector(copy:)) + continue; + + // Add in an "Open with <default PDF viewer>" item + NSString *appName = nil; + NSImage *appIcon = nil; + + _applicationInfoForMIMEType(@"application/pdf", &appName, &appIcon); + if (!appName) + appName = WEB_UI_STRING("Finder", "Default application name for Open With context menu"); + + // To match the PDFKit style, we'll add Open with Preview even when there's no document yet to view, and + // disable it using validateUserInterfaceItem. + NSString *title = [NSString stringWithFormat:WEB_UI_STRING("Open with %@", "context menu item for PDF"), appName]; + + item = [[NSMenuItem alloc] initWithTitle:title action:@selector(_openWithFinder:) keyEquivalent:@""]; + if (appIcon) + [item setImage:appIcon]; + [menu addItem:[NSMenuItem separatorItem]]; + [menu addItem:item]; + [item release]; + } + + return [menu autorelease]; +} + +// MARK: NSUserInterfaceValidations PROTOCOL IMPLEMENTATION + +- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item +{ + SEL action = [item action]; + if (action == @selector(_openWithFinder:)) + return [_pdfView document] != nil; + return YES; +} + +// MARK: PDFView delegate methods + +- (void)PDFViewWillClickOnLink:(PDFView *)sender withURL:(NSURL *)URL +{ + _pdfViewController->linkClicked([URL absoluteString]); +} - (void)PDFViewOpenPDFInNativeApplication:(PDFView *)sender { @@ -416,4 +582,55 @@ NSString *PDFViewController::pathToPDFOnDisk() return path; } +void PDFViewController::linkClicked(const String& url) +{ + NSEvent* nsEvent = [NSApp currentEvent]; + WebMouseEvent event; + switch ([nsEvent type]) { + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + event = WebEventFactory::createWebMouseEvent(nsEvent, m_pdfView); + default: + // For non mouse-clicks or for keyboard events, pass an empty WebMouseEvent + // through. The event is only used by the WebFrameLoaderClient to determine + // the modifier keys and which mouse button is down. These queries will be + // valid with an empty event. + break; + } + + page()->linkClicked(url, event); +} + +void PDFViewController::findString(const String& string, FindOptions options, unsigned maxMatchCount) +{ + BOOL forward = !(options & FindOptionsBackwards); + BOOL caseFlag = !(options & FindOptionsCaseInsensitive); + BOOL wrapFlag = options & FindOptionsWrapAround; + + PDFSelection *selection = [m_wkPDFView.get() _nextMatchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag fromSelection:[m_pdfView currentSelection] startInSelection:NO]; + NSUInteger matchCount = [m_wkPDFView.get() _countMatches:string caseSensitive:caseFlag]; + if (matchCount > maxMatchCount) + matchCount = maxMatchCount; + + if (!selection) { + page()->didFailToFindString(string); + return; + } + + [m_pdfView setCurrentSelection:selection]; + [m_pdfView scrollSelectionToVisible:nil]; + page()->didFindString(string, matchCount); +} + +void PDFViewController::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount) +{ + BOOL caseFlag = !(options & FindOptionsCaseInsensitive); + + NSUInteger matchCount = [m_wkPDFView.get() _countMatches:string caseSensitive:caseFlag]; + if (matchCount > maxMatchCount) + matchCount = maxMatchCount; + page()->didCountStringMatches(string, matchCount); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h index e217fc5..9e08a28 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ #include "PageClient.h" #include <wtf/RetainPtr.h> +@class WKEditorUndoTargetObjC; @class WKView; -@class WebEditorUndoTargetObjC; namespace WebKit { @@ -63,16 +63,18 @@ private: virtual void processDidCrash(); virtual void pageClosed(); virtual void didRelaunchProcess(); - virtual void setFocus(bool focused); - virtual void takeFocus(bool direction); virtual void toolTipChanged(const String& oldToolTip, const String& newToolTip); virtual void setCursor(const WebCore::Cursor&); virtual void setViewportArguments(const WebCore::ViewportArguments&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); - virtual void interceptKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commandName, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines); + virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); + virtual void executeUndoRedo(WebPageProxy::UndoOrRedo); + virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>&); + virtual bool executeSavedCommandBySelector(const String& selector); virtual void setDragImage(const WebCore::IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag); + virtual void updateSecureInputState(); virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); @@ -100,10 +102,13 @@ private: virtual double customRepresentationZoomFactor(); virtual void setCustomRepresentationZoomFactor(double); + virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount); + virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount); virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects); virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&); + virtual void dismissDictionaryLookupPanel(); virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel); @@ -113,7 +118,7 @@ private: virtual float userSpaceScaleFactor() const; WKView* m_wkView; - RetainPtr<WebEditorUndoTargetObjC> m_undoTarget; + RetainPtr<WKEditorUndoTargetObjC> m_undoTarget; #if !defined(BUILDING_ON_SNOW_LEOPARD) CorrectionPanel m_correctionPanel; #endif diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm index 7a0d62d..e1888de 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -52,20 +52,24 @@ @end using namespace WebCore; +using namespace WebKit; -@interface WebEditCommandObjC : NSObject +@interface WKEditCommandObjC : NSObject { - RefPtr<WebKit::WebEditCommandProxy> m_command; + RefPtr<WebEditCommandProxy> m_command; } +- (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command; +- (WebEditCommandProxy*)command; +@end -- (id)initWithWebEditCommandProxy:(PassRefPtr<WebKit::WebEditCommandProxy>)command; -- (WebKit::WebEditCommandProxy*)command; - +@interface WKEditorUndoTargetObjC : NSObject +- (void)undoEditing:(id)sender; +- (void)redoEditing:(id)sender; @end -@implementation WebEditCommandObjC +@implementation WKEditCommandObjC -- (id)initWithWebEditCommandProxy:(PassRefPtr<WebKit::WebEditCommandProxy>)command +- (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command { self = [super init]; if (!self) @@ -75,31 +79,24 @@ using namespace WebCore; return self; } -- (WebKit::WebEditCommandProxy*)command +- (WebEditCommandProxy*)command { return m_command.get(); } @end -@interface WebEditorUndoTargetObjC : NSObject - -- (void)undoEditing:(id)sender; -- (void)redoEditing:(id)sender; - -@end - -@implementation WebEditorUndoTargetObjC +@implementation WKEditorUndoTargetObjC - (void)undoEditing:(id)sender { - ASSERT([sender isKindOfClass:[WebEditCommandObjC class]]); + ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]); [sender command]->unapply(); } - (void)redoEditing:(id)sender { - ASSERT([sender isKindOfClass:[WebEditCommandObjC class]]); + ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]); [sender command]->reapply(); } @@ -119,7 +116,7 @@ PassOwnPtr<PageClientImpl> PageClientImpl::create(WKView* wkView) PageClientImpl::PageClientImpl(WKView* wkView) : m_wkView(wkView) - , m_undoTarget(AdoptNS, [[WebEditorUndoTargetObjC alloc] init]) + , m_undoTarget(AdoptNS, [[WKEditorUndoTargetObjC alloc] init]) { } @@ -157,7 +154,7 @@ IntSize PageClientImpl::viewSize() bool PageClientImpl::isViewWindowActive() { - return [[m_wkView window] isKeyWindow]; + return [[m_wkView window] isKeyWindow] || [NSApp keyWindow] == [m_wkView window]; } bool PageClientImpl::isViewFocused() @@ -170,6 +167,9 @@ bool PageClientImpl::isViewVisible() if (![m_wkView window]) return false; + if (![[m_wkView window] isVisible]) + return false; + if ([m_wkView isHiddenOrHasHiddenAncestor]) return false; @@ -196,20 +196,6 @@ void PageClientImpl::didRelaunchProcess() [m_wkView _didRelaunchProcess]; } -void PageClientImpl::setFocus(bool focused) -{ - if (focused) - [[m_wkView window] makeFirstResponder:m_wkView]; - else - // takeFocus in this context means take focus away from the WKView. - takeFocus(true); -} - -void PageClientImpl::takeFocus(bool direction) -{ - [m_wkView _takeFocus:direction]; -} - void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) { [m_wkView _toolTipChangedFrom:nsStringFromWebCoreString(oldToolTip) to:nsStringFromWebCoreString(newToolTip)]; @@ -223,67 +209,19 @@ void PageClientImpl::setCursor(const WebCore::Cursor& cursor) void PageClientImpl::setViewportArguments(const WebCore::ViewportArguments&) { - -} - -static NSString* nameForEditAction(EditAction editAction) -{ - // FIXME: Use localized strings. - // FIXME: Move this to a platform independent location. - - switch (editAction) { - case EditActionUnspecified: return nil; - case EditActionSetColor: return @"Set Color"; - case EditActionSetBackgroundColor: return @"Set Background Color"; - case EditActionTurnOffKerning: return @"Turn Off Kerning"; - case EditActionTightenKerning: return @"Tighten Kerning"; - case EditActionLoosenKerning: return @"Loosen Kerning"; - case EditActionUseStandardKerning: return @"Use Standard Kerning"; - case EditActionTurnOffLigatures: return @"Turn Off Ligatures"; - case EditActionUseStandardLigatures: return @"Use Standard Ligatures"; - case EditActionUseAllLigatures: return @"Use All Ligatures"; - case EditActionRaiseBaseline: return @"Raise Baseline"; - case EditActionLowerBaseline: return @"Lower Baseline"; - case EditActionSetTraditionalCharacterShape: return @"Set Traditional Character Shape"; - case EditActionSetFont: return @"Set Font"; - case EditActionChangeAttributes: return @"Change Attributes"; - case EditActionAlignLeft: return @"Align Left"; - case EditActionAlignRight: return @"Align Right"; - case EditActionCenter: return @"Center"; - case EditActionJustify: return @"Justify"; - case EditActionSetWritingDirection: return @"Set Writing Direction"; - case EditActionSubscript: return @"Subscript"; - case EditActionSuperscript: return @"Superscript"; - case EditActionUnderline: return @"Underline"; - case EditActionOutline: return @"Outline"; - case EditActionUnscript: return @"Unscript"; - case EditActionDrag: return @"Drag"; - case EditActionCut: return @"Cut"; - case EditActionPaste: return @"Paste"; - case EditActionPasteFont: return @"Paste Font"; - case EditActionPasteRuler: return @"Paste Ruler"; - case EditActionTyping: return @"Typing"; - case EditActionCreateLink: return @"Create Link"; - case EditActionUnlink: return @"Unlink"; - case EditActionInsertList: return @"Insert List"; - case EditActionFormatBlock: return @"Formatting"; - case EditActionIndent: return @"Indent"; - case EditActionOutdent: return @"Outdent"; - } - return nil; } void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo) { RefPtr<WebEditCommandProxy> command = prpCommand; - RetainPtr<WebEditCommandObjC> commandObjC(AdoptNS, [[WebEditCommandObjC alloc] initWithWebEditCommandProxy:command]); - NSString *actionName = nameForEditAction(command->editAction()); + RetainPtr<WKEditCommandObjC> commandObjC(AdoptNS, [[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command]); + String actionName = WebEditCommandProxy::nameForEditAction(command->editAction()); NSUndoManager *undoManager = [m_wkView undoManager]; [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()]; - if (actionName) - [undoManager setActionName:actionName]; + if (!actionName.isEmpty()) + [undoManager setActionName:(NSString *)actionName]; } void PageClientImpl::clearAllEditCommands() @@ -291,10 +229,19 @@ void PageClientImpl::clearAllEditCommands() [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()]; } -void PageClientImpl::interceptKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commandsList, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines) +bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) { - commandsList = [m_wkView _interceptKeyEvent:event.nativeEvent()]; - [m_wkView _getTextInputState:selectionStart selectionEnd:selectionEnd underlines:underlines]; + return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] canUndo] : [[m_wkView undoManager] canRedo]; +} + +void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) +{ + return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] undo] : [[m_wkView undoManager] redo]; +} + +bool PageClientImpl::interpretKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commands) +{ + return [m_wkView _interpretKeyEvent:event.nativeEvent() savingCommandsTo:commands]; } void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) @@ -304,7 +251,12 @@ void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<Sha [m_wkView _setDragImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag]; } - + +void PageClientImpl::updateSecureInputState() +{ + [m_wkView _updateSecureInputState]; +} + FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect) { return [m_wkView _convertToDeviceSpace:rect]; @@ -408,6 +360,16 @@ void PageClientImpl::setCustomRepresentationZoomFactor(double zoomFactor) [m_wkView _setCustomRepresentationZoomFactor:zoomFactor]; } +void PageClientImpl::findStringInCustomRepresentation(const String& string, FindOptions options, unsigned maxMatchCount) +{ + [m_wkView _findStringInCustomRepresentation:string withFindOptions:options maxMatchCount:maxMatchCount]; +} + +void PageClientImpl::countStringMatchesInCustomRepresentation(const String& string, FindOptions options, unsigned maxMatchCount) +{ + [m_wkView _countStringMatchesInCustomRepresentation:string withFindOptions:options maxMatchCount:maxMatchCount]; +} + void PageClientImpl::flashBackingStoreUpdates(const Vector<IntRect>&) { notImplemented(); @@ -437,6 +399,13 @@ void PageClientImpl::didPerformDictionaryLookup(const String& text, double scale #endif } +void PageClientImpl::dismissDictionaryLookupPanel() +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + WKHideWordDefinitionWindow(); +#endif +} + void PageClientImpl::showCorrectionPanel(CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) { #if !defined(BUILDING_ON_SNOW_LEOPARD) @@ -484,4 +453,9 @@ float PageClientImpl::userSpaceScaleFactor() const #endif } +bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString) +{ + return [m_wkView _executeSavedCommandBySelector:NSSelectorFromString(selectorString)]; +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm b/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm index 3b69a1d..2c9ceaa 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm @@ -86,7 +86,14 @@ BOOL hadMarkedText = [_inputTextView hasMarkedText]; *string = nil; - + + // Let TSM know that a bottom input window would be created for marked text. + EventRef carbonEvent = static_cast<EventRef>(const_cast<void*>([event eventRef])); + if (carbonEvent) { + Boolean ignorePAH = true; + SetEventParameter(carbonEvent, 'iPAH', typeBoolean, sizeof(ignorePAH), &ignorePAH); + } + if (![[_inputTextView inputContext] handleEvent:event]) return NO; diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.h b/Source/WebKit2/UIProcess/API/mac/WKView.h index 8c1826c..098b3ca 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.h +++ b/Source/WebKit2/UIProcess/API/mac/WKView.h @@ -29,7 +29,7 @@ @class WKViewData; WK_EXPORT -@interface WKView : NSView <NSTextInput> { +@interface WKView : NSView <NSTextInputClient> { WKViewData *_data; unsigned _frameSizeUpdatesDisabledCount; } diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index 05693ef..80345f7 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -26,14 +26,17 @@ #import "config.h" #import "WKView.h" +#import "AttributedString.h" #import "ChunkedUpdateDrawingAreaProxy.h" #import "DataReference.h" #import "DrawingAreaProxyImpl.h" +#import "EditorState.h" #import "FindIndicator.h" #import "FindIndicatorWindow.h" #import "LayerTreeContext.h" #import "Logging.h" #import "NativeWebKeyboardEvent.h" +#import "NativeWebMouseEvent.h" #import "PDFViewController.h" #import "PageClientImpl.h" #import "PasteboardTypes.h" @@ -69,24 +72,23 @@ #import <wtf/RefPtr.h> #import <wtf/RetainPtr.h> -@interface NSApplication (WebNSApplicationDetails) +@interface NSApplication (WKNSApplicationDetails) - (void)speakString:(NSString *)string; - (void)_setCurrentEvent:(NSEvent *)event; @end -@interface NSWindow (WebNSWindowDetails) +@interface NSObject (WKNSTextInputContextDetails) +- (BOOL)wantsToHandleMouseEvents; +- (BOOL)handleMouseEvent:(NSEvent *)event; +@end + +@interface NSWindow (WKNSWindowDetails) - (NSRect)_growBoxRect; - (id)_growBoxOwner; - (void)_setShowOpaqueGrowBoxForOwner:(id)owner; - (BOOL)_updateGrowBoxForWindowFrameChange; @end -extern "C" { - // Need to declare this attribute name because AppKit exports it but does not make it available in API or SPI headers. - // <rdar://problem/8631468> tracks the request to make it available. This code should be removed when the bug is closed. - extern NSString *NSTextInputReplacementRangeAttributeName; -} - using namespace WebKit; using namespace WebCore; @@ -98,6 +100,13 @@ typedef HashMap<String, ValidationVector> ValidationMap; } +struct WKViewInterpretKeyEventsParameters { + bool eventInterpretationHadSideEffects; + bool consumedByIM; + bool executingSavedKeypressCommands; + Vector<KeypressCommand>* commands; +}; + @interface WKViewData : NSObject { @public OwnPtr<PageClientImpl> _pageClient; @@ -122,18 +131,13 @@ typedef HashMap<String, ValidationVector> ValidationMap; // the application to distinguish the case of a new event from one // that has been already sent to WebCore. RetainPtr<NSEvent> _keyDownEventBeingResent; - bool _isInInterpretKeyEvents; - Vector<KeypressCommand> _commandsList; + WKViewInterpretKeyEventsParameters* _interpretKeyEventsParameters; NSSize _resizeScrollOffset; // The identifier of the plug-in we want to send complex text input to, or 0 if there is none. uint64_t _pluginComplexTextInputIdentifier; - Vector<CompositionUnderline> _underlines; - unsigned _selectionStart; - unsigned _selectionEnd; - bool _inBecomeFirstResponder; bool _inResignFirstResponder; NSEvent *_mouseDownEvent; @@ -150,15 +154,21 @@ typedef HashMap<String, ValidationVector> ValidationMap; BOOL _hasSpellCheckerDocumentTag; NSInteger _spellCheckerDocumentTag; + + BOOL _inSecureInputState; } @end -@implementation WKViewData +@interface WKResponderChainSink : NSResponder { + NSResponder *_lastResponderInChain; + bool _didReceiveUnhandledCommand; +} +- (id)initWithResponderChain:(NSResponder *)chain; +- (void)detach; +- (bool)didReceiveUnhandledCommand; @end -@interface NSObject (NSTextInputContextDetails) -- (BOOL)wantsToHandleMouseEvents; -- (BOOL)handleMouseEvent:(NSEvent *)event; +@implementation WKViewData @end @implementation WKView @@ -239,6 +249,8 @@ typedef HashMap<String, ValidationVector> ValidationMap; { _data->_page->close(); + ASSERT(!_data->_inSecureInputState); + [_data release]; _data = nil; @@ -282,7 +294,10 @@ typedef HashMap<String, ValidationVector> ValidationMap; NSSelectionDirection direction = [[self window] keyViewSelectionDirection]; _data->_inBecomeFirstResponder = true; + + [self _updateSecureInputState]; _data->_page->viewStateDidChange(WebPageProxy::ViewIsFocused); + _data->_inBecomeFirstResponder = false; if (direction != NSDirectSelection) @@ -294,7 +309,13 @@ typedef HashMap<String, ValidationVector> ValidationMap; - (BOOL)resignFirstResponder { _data->_inResignFirstResponder = true; + + if (_data->_inSecureInputState) { + DisableSecureEventInput(); + _data->_inSecureInputState = NO; + } _data->_page->viewStateDidChange(WebPageProxy::ViewIsFocused); + _data->_inResignFirstResponder = false; return YES; @@ -514,13 +535,13 @@ WEBCORE_COMMAND(yankAndSelect) - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType { - BOOL isValidSendType = !sendType || ([PasteboardTypes::forSelection() containsObject:sendType] && !_data->_page->selectionState().isNone); + BOOL isValidSendType = !sendType || ([PasteboardTypes::forSelection() containsObject:sendType] && !_data->_page->editorState().selectionIsNone); BOOL isValidReturnType = NO; if (!returnType) isValidReturnType = YES; - else if ([PasteboardTypes::forEditing() containsObject:returnType] && _data->_page->selectionState().isContentEditable) { + else if ([PasteboardTypes::forEditing() containsObject:returnType] && _data->_page->editorState().isContentEditable) { // We can insert strings in any editable context. We can insert other types, like images, only in rich edit contexts. - isValidReturnType = _data->_page->selectionState().isContentRichlyEditable || [returnType isEqualToString:NSStringPboardType]; + isValidReturnType = _data->_page->editorState().isContentRichlyEditable || [returnType isEqualToString:NSStringPboardType]; } if (isValidSendType && isValidReturnType) return self; @@ -604,12 +625,12 @@ static void validateCommandCallback(WKStringRef commandName, bool isEnabled, int if (action == @selector(showGuessPanel:)) { if (NSMenuItem *menuItem = ::menuItem(item)) - [menuItem setTitle:contextMenuItemTagShowSpellingPanel([[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible])]; - return _data->_page->selectionState().isContentEditable; + [menuItem setTitle:contextMenuItemTagShowSpellingPanel(![[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible])]; + return _data->_page->editorState().isContentEditable; } if (action == @selector(checkSpelling:) || action == @selector(changeSpelling:)) - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; if (action == @selector(toggleContinuousSpellChecking:)) { bool enabled = TextChecker::isContinuousSpellCheckingAllowed(); @@ -627,47 +648,47 @@ static void validateCommandCallback(WKStringRef commandName, bool isEnabled, int if (action == @selector(toggleAutomaticSpellingCorrection:)) { bool checked = TextChecker::state().isAutomaticSpellingCorrectionEnabled; [menuItem(item) setState:checked ? NSOnState : NSOffState]; - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; } if (action == @selector(orderFrontSubstitutionsPanel:)) { if (NSMenuItem *menuItem = ::menuItem(item)) - [menuItem setTitle:contextMenuItemTagShowSubstitutions([[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible])]; - return _data->_page->selectionState().isContentEditable; + [menuItem setTitle:contextMenuItemTagShowSubstitutions(![[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible])]; + return _data->_page->editorState().isContentEditable; } if (action == @selector(toggleSmartInsertDelete:)) { bool checked = _data->_page->isSmartInsertDeleteEnabled(); [menuItem(item) setState:checked ? NSOnState : NSOffState]; - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; } if (action == @selector(toggleAutomaticQuoteSubstitution:)) { bool checked = TextChecker::state().isAutomaticQuoteSubstitutionEnabled; [menuItem(item) setState:checked ? NSOnState : NSOffState]; - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; } if (action == @selector(toggleAutomaticDashSubstitution:)) { bool checked = TextChecker::state().isAutomaticDashSubstitutionEnabled; [menuItem(item) setState:checked ? NSOnState : NSOffState]; - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; } if (action == @selector(toggleAutomaticLinkDetection:)) { bool checked = TextChecker::state().isAutomaticLinkDetectionEnabled; [menuItem(item) setState:checked ? NSOnState : NSOffState]; - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; } if (action == @selector(toggleAutomaticTextReplacement:)) { bool checked = TextChecker::state().isAutomaticTextReplacementEnabled; [menuItem(item) setState:checked ? NSOnState : NSOffState]; - return _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().isContentEditable; } if (action == @selector(uppercaseWord:) || action == @selector(lowercaseWord:) || action == @selector(capitalizeWord:)) - return _data->_page->selectionState().selectedRangeLength && _data->_page->selectionState().isContentEditable; + return _data->_page->editorState().selectionIsRange && _data->_page->editorState().isContentEditable; if (action == @selector(stopSpeaking:)) return [NSApp isSpeaking]; @@ -751,9 +772,6 @@ static void speakString(WKStringRef string, WKErrorRef error, void*) TextChecker::setContinuousSpellCheckingEnabled(spellCheckingEnabled); _data->_page->process()->updateTextCheckerState(); - - if (!spellCheckingEnabled) - _data->_page->unmarkAllMisspellings(); } - (BOOL)isGrammarCheckingEnabled @@ -768,9 +786,6 @@ static void speakString(WKStringRef string, WKErrorRef error, void*) TextChecker::setGrammarCheckingEnabled(flag); _data->_page->process()->updateTextCheckerState(); - - if (!flag) - _data->_page->unmarkAllBadGrammar(); } - (IBAction)toggleGrammarChecking:(id)sender @@ -779,9 +794,6 @@ static void speakString(WKStringRef string, WKErrorRef error, void*) TextChecker::setGrammarCheckingEnabled(grammarCheckingEnabled); _data->_page->process()->updateTextCheckerState(); - - if (!grammarCheckingEnabled) - _data->_page->unmarkAllBadGrammar(); } - (IBAction)toggleAutomaticSpellingCorrection:(id)sender @@ -927,6 +939,33 @@ static void speakString(WKStringRef string, WKErrorRef error, void*) _data->_mouseDownEvent = [event retain]; } +#define NATIVE_MOUSE_EVENT_HANDLER(Selector) \ + - (void)Selector:(NSEvent *)theEvent \ + { \ + if ([[self inputContext] handleEvent:theEvent]) { \ + LOG(TextInput, "%s was handled by text input context", String(#Selector).substring(0, String(#Selector).find("Internal")).ascii().data()); \ + return; \ + } \ + NativeWebMouseEvent webEvent(theEvent, self); \ + _data->_page->handleMouseEvent(webEvent); \ + } + +NATIVE_MOUSE_EVENT_HANDLER(mouseEntered) +NATIVE_MOUSE_EVENT_HANDLER(mouseExited) +NATIVE_MOUSE_EVENT_HANDLER(mouseMovedInternal) +NATIVE_MOUSE_EVENT_HANDLER(mouseDownInternal) +NATIVE_MOUSE_EVENT_HANDLER(mouseUpInternal) +NATIVE_MOUSE_EVENT_HANDLER(mouseDraggedInternal) +NATIVE_MOUSE_EVENT_HANDLER(otherMouseDown) +NATIVE_MOUSE_EVENT_HANDLER(otherMouseDragged) +NATIVE_MOUSE_EVENT_HANDLER(otherMouseMoved) +NATIVE_MOUSE_EVENT_HANDLER(otherMouseUp) +NATIVE_MOUSE_EVENT_HANDLER(rightMouseDown) +NATIVE_MOUSE_EVENT_HANDLER(rightMouseDragged) +NATIVE_MOUSE_EVENT_HANDLER(rightMouseUp) + +#undef NATIVE_MOUSE_EVENT_HANDLER + #define EVENT_HANDLER(Selector, Type) \ - (void)Selector:(NSEvent *)theEvent \ { \ @@ -934,28 +973,17 @@ static void speakString(WKStringRef string, WKErrorRef error, void*) _data->_page->handle##Type##Event(webEvent); \ } -EVENT_HANDLER(mouseEntered, Mouse) -EVENT_HANDLER(mouseExited, Mouse) -EVENT_HANDLER(mouseMoved, Mouse) -EVENT_HANDLER(otherMouseDown, Mouse) -EVENT_HANDLER(otherMouseDragged, Mouse) -EVENT_HANDLER(otherMouseMoved, Mouse) -EVENT_HANDLER(otherMouseUp, Mouse) -EVENT_HANDLER(rightMouseDown, Mouse) -EVENT_HANDLER(rightMouseDragged, Mouse) -EVENT_HANDLER(rightMouseMoved, Mouse) -EVENT_HANDLER(rightMouseUp, Mouse) EVENT_HANDLER(scrollWheel, Wheel) #undef EVENT_HANDLER -- (void)_mouseHandler:(NSEvent *)event +- (void)mouseMoved:(NSEvent *)event { - NSInputManager *currentInputManager = [NSInputManager currentInputManager]; - if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event]) + // When a view is first responder, it gets mouse moved events even when the mouse is outside its visible rect. + if (self == [[self window] firstResponder] && !NSPointInRect([self convertPoint:[event locationInWindow] fromView:nil], [self visibleRect])) return; - WebMouseEvent webEvent = WebEventFactory::createWebMouseEvent(event, self); - _data->_page->handleMouseEvent(webEvent); + + [self mouseMovedInternal:event]; } - (void)mouseDown:(NSEvent *)event @@ -963,20 +991,57 @@ EVENT_HANDLER(scrollWheel, Wheel) [self _setMouseDownEvent:event]; _data->_ignoringMouseDraggedEvents = NO; _data->_dragHasStarted = NO; - [self _mouseHandler:event]; + [self mouseDownInternal:event]; } - (void)mouseUp:(NSEvent *)event { [self _setMouseDownEvent:nil]; - [self _mouseHandler:event]; + [self mouseUpInternal:event]; } - (void)mouseDragged:(NSEvent *)event { if (_data->_ignoringMouseDraggedEvents) return; - [self _mouseHandler:event]; + [self mouseDraggedInternal:event]; +} + +- (BOOL)acceptsFirstMouse:(NSEvent *)event +{ + // There's a chance that responding to this event will run a nested event loop, and + // fetching a new event might release the old one. Retaining and then autoreleasing + // the current event prevents that from causing a problem inside WebKit or AppKit code. + [[event retain] autorelease]; + + if (![self hitTest:[event locationInWindow]]) + return NO; + + [self _setMouseDownEvent:event]; + bool result = _data->_page->acceptsFirstMouse([event eventNumber], WebEventFactory::createWebMouseEvent(event, self)); + [self _setMouseDownEvent:nil]; + return result; +} + +- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)event +{ + // If this is the active window or we don't have a range selection, there is no need to perform additional checks + // and we can avoid making a synchronous call to the WebProcess. + if ([[self window] isKeyWindow] || _data->_page->editorState().selectionIsNone || !_data->_page->editorState().selectionIsRange) + return NO; + + // There's a chance that responding to this event will run a nested event loop, and + // fetching a new event might release the old one. Retaining and then autoreleasing + // the current event prevents that from causing a problem inside WebKit or AppKit code. + [[event retain] autorelease]; + + if (![self hitTest:[event locationInWindow]]) + return NO; + + [self _setMouseDownEvent:event]; + bool result = _data->_page->shouldDelayWindowOrderingForEvent(WebEventFactory::createWebMouseEvent(event, self)); + [self _setMouseDownEvent:nil]; + return result; } #if ENABLE(GESTURE_EVENTS) @@ -1018,52 +1083,75 @@ static const short kIOHIDEventTypeScroll = 6; { LOG(TextInput, "doCommandBySelector:\"%s\"", sel_getName(selector)); - if (!_data->_isInInterpretKeyEvents) { + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + if (parameters) + parameters->consumedByIM = false; + + // As in insertText:replacementRange:, we assume that the call comes from an input method if there is marked text. + bool isFromInputMethod = _data->_page->editorState().hasComposition; + + if (parameters && !isFromInputMethod) + parameters->commands->append(KeypressCommand(NSStringFromSelector(selector))); + else { + // FIXME: Send the command to Editor synchronously and only send it along the + // responder chain if it's a selector that does not correspond to an editing command. [super doCommandBySelector:selector]; - return; } - if (selector != @selector(noop:)) - _data->_commandsList.append(KeypressCommand(commandNameForSelector(selector))); } - (void)insertText:(id)string { - BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; // Otherwise, NSString - - LOG(TextInput, "insertText:\"%@\"", isAttributedString ? [string string] : string); + // Unlike and NSTextInputClient variant with replacementRange, this NSResponder method is called when there is no input context, + // so text input processing isn't performed. We are not going to actually insert any text in that case, but saving an insertText + // command ensures that a keypress event is dispatched as appropriate. + [self insertText:string replacementRange:NSMakeRange(NSNotFound, 0)]; +} + +- (void)insertText:(id)string replacementRange:(NSRange)replacementRange +{ + BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; + ASSERT(isAttributedString || [string isKindOfClass:[NSString class]]); + + if (replacementRange.location != NSNotFound) + LOG(TextInput, "insertText:\"%@\" replacementRange:(%u, %u)", isAttributedString ? [string string] : string, replacementRange.location, replacementRange.length); + else + LOG(TextInput, "insertText:\"%@\"", isAttributedString ? [string string] : string); + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + if (parameters) + parameters->consumedByIM = false; + NSString *text; - bool isFromInputMethod = _data->_page->selectionState().hasComposition; + bool isFromInputMethod = _data->_page->editorState().hasComposition; if (isAttributedString) { + // FIXME: We ignore most attributes from the string, so for example inserting from Character Palette loses font and glyph variation data. text = [string string]; - // We deal with the NSTextInputReplacementRangeAttributeName attribute from NSAttributedString here - // simply because it is used by at least one Input Method -- it corresonds to the kEventParamTextInputSendReplaceRange - // event in TSM. This behaviour matches that of -[WebHTMLView setMarkedText:selectedRange:] when it receives an - // NSAttributedString - NSString *rangeString = [string attribute:NSTextInputReplacementRangeAttributeName atIndex:0 longestEffectiveRange:NULL inRange:NSMakeRange(0, [text length])]; - LOG(TextInput, "ReplacementRange: %@", rangeString); - if (rangeString) - isFromInputMethod = YES; } else text = string; + // insertText can be called for several reasons: + // - If it's from normal key event processing (including key bindings), we may need to save the action to perform it later. + // - If it's from an input method, then we should go ahead and insert the text now. We assume it's from the input method if we have marked text. + // FIXME: In theory, this could be wrong for some input methods, so we should try to find another way to determine if the call is from the input method. + // - If it's sent outside of keyboard event processing (e.g. from Character Viewer, or when confirming an inline input area with a mouse), + // then we also execute it immediately, as there will be no other chance. + if (parameters && !isFromInputMethod) { + ASSERT(replacementRange.location == NSNotFound); + parameters->commands->append(KeypressCommand("insertText:", text)); + return; + } + String eventText = text; - - // We'd need a different code path here if we wanted to be able to handle this - // outside of interpretKeyEvents. - ASSERT(_data->_isInInterpretKeyEvents); + eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore + bool eventHandled = _data->_page->insertText(eventText, replacementRange.location, NSMaxRange(replacementRange)); - if (!isFromInputMethod) - _data->_commandsList.append(KeypressCommand("insertText", text)); - else { - eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore - _data->_commandsList.append(KeypressCommand("insertText", eventText)); - } + if (parameters) + parameters->eventInterpretationHadSideEffects |= eventHandled; } - (BOOL)_handleStyleKeyEquivalent:(NSEvent *)event { - if (!_data->_page->selectionState().isContentEditable) + if (!_data->_page->editorState().isContentEditable) return NO; if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) != NSCommandKeyMask) @@ -1130,9 +1218,6 @@ static const short kIOHIDEventTypeScroll = 6; } } - _data->_underlines.clear(); - _data->_selectionStart = 0; - _data->_selectionEnd = 0; // We could be receiving a key down from AppKit if we have re-sent an event // that maps to an action that is currently unavailable (for example a copy when // there is no range selection). @@ -1144,37 +1229,108 @@ static const short kIOHIDEventTypeScroll = 6; _data->_page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent, self)); } -- (NSTextInputContext *)inputContext { - if (_data->_pluginComplexTextInputIdentifier && !_data->_isInInterpretKeyEvents) +- (void)flagsChanged:(NSEvent *)theEvent +{ + // There's a chance that responding to this event will run a nested event loop, and + // fetching a new event might release the old one. Retaining and then autoreleasing + // the current event prevents that from causing a problem inside WebKit or AppKit code. + [[theEvent retain] autorelease]; + + unsigned short keyCode = [theEvent keyCode]; + + // Don't make an event from the num lock and function keys + if (!keyCode || keyCode == 10 || keyCode == 63) + return; + + _data->_page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent, self)); +} + +- (void)_executeSavedKeypressCommands +{ + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + if (!parameters || parameters->commands->isEmpty()) + return; + + // We could be called again if the execution of one command triggers a call to selectedRange. + // In this case, the state is up to date, and we don't need to execute any more saved commands to return a result. + if (parameters->executingSavedKeypressCommands) + return; + + parameters->executingSavedKeypressCommands = true; + parameters->eventInterpretationHadSideEffects |= _data->_page->executeKeypressCommands(*parameters->commands); + parameters->commands->clear(); + parameters->executingSavedKeypressCommands = false; +} + +- (NSTextInputContext *)inputContext +{ + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + + if (_data->_pluginComplexTextInputIdentifier && !parameters) return [[WKTextInputWindowController sharedTextInputWindowController] inputContext]; + // Disable text input machinery when in non-editable content. An invisible inline input area affects performance, and can prevent Expose from working. + if (!_data->_page->editorState().isContentEditable) + return nil; + return [super inputContext]; } - (NSRange)selectedRange { - if (_data->_page->selectionState().isNone || !_data->_page->selectionState().isContentEditable) - return NSMakeRange(NSNotFound, 0); - - LOG(TextInput, "selectedRange -> (%u, %u)", _data->_page->selectionState().selectedRangeStart, _data->_page->selectionState().selectedRangeLength); - return NSMakeRange(_data->_page->selectionState().selectedRangeStart, _data->_page->selectionState().selectedRangeLength); + [self _executeSavedKeypressCommands]; + + uint64_t selectionStart; + uint64_t selectionLength; + _data->_page->getSelectedRange(selectionStart, selectionLength); + + NSRange result = NSMakeRange(selectionStart, selectionLength); + if (result.location == NSNotFound) + LOG(TextInput, "selectedRange -> (NSNotFound, %u)", result.length); + else + LOG(TextInput, "selectedRange -> (%u, %u)", result.location, result.length); + + return result; } - (BOOL)hasMarkedText { - LOG(TextInput, "hasMarkedText -> %u", _data->_page->selectionState().hasComposition); - return _data->_page->selectionState().hasComposition; + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + + BOOL result; + if (parameters) { + result = _data->_page->editorState().hasComposition; + if (result) { + // A saved command can confirm a composition, but it cannot start a new one. + [self _executeSavedKeypressCommands]; + result = _data->_page->editorState().hasComposition; + } + } else { + uint64_t location; + uint64_t length; + _data->_page->getMarkedRange(location, length); + result = location != NSNotFound; + } + + LOG(TextInput, "hasMarkedText -> %u", result); + return result; } - (void)unmarkText { + [self _executeSavedKeypressCommands]; + LOG(TextInput, "unmarkText"); - // We'd need a different code path here if we wanted to be able to handle this - // outside of interpretKeyEvents. - ASSERT(_data->_isInInterpretKeyEvents); + // Use pointer to get parameters passed to us by the caller of interpretKeyEvents. + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + + if (parameters) { + parameters->eventInterpretationHadSideEffects = true; + parameters->consumedByIM = false; + } - _data->_commandsList.append(KeypressCommand("unmarkText")); + _data->_page->confirmComposition(); } - (NSArray *)validAttributesForMarkedText @@ -1183,7 +1339,7 @@ static const short kIOHIDEventTypeScroll = 6; if (!validAttributes) { validAttributes = [[NSArray alloc] initWithObjects: NSUnderlineStyleAttributeName, NSUnderlineColorAttributeName, - NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil]; + NSMarkedClauseSegmentAttributeName, nil]; // NSText also supports the following attributes, but it's // hard to tell which are really required for text input to // work well; I have not seen any input method make use of them yet. @@ -1215,47 +1371,86 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde } } -- (void)setMarkedText:(id)string selectedRange:(NSRange)newSelRange +- (void)setMarkedText:(id)string selectedRange:(NSRange)newSelRange replacementRange:(NSRange)replacementRange { - BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; // Otherwise, NSString - + [self _executeSavedKeypressCommands]; + + BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; + ASSERT(isAttributedString || [string isKindOfClass:[NSString class]]); + LOG(TextInput, "setMarkedText:\"%@\" selectedRange:(%u, %u)", isAttributedString ? [string string] : string, newSelRange.location, newSelRange.length); + + // Use pointer to get parameters passed to us by the caller of interpretKeyEvents. + WKViewInterpretKeyEventsParameters* parameters = _data->_interpretKeyEventsParameters; + + if (parameters) { + parameters->eventInterpretationHadSideEffects = true; + parameters->consumedByIM = false; + } - NSString *text = string; - + Vector<CompositionUnderline> underlines; + NSString *text; + if (isAttributedString) { + // FIXME: We ignore most attributes from the string, so an input method cannot specify e.g. a font or a glyph variation. text = [string string]; - extractUnderlines(string, _data->_underlines); + extractUnderlines(string, underlines); + } else + text = string; + + if (_data->_page->editorState().isInPasswordField) { + // In password fields, we only allow ASCII dead keys, and don't allow inline input, matching NSSecureTextInputField. + // Allowing ASCII dead keys is necessary to enable full Roman input when using a Vietnamese keyboard. + ASSERT(!_data->_page->editorState().hasComposition); + [[super inputContext] discardMarkedText]; // Inform the input method that we won't have an inline input area despite having been asked to. + if ([text length] == 1 && [[text decomposedStringWithCanonicalMapping] characterAtIndex:0] < 0x80) { + _data->_page->insertText(text, replacementRange.location, NSMaxRange(replacementRange)); + } else + NSBeep(); + return; } - - // We'd need a different code path here if we wanted to be able to handle this - // outside of interpretKeyEvents. - ASSERT(_data->_isInInterpretKeyEvents); - _data->_commandsList.append(KeypressCommand("setMarkedText", text)); - _data->_selectionStart = newSelRange.location; - _data->_selectionEnd = NSMaxRange(newSelRange); + _data->_page->setComposition(text, underlines, newSelRange.location, NSMaxRange(newSelRange), replacementRange.location, NSMaxRange(replacementRange)); } - (NSRange)markedRange { + [self _executeSavedKeypressCommands]; + uint64_t location; uint64_t length; - _data->_page->getMarkedRange(location, length); + LOG(TextInput, "markedRange -> (%u, %u)", location, length); return NSMakeRange(location, length); } -- (NSAttributedString *)attributedSubstringFromRange:(NSRange)nsRange +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)nsRange actualRange:(NSRangePointer)actualRange { - // This is not implemented for now. Need to figure out how to serialize the attributed string across processes. - LOG(TextInput, "attributedSubstringFromRange"); - return nil; + [self _executeSavedKeypressCommands]; + + if (!_data->_page->editorState().isContentEditable) { + LOG(TextInput, "attributedSubstringFromRange:(%u, %u) -> nil", nsRange.location, nsRange.length); + return nil; + } + + if (_data->_page->editorState().isInPasswordField) + return nil; + + AttributedString result; + _data->_page->getAttributedSubstringFromRange(nsRange.location, NSMaxRange(nsRange), result); + + if (actualRange) + *actualRange = nsRange; + + LOG(TextInput, "attributedSubstringFromRange:(%u, %u) -> \"%@\"", nsRange.location, nsRange.length, [result.string.get() string]); + return [[result.string.get() retain] autorelease]; } - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint { + [self _executeSavedKeypressCommands]; + NSWindow *window = [self window]; if (window) @@ -1267,8 +1462,10 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde return result; } -- (NSRect)firstRectForCharacterRange:(NSRange)theRange +- (NSRect)firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange { + [self _executeSavedKeypressCommands]; + // Just to match NSTextView's behavior. Regression tests cannot detect this; // to reproduce, use a test application from http://bugs.webkit.org/show_bug.cgi?id=4682 // (type something; try ranges (1, -1) and (2, -1). @@ -1281,7 +1478,10 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde NSWindow *window = [self window]; if (window) resultRect.origin = [window convertBaseToScreen:resultRect.origin]; - + + if (actualRange) + *actualRange = theRange; + LOG(TextInput, "firstRectForCharacterRange:(%u, %u) -> (%f, %f, %f, %f)", theRange.location, theRange.length, resultRect.origin.x, resultRect.origin.y, resultRect.size.width, resultRect.size.height); return resultRect; } @@ -1318,7 +1518,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); _data->_page->resetDragOperation(); - _data->_page->performDragControllerAction(DragControllerActionEntered, &dragData, [[draggingInfo draggingPasteboard] name]); + _data->_page->dragEntered(&dragData, [[draggingInfo draggingPasteboard] name]); return NSDragOperationCopy; } @@ -1327,7 +1527,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde IntPoint client([self convertPoint:[draggingInfo draggingLocation] fromView:nil]); IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); - _data->_page->performDragControllerAction(DragControllerActionUpdated, &dragData, [[draggingInfo draggingPasteboard] name]); + _data->_page->dragUpdated(&dragData, [[draggingInfo draggingPasteboard] name]); return _data->_page->dragOperation(); } @@ -1336,7 +1536,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde IntPoint client([self convertPoint:[draggingInfo draggingLocation] fromView:nil]); IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); - _data->_page->performDragControllerAction(DragControllerActionExited, &dragData, [[draggingInfo draggingPasteboard] name]); + _data->_page->dragExited(&dragData, [[draggingInfo draggingPasteboard] name]); _data->_page->resetDragOperation(); } @@ -1345,15 +1545,53 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde return YES; } +// FIXME: This code is more or less copied from Pasteboard::getBestURL. +// It would be nice to be able to share the code somehow. +static void maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, SandboxExtension::Handle& sandboxExtensionHandle) +{ + NSArray *types = [pasteboard types]; + if (![types containsObject:NSFilenamesPboardType]) + return; + + NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType]; + if ([files count] != 1) + return; + + NSString *file = [files objectAtIndex:0]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory]) + return; + + if (isDirectory) + return; + + SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, sandboxExtensionHandle); +} + - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo { IntPoint client([self convertPoint:[draggingInfo draggingLocation] fromView:nil]); IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]); - _data->_page->performDragControllerAction(DragControllerActionPerformDrag, &dragData, [[draggingInfo draggingPasteboard] name]); + + SandboxExtension::Handle sandboxExtensionHandle; + maybeCreateSandboxExtensionFromPasteboard([draggingInfo draggingPasteboard], sandboxExtensionHandle); + + _data->_page->performDrag(&dragData, [[draggingInfo draggingPasteboard] name], sandboxExtensionHandle); + return YES; } +// This code is needed to support drag and drop when the drag types cannot be matched. +// This is the case for elements that do not place content +// in the drag pasteboard automatically when the drag start (i.e. dragging a DIV element). +- (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types +{ + if ([[self superview] mouse:*point inRect:[self frame]]) + return self; + return nil; +} + - (void)_updateWindowVisibility { _data->_page->updateWindowIsVisible(![[self window] isMiniaturized]); @@ -1423,6 +1661,10 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde name:NSWindowDidMoveNotification object:window]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowFrameDidChange:) name:NSWindowDidResizeNotification object:window]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidOrderOffScreen:) + name:@"NSWindowDidOrderOffScreenNotification" object:window]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidOrderOnScreen:) + name:@"_NSWindowDidBecomeVisible" object:window]; } } @@ -1438,6 +1680,8 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidMoveNotification object:window]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:window]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NSWindowDidOrderOffScreenNotification" object:window]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:@"_NSWindowDidBecomeVisible" object:window]; } - (void)viewWillMoveToWindow:(NSWindow *)window @@ -1492,15 +1736,19 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde - (void)_windowDidBecomeKey:(NSNotification *)notification { NSWindow *keyWindow = [notification object]; - if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet]) + if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet]) { + [self _updateSecureInputState]; _data->_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive); + } } - (void)_windowDidResignKey:(NSNotification *)notification { NSWindow *formerKeyWindow = [notification object]; - if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet]) + if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet]) { + [self _updateSecureInputState]; _data->_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive); + } } - (void)_windowDidMiniaturize:(NSNotification *)notification @@ -1518,6 +1766,16 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde [self _updateWindowAndViewFrames]; } +- (void)_windowDidOrderOffScreen:(NSNotification *)notification +{ + _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible); +} + +- (void)_windowDidOrderOnScreen:(NSNotification *)notification +{ + _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible); +} + static void drawPageBackground(CGContextRef context, WebPageProxy* page, const IntRect& rect) { if (!page->drawsBackground()) @@ -1667,6 +1925,7 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I // NSPrintOperation takes ownership of the view. NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:printingView.get()]; [printOperation setCanSpawnSeparateThread:YES]; + [printOperation setJobTitle:toImpl(frameRef)->title()]; printingView->_printOperation = printOperation; return printOperation; } @@ -1706,14 +1965,6 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I [self setNeedsDisplay:YES]; } -- (void)_takeFocus:(BOOL)forward -{ - if (forward) - [[self window] selectKeyViewFollowingView:self]; - else - [[self window] selectKeyViewPrecedingView:self]; -} - - (void)_setCursor:(NSCursor *)cursor { if ([NSCursor currentCursor] == cursor) @@ -1744,27 +1995,34 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I _data->_keyDownEventBeingResent = nullptr; } -- (Vector<KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent +- (BOOL)_interpretKeyEvent:(NSEvent *)event savingCommandsTo:(Vector<WebCore::KeypressCommand>&)commands { - ASSERT(!_data->_isInInterpretKeyEvents); + ASSERT(!_data->_interpretKeyEventsParameters); + ASSERT(commands.isEmpty()); - _data->_isInInterpretKeyEvents = true; - _data->_commandsList.clear(); + if ([event type] == NSFlagsChanged) + return NO; - // Calling interpretKeyEvents will trigger one or more calls to doCommandBySelector and insertText - // that will populate the commandsList vector. - [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + WKViewInterpretKeyEventsParameters parameters; + parameters.eventInterpretationHadSideEffects = false; + parameters.executingSavedKeypressCommands = false; + // We assume that an input method has consumed the event, and only change this assumption if one of the NSTextInput methods is called. + // We assume the IM will *not* consume hotkey sequences. + parameters.consumedByIM = !([event modifierFlags] & NSCommandKeyMask); + parameters.commands = &commands; + _data->_interpretKeyEventsParameters = ¶meters; - _data->_isInInterpretKeyEvents = false; + [self interpretKeyEvents:[NSArray arrayWithObject:event]]; - return _data->_commandsList; -} + _data->_interpretKeyEventsParameters = 0; -- (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<CompositionUnderline>&)lines -{ - start = _data->_selectionStart; - end = _data->_selectionEnd; - lines = _data->_underlines; + // An input method may consume an event and not tell us (e.g. when displaying a candidate window), + // in which case we should not bubble the event up the DOM. + if (parameters.consumedByIM) + return YES; + + // If we have already executed all or some of the commands, the event is "handled". Note that there are additional checks on web process side. + return parameters.eventInterpretationHadSideEffects; } - (NSRect)_convertToDeviceSpace:(NSRect)rect @@ -2010,6 +2268,22 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I _data->_pdfViewController->setZoomFactor(zoomFactor); } +- (void)_findStringInCustomRepresentation:(NSString *)string withFindOptions:(WebKit::FindOptions)options maxMatchCount:(NSUInteger)count +{ + if (!_data->_pdfViewController) + return; + + _data->_pdfViewController->findString(string, options, count); +} + +- (void)_countStringMatchesInCustomRepresentation:(NSString *)string withFindOptions:(WebKit::FindOptions)options maxMatchCount:(NSUInteger)count +{ + if (!_data->_pdfViewController) + return; + + _data->_pdfViewController->countStringMatches(string, options, count); +} + - (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag { // We need to prevent re-entering this call to avoid crashing in AppKit. @@ -2028,6 +2302,32 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I _data->_dragHasStarted = NO; } +- (void)_updateSecureInputState +{ + if (![[self window] isKeyWindow] || ([[self window] firstResponder] != self && !_data->_inBecomeFirstResponder)) { + if (_data->_inSecureInputState) { + DisableSecureEventInput(); + _data->_inSecureInputState = NO; + } + return; + } + // WKView has a single input context for all editable areas (except for plug-ins). + NSTextInputContext *context = [super inputContext]; + bool isInPasswordField = _data->_page->editorState().isInPasswordField; + + if (isInPasswordField) { + if (!_data->_inSecureInputState) + EnableSecureEventInput(); + static NSArray *romanInputSources = [[NSArray alloc] initWithObjects:&NSAllRomanInputSourcesLocaleIdentifier count:1]; + [context setAllowedInputSourceLocales:romanInputSources]; + } else { + if (_data->_inSecureInputState) + DisableSecureEventInput(); + [context setAllowedInputSourceLocales:nil]; + } + _data->_inSecureInputState = isInPasswordField; +} + - (void)_setDrawingAreaSize:(NSSize)size { if (!_data->_page->drawingArea()) @@ -2053,6 +2353,16 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I } #endif +- (bool)_executeSavedCommandBySelector:(SEL)selector +{ + // The sink does two things: 1) Tells us if the responder went unhandled, and + // 2) prevents any NSBeep; we don't ever want to beep here. + RetainPtr<WKResponderChainSink> sink(AdoptNS, [[WKResponderChainSink alloc] initWithResponderChain:self]); + [super doCommandBySelector:selector]; + [sink.get() detach]; + return ![sink.get() didReceiveUnhandledCommand]; +} + @end @implementation WKView (Private) @@ -2101,3 +2411,45 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I @end +@implementation WKResponderChainSink + +- (id)initWithResponderChain:(NSResponder *)chain +{ + self = [super init]; + if (!self) + return nil; + _lastResponderInChain = chain; + while (NSResponder *next = [_lastResponderInChain nextResponder]) + _lastResponderInChain = next; + [_lastResponderInChain setNextResponder:self]; + return self; +} + +- (void)detach +{ + [_lastResponderInChain setNextResponder:nil]; + _lastResponderInChain = nil; +} + +- (bool)didReceiveUnhandledCommand +{ + return _didReceiveUnhandledCommand; +} + +- (void)noResponderFor:(SEL)selector +{ + _didReceiveUnhandledCommand = true; +} + +- (void)doCommandBySelector:(SEL)selector +{ + _didReceiveUnhandledCommand = true; +} + +- (BOOL)tryToPerform:(SEL)action with:(id)object +{ + _didReceiveUnhandledCommand = true; + return YES; +} + +@end diff --git a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h index e4a40f7..82acdcf 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h +++ b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h @@ -24,22 +24,25 @@ */ #import "WKView.h" -#import <WebCore/Editor.h> -#import <WebCore/KeyboardEvent.h> +#import "WebFindOptions.h" +#import <wtf/Forward.h> +#import <wtf/Vector.h> namespace CoreIPC { class DataReference; } +namespace WebCore { + struct KeypressCommand; +} + namespace WebKit { class DrawingAreaProxy; class FindIndicator; class LayerTreeContext; } -#if ENABLE(FULLSCREEN_API) @class WKFullScreenWindowController; -#endif @interface WKView (Internal) - (PassOwnPtr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy; @@ -47,13 +50,12 @@ namespace WebKit { - (void)_processDidCrash; - (void)_pageClosed; - (void)_didRelaunchProcess; -- (void)_takeFocus:(BOOL)direction; - (void)_toolTipChangedFrom:(NSString *)oldToolTip to:(NSString *)newToolTip; - (void)_setCursor:(NSCursor *)cursor; - (void)_setUserInterfaceItemState:(NSString *)commandName enabled:(BOOL)isEnabled state:(int)newState; -- (Vector<WebCore::KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent; -- (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<WebCore::CompositionUnderline>&)lines; +- (BOOL)_interpretKeyEvent:(NSEvent *)theEvent savingCommandsTo:(Vector<WebCore::KeypressCommand>&)commands; - (void)_resendKeyDownEvent:(NSEvent *)event; +- (bool)_executeSavedCommandBySelector:(SEL)selector; - (NSRect)_convertToDeviceSpace:(NSRect)rect; - (NSRect)_convertToUserSpace:(NSRect)rect; - (void)_setFindIndicator:(PassRefPtr<WebKit::FindIndicator>)findIndicator fadeOut:(BOOL)fadeOut; @@ -68,7 +70,10 @@ namespace WebKit { - (void)_didFinishLoadingDataForCustomRepresentationWithSuggestedFilename:(const String&)suggestedFilename dataReference:(const CoreIPC::DataReference&)dataReference; - (double)_customRepresentationZoomFactor; - (void)_setCustomRepresentationZoomFactor:(double)zoomFactor; +- (void)_findStringInCustomRepresentation:(NSString *)string withFindOptions:(WebKit::FindOptions)options maxMatchCount:(NSUInteger)count; +- (void)_countStringMatchesInCustomRepresentation:(NSString *)string withFindOptions:(WebKit::FindOptions)options maxMatchCount:(NSUInteger)count; - (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag; +- (void)_updateSecureInputState; - (void)_setDrawingAreaSize:(NSSize)size; diff --git a/Source/WebKit2/UIProcess/API/qt/ClientImpl.cpp b/Source/WebKit2/UIProcess/API/qt/ClientImpl.cpp index 8197236..b427058 100644 --- a/Source/WebKit2/UIProcess/API/qt/ClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/qt/ClientImpl.cpp @@ -165,6 +165,17 @@ void qt_wk_close(WKPageRef page, const void* clientInfo) emit toQWKPage(clientInfo)->windowCloseRequested(); } +void qt_wk_takeFocus(WKPageRef page, WKFocusDirection direction, const void *clientInfo) +{ + emit toQWKPage(clientInfo)->focusNextPrevChild(direction == kWKFocusDirectionForward); +} + void qt_wk_runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void* clientInfo) { } + +void qt_wk_setStatusText(WKPageRef page, WKStringRef text, const void *clientInfo) +{ + QString qText = WKStringCopyQString(text); + emit toQWKPage(clientInfo)->statusBarMessage(qText); +} diff --git a/Source/WebKit2/UIProcess/API/qt/ClientImpl.h b/Source/WebKit2/UIProcess/API/qt/ClientImpl.h index 5d8c062..7955144 100644 --- a/Source/WebKit2/UIProcess/API/qt/ClientImpl.h +++ b/Source/WebKit2/UIProcess/API/qt/ClientImpl.h @@ -48,7 +48,9 @@ void qt_wk_didBecomeResponsive(WKPageRef, const void* clientInfo); WKPageRef qt_wk_createNewPage(WKPageRef page, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo); void qt_wk_showPage(WKPageRef page, const void *clientInfo); void qt_wk_close(WKPageRef page, const void *clientInfo); +void qt_wk_takeFocus(WKPageRef page, WKFocusDirection direction, const void *clientInfo); void qt_wk_runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void* clientInfo); +void qt_wk_setStatusText(WKPageRef page, WKStringRef text, const void *clientInfo); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/qt/WKView.h b/Source/WebKit2/UIProcess/API/qt/WKView.h index 5bb95e8..57a5458 100644 --- a/Source/WebKit2/UIProcess/API/qt/WKView.h +++ b/Source/WebKit2/UIProcess/API/qt/WKView.h @@ -22,6 +22,7 @@ #include <WebKit2/qgraphicswkview.h> #include <WebKit2/qwkcontext.h> +#include <WebKit2/qwkhistory.h> #include <WebKit2/qwkpage.h> #include <WebKit2/qwkpreferences.h> diff --git a/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp b/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp index 0381d73..d85ade3 100644 --- a/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp @@ -50,6 +50,7 @@ struct QGraphicsWKViewPrivate { QGraphicsWKViewPrivate(QGraphicsWKView* view); WKPageRef pageRef() const { return page->pageRef(); } + void onToolTipChanged(const QString&); void onScaleChanged(); void commitScale(); @@ -84,6 +85,7 @@ QGraphicsWKView::QGraphicsWKView(QWKContext* context, BackingStoreType backingSt connect(d->page, SIGNAL(cursorChanged(const QCursor&)), this, SLOT(updateCursor(const QCursor&))); connect(d->page, SIGNAL(focusNextPrevChild(bool)), this, SLOT(focusNextPrevChildCallback(bool))); connect(d->page, SIGNAL(showContextMenu(QSharedPointer<QMenu>)), this, SLOT(showContextMenu(QSharedPointer<QMenu>))); + connect(d->page, SIGNAL(toolTipChanged(QString)), this, SLOT(onToolTipChanged(QString))); } QGraphicsWKView::~QGraphicsWKView() @@ -424,6 +426,11 @@ void QGraphicsWKViewPrivate::onScaleChanged() #endif } +void QGraphicsWKViewPrivate::onToolTipChanged(const QString& toolTip) +{ + q->setToolTip(toolTip); +} + void QGraphicsWKViewPrivate::commitScale() { #if ENABLE(TILED_BACKING_STORE) diff --git a/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.h b/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.h index 03fc722..e4aecdd 100644 --- a/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.h +++ b/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.h @@ -90,7 +90,8 @@ protected: virtual void focusOutEvent(QFocusEvent*); private: - Q_PRIVATE_SLOT(d, void onScaleChanged()); + Q_PRIVATE_SLOT(d, void onScaleChanged()) + Q_PRIVATE_SLOT(d, void onToolTipChanged(const QString&)) QGraphicsWKViewPrivate* d; friend class QGraphicsWKViewPrivate; diff --git a/Source/WebKit2/UIProcess/API/qt/qwkhistory.h b/Source/WebKit2/UIProcess/API/qt/qwkhistory.h index 81081c9..cf1c842 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwkhistory.h +++ b/Source/WebKit2/UIProcess/API/qt/qwkhistory.h @@ -25,10 +25,10 @@ #ifndef qwkhistory_h #define qwkhistory_h +#include "WebKit2/WKBackForwardListItem.h" #include "qwebkitglobal.h" #include <QObject> #include <QSharedData> -#include "WKBackForwardListItem.h" class QWKHistoryPrivate; class QWKHistoryItemPrivate; @@ -49,7 +49,7 @@ public: QUrl url() const; private: - QWKHistoryItem(WKBackForwardListItemRef item); + QWKHistoryItem(WKBackForwardListItemRef); QExplicitlySharedDataPointer<QWKHistoryItemPrivate> d; diff --git a/Source/WebKit2/UIProcess/API/qt/qwkpage.cpp b/Source/WebKit2/UIProcess/API/qt/qwkpage.cpp index a162918..7eb78da 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwkpage.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwkpage.cpp @@ -34,6 +34,7 @@ #include "FindIndicator.h" #include "LocalizedStrings.h" #include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" #include "NotImplemented.h" #include "TiledDrawingAreaProxy.h" #include "WebContext.h" @@ -125,11 +126,6 @@ void QWKPagePrivate::setViewportArguments(const ViewportArguments& args) emit q->viewportChangeRequested(); } -void QWKPagePrivate::takeFocus(bool direction) -{ - emit q->focusNextPrevChild(direction); -} - PassOwnPtr<DrawingAreaProxy> QWKPagePrivate::createDrawingAreaProxy() { // FIXME: We should avoid this cast by decoupling the view from the page. @@ -206,7 +202,7 @@ void QWKPagePrivate::didChangeContentsSize(const IntSize& newSize) void QWKPagePrivate::toolTipChanged(const String&, const String& newTooltip) { - emit q->statusBarMessage(QString(newTooltip)); + emit q->toolTipChanged(QString(newTooltip)); } void QWKPagePrivate::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo) @@ -217,6 +213,15 @@ void QWKPagePrivate::clearAllEditCommands() { } +bool QWKPagePrivate::canUndoRedo(WebPageProxy::UndoOrRedo) +{ + return false; +} + +void QWKPagePrivate::executeUndoRedo(WebPageProxy::UndoOrRedo) +{ +} + FloatRect QWKPagePrivate::convertToDeviceSpace(const FloatRect& rect) { return rect; @@ -297,32 +302,27 @@ void QWKPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev) return; lastPos = ev->pos(); - WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 0); - page->handleMouseEvent(mouseEvent); + page->handleMouseEvent(NativeWebMouseEvent(ev, 0)); } void QWKPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev) { if (tripleClickTimer.isActive() && (ev->pos() - tripleClick).manhattanLength() < QApplication::startDragDistance()) { - WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 3); - page->handleMouseEvent(mouseEvent); + page->handleMouseEvent(NativeWebMouseEvent(ev, 3)); return; } - WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 1); - page->handleMouseEvent(mouseEvent); + page->handleMouseEvent(NativeWebMouseEvent(ev, 1)); } void QWKPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev) { - WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 0); - page->handleMouseEvent(mouseEvent); + page->handleMouseEvent(NativeWebMouseEvent(ev, 0)); } void QWKPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev) { - WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 2); - page->handleMouseEvent(mouseEvent); + page->handleMouseEvent(NativeWebMouseEvent(ev, 2)); tripleClickTimer.start(QApplication::doubleClickInterval(), q); tripleClick = ev->pos().toPoint(); @@ -458,10 +458,13 @@ QWKPage::QWKPage(QWKContext* context) qt_wk_createNewPage, qt_wk_showPage, qt_wk_close, + qt_wk_takeFocus, + 0, /* focus */ + 0, /* unfocus */ qt_wk_runJavaScriptAlert, 0, /* runJavaScriptConfirm */ 0, /* runJavaScriptPrompt */ - 0, /* setStatusText */ + qt_wk_setStatusText, 0, /* mouseDidMoveOverElement */ 0, /* missingPluginButtonClicked */ 0, /* didNotHandleKeyEvent */ diff --git a/Source/WebKit2/UIProcess/API/qt/qwkpage.h b/Source/WebKit2/UIProcess/API/qt/qwkpage.h index 48fdd9f..5dcfad2 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwkpage.h +++ b/Source/WebKit2/UIProcess/API/qt/qwkpage.h @@ -48,7 +48,7 @@ public: WebActionCount }; - class ViewportAttributes { + class QWEBKIT_EXPORT ViewportAttributes { public: ViewportAttributes(); ViewportAttributes(const QWKPage::ViewportAttributes& other); @@ -122,6 +122,7 @@ public: public: Q_SIGNAL void statusBarMessage(const QString&); + Q_SIGNAL void toolTipChanged(const QString&); Q_SIGNAL void titleChanged(const QString&); Q_SIGNAL void loadStarted(); Q_SIGNAL void loadFinished(bool ok); diff --git a/Source/WebKit2/UIProcess/API/qt/qwkpage_p.h b/Source/WebKit2/UIProcess/API/qt/qwkpage_p.h index ee1fb0e..d2fd26b 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwkpage_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwkpage_p.h @@ -71,11 +71,11 @@ public: virtual void didFindZoomableArea(const WebCore::IntRect&); virtual void setCursor(const WebCore::Cursor&); virtual void setViewportArguments(const WebCore::ViewportArguments&); - virtual void takeFocus(bool direction); - virtual void setFocus(bool focused) { } virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void registerEditCommand(PassRefPtr<WebKit::WebEditCommandProxy>, WebKit::WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); + virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); + virtual void executeUndoRedo(WebPageProxy::UndoOrRedo); virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&); @@ -94,7 +94,8 @@ public: virtual void didChangeScrollbarsForMainFrame() const { } virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects); - + virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount) { } + virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount) { } virtual float userSpaceScaleFactor() const { return 1; } void paint(QPainter* painter, QRect); diff --git a/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp index ad61d33..c93a6df 100644 --- a/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp +++ b/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp @@ -65,7 +65,8 @@ void DownloadProxy::cancel() if (!m_webContext) return; - m_webContext->process()->send(Messages::WebProcess::CancelDownload(m_downloadID), 0); + // FIXME (Multi-WebProcess): Downloads shouldn't be handled in the web process. + m_webContext->sendToAllProcesses(Messages::WebProcess::CancelDownload(m_downloadID)); } void DownloadProxy::invalidate() diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxy.h b/Source/WebKit2/UIProcess/DrawingAreaProxy.h index c72cf03..5ccb2fb 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxy.h +++ b/Source/WebKit2/UIProcess/DrawingAreaProxy.h @@ -83,9 +83,10 @@ public: virtual void sizeDidChange() = 0; - // FIXME: visibilityDidChange() should be pure virtual. + // FIXME: These should be pure virtual. virtual void visibilityDidChange() { } - + virtual void setBackingStoreIsDiscardable(bool) { } + virtual void setPageIsVisible(bool isVisible) = 0; const WebCore::IntSize& size() const { return m_size; } diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp index 0ee42f4..0c5359a 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp +++ b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp @@ -52,6 +52,7 @@ DrawingAreaProxyImpl::DrawingAreaProxyImpl(WebPageProxy* webPageProxy) , m_currentBackingStoreStateID(0) , m_nextBackingStoreStateID(0) , m_isWaitingForDidUpdateBackingStoreState(false) + , m_isBackingStoreDiscardable(true) , m_discardBackingStoreTimer(RunLoop::current(), this, &DrawingAreaProxyImpl::discardBackingStore) { } @@ -135,12 +136,31 @@ void DrawingAreaProxyImpl::visibilityDidChange() // Resume painting. m_webPageProxy->process()->send(Messages::DrawingArea::ResumePainting(), m_webPageProxy->pageID()); + +#if USE(ACCELERATED_COMPOSITING) + // If we don't have a backing store, go ahead and mark the backing store as being changed so + // that when paint we'll actually wait for something to paint and not flash white. + if (!m_backingStore && m_layerTreeContext.isEmpty()) + backingStoreStateDidChange(DoNotRespondImmediately); +#endif } void DrawingAreaProxyImpl::setPageIsVisible(bool) { } +void DrawingAreaProxyImpl::setBackingStoreIsDiscardable(bool isBackingStoreDiscardable) +{ + if (m_isBackingStoreDiscardable == isBackingStoreDiscardable) + return; + + m_isBackingStoreDiscardable = isBackingStoreDiscardable; + if (m_isBackingStoreDiscardable) + discardBackingStoreSoon(); + else + m_discardBackingStoreTimer.stop(); +} + void DrawingAreaProxyImpl::update(uint64_t backingStoreStateID, const UpdateInfo& updateInfo) { ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID); @@ -277,7 +297,7 @@ void DrawingAreaProxyImpl::waitForAndDispatchDidUpdateBackingStoreState() return; if (m_webPageProxy->process()->isLaunching()) return; - + #if USE(ACCELERATED_COMPOSITING) // FIXME: waitForAndDispatchImmediately will always return the oldest DidUpdateBackingStoreState message that // hasn't yet been processed. But it might be better to skip ahead to some other DidUpdateBackingStoreState @@ -311,6 +331,9 @@ void DrawingAreaProxyImpl::exitAcceleratedCompositingMode() void DrawingAreaProxyImpl::discardBackingStoreSoon() { + if (!m_isBackingStoreDiscardable) + return; + // We'll wait this many seconds after the last paint before throwing away our backing store to save memory. // FIXME: It would be smarter to make this delay based on how expensive painting is. See <http://webkit.org/b/55733>. static const double discardBackingStoreDelay = 5; diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h index 11e430c..5762264 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h +++ b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h @@ -54,6 +54,7 @@ private: virtual void sizeDidChange(); virtual void visibilityDidChange(); virtual void setPageIsVisible(bool); + virtual void setBackingStoreIsDiscardable(bool); // CoreIPC message handlers virtual void update(uint64_t backingStoreStateID, const UpdateInfo&); @@ -98,6 +99,7 @@ private: // Used to throttle UpdateBackingStoreState messages so we don't send them faster than the Web process can handle. bool m_isWaitingForDidUpdateBackingStoreState; + bool m_isBackingStoreDiscardable; OwnPtr<BackingStore> m_backingStore; RunLoop::Timer<DrawingAreaProxyImpl> m_discardBackingStoreTimer; diff --git a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp index 04d8a03..f877209 100644 --- a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp +++ b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp @@ -32,8 +32,9 @@ #include <WebCore/FileSystem.h> #include <WebCore/ResourceHandle.h> #include <errno.h> -#include <stdio.h> -#include <unistd.h> +#if OS(LINUX) +#include <sys/prctl.h> +#endif #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> #include <wtf/gobject/GOwnPtr.h> @@ -44,32 +45,46 @@ namespace WebKit { const char* gWebKitWebProcessName = "WebKitWebProcess"; +static void childSetupFunction(gpointer userData) +{ + int socket = GPOINTER_TO_INT(userData); + close(socket); + +#if OS(LINUX) + // Kill child process when parent dies. + prctl(PR_SET_PDEATHSIG, SIGKILL); +#endif +} + void ProcessLauncher::launchProcess() { - pid_t pid = 0; + GPid pid = 0; int sockets[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { - fprintf(stderr, "Creation of socket failed with errno %d.\n", errno); + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) < 0) { + g_printerr("Creation of socket failed: %s.\n", g_strerror(errno)); ASSERT_NOT_REACHED(); return; } - pid = fork(); - if (!pid) { // child process - close(sockets[1]); - String socket = String::format("%d", sockets[0]); - GOwnPtr<gchar> binaryPath(g_build_filename(applicationDirectoryPath().data(), gWebKitWebProcessName, NULL)); - execl(binaryPath.get(), gWebKitWebProcessName, socket.utf8().data(), NULL); - } else if (pid > 0) { // parent process - close(sockets[0]); - m_processIdentifier = pid; - // We've finished launching the process, message back to the main run loop. - RunLoop::main()->scheduleWork(WorkItem::create(this, &ProcessLauncher::didFinishLaunchingProcess, pid, sockets[1])); - } else { - fprintf(stderr, "Unable to fork a new WebProcess with errno: %d.\n", errno); + GOwnPtr<gchar> binaryPath(g_build_filename(applicationDirectoryPath().data(), gWebKitWebProcessName, NULL)); + GOwnPtr<gchar> socket(g_strdup_printf("%d", sockets[0])); + char* argv[3]; + argv[0] = binaryPath.get(); + argv[1] = socket.get(); + argv[2] = 0; + + GOwnPtr<GError> error; + int spawnFlags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD; + if (!g_spawn_async(0, argv, 0, static_cast<GSpawnFlags>(spawnFlags), childSetupFunction, GINT_TO_POINTER(sockets[1]), &pid, &error.outPtr())) { + g_printerr("Unable to fork a new WebProcess: %s.\n", error->message); ASSERT_NOT_REACHED(); } + + close(sockets[0]); + m_processIdentifier = pid; + // We've finished launching the process, message back to the main run loop. + RunLoop::main()->scheduleWork(WorkItem::create(this, &ProcessLauncher::didFinishLaunchingProcess, m_processIdentifier, sockets[1])); } void ProcessLauncher::terminateProcess() diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp index cae5bdf..5f3c99f 100644 --- a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp +++ b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp @@ -83,6 +83,16 @@ void QtWebProcess::setupChildProcess() #endif } +#if OS(SYMBIAN) +// FIXME: Symbian's POSIX layer doesn't have a socketpair(), so +// the following is just to fix the build until a pure Symbian +// IPC implementation lands on trunk +static int socketpair(int, int, int , int[2]) +{ + return -1; +} +#endif + void ProcessLauncher::launchProcess() { QString applicationPath = QLatin1String("%1 %2"); diff --git a/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp index 8981e80..03175b5 100644 --- a/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp +++ b/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp @@ -76,7 +76,9 @@ void ProcessLauncher::launchProcess() // FIXME: It would be nice if we could just create a CommandLine object and output a command line vector from it. Vector<UChar> commandLineVector; + append(commandLineVector, "\""); append(commandLineVector, commandLine); + append(commandLineVector, "\""); append(commandLineVector, " -type webprocess"); append(commandLineVector, " -clientIdentifier "); append(commandLineVector, String::number(reinterpret_cast<uintptr_t>(clientIdentifier))); diff --git a/Source/WebKit2/UIProcess/PageClient.h b/Source/WebKit2/UIProcess/PageClient.h index 83ce502..7582152 100644 --- a/Source/WebKit2/UIProcess/PageClient.h +++ b/Source/WebKit2/UIProcess/PageClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -81,8 +81,6 @@ public: virtual void didRelaunchProcess() = 0; virtual void pageClosed() = 0; - virtual void setFocus(bool focused) = 0; - virtual void takeFocus(bool direction) = 0; virtual void toolTipChanged(const String&, const String&) = 0; #if ENABLE(TILED_BACKING_STORE) @@ -98,14 +96,21 @@ public: virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo) = 0; virtual void clearAllEditCommands() = 0; + virtual bool canUndoRedo(WebPageProxy::UndoOrRedo) = 0; + virtual void executeUndoRedo(WebPageProxy::UndoOrRedo) = 0; #if PLATFORM(MAC) virtual void accessibilityWebProcessTokenReceived(const CoreIPC::DataReference&) = 0; - virtual void interceptKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>& commandName, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines) = 0; + virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>&) = 0; + virtual bool executeSavedCommandBySelector(const String& selector) = 0; virtual void setDragImage(const WebCore::IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) = 0; + virtual void updateSecureInputState() = 0; #endif #if PLATFORM(WIN) virtual void compositionSelectionChanged(bool) = 0; #endif +#if PLATFORM(GTK) + virtual void getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent&, Vector<WTF::String>&) = 0; +#endif virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&) = 0; virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&) = 0; virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&) = 0; @@ -124,12 +129,14 @@ public: #if PLATFORM(WIN) virtual HWND nativeWindow() = 0; + virtual void setGestureReachedScrollingLimit(bool) = 0; #endif #if PLATFORM(MAC) virtual void setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled) = 0; virtual CGContextRef containingWindowGraphicsContext() = 0; virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&) = 0; + virtual void dismissDictionaryLookupPanel() = 0; virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) = 0; virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel) = 0; virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel) = 0; @@ -145,6 +152,8 @@ public: virtual void setCustomRepresentationZoomFactor(double) = 0; virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects) = 0; + virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount) = 0; + virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount) = 0; virtual float userSpaceScaleFactor() const = 0; }; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h index fc49d96..bcef7d6 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h @@ -35,6 +35,8 @@ namespace WebCore { namespace WebKit { class PluginInfoStore { + WTF_MAKE_NONCOPYABLE(PluginInfoStore); + public: PluginInfoStore(); diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp index c0aa8b3..fd81da5 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp @@ -45,14 +45,13 @@ PluginProcessManager::PluginProcessManager() { } -void PluginProcessManager::getPluginProcessConnection(const String& pluginPath, WebProcessProxy* webProcessProxy, CoreIPC::ArgumentEncoder* reply) +void PluginProcessManager::getPluginProcessConnection(PluginInfoStore* pluginInfoStore, const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply) { ASSERT(!pluginPath.isNull()); - PluginInfoStore::Plugin plugin = webProcessProxy->context()->pluginInfoStore()->infoForPluginWithPath(pluginPath); + PluginInfoStore::Plugin plugin = pluginInfoStore->infoForPluginWithPath(pluginPath); PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(plugin); - - pluginProcess->createWebProcessConnection(webProcessProxy, reply); + pluginProcess->getPluginProcessConnection(reply); } void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginProcessProxy) @@ -75,12 +74,28 @@ void PluginProcessManager::clearSiteData(const PluginInfoStore::Plugin& plugin, pluginProcess->clearSiteData(webPluginSiteDataManager, sites, flags, maxAgeInSeconds, callbackID); } -PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(const PluginInfoStore::Plugin& plugin) +void PluginProcessManager::pluginSyncMessageSendTimedOut(const String& pluginPath) +{ + PluginProcessProxy* pluginProcess = pluginProcessWithPath(pluginPath); + if (!pluginProcess) + return; + + pluginProcess->terminate(); +} + +PluginProcessProxy* PluginProcessManager::pluginProcessWithPath(const String& pluginPath) { for (size_t i = 0; i < m_pluginProcesses.size(); ++i) { - if (m_pluginProcesses[i]->pluginInfo().path == plugin.path) + if (m_pluginProcesses[i]->pluginInfo().path == pluginPath) return m_pluginProcesses[i]; } + return 0; +} + +PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(const PluginInfoStore::Plugin& plugin) +{ + if (PluginProcessProxy* pluginProcess = pluginProcessWithPath(plugin.path)) + return pluginProcess; PluginProcessProxy* pluginProcess = PluginProcessProxy::create(this, plugin).leakPtr(); m_pluginProcesses.append(pluginProcess); diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h index 79e5952..eaa7536 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h @@ -29,6 +29,7 @@ #if ENABLE(PLUGIN_PROCESS) #include "PluginInfoStore.h" +#include "WebProcessProxyMessages.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/Vector.h> @@ -39,6 +40,7 @@ namespace CoreIPC { namespace WebKit { +class PluginInfoStore; class PluginProcessProxy; class WebProcessProxy; class WebPluginSiteDataManager; @@ -48,16 +50,19 @@ class PluginProcessManager { public: static PluginProcessManager& shared(); - void getPluginProcessConnection(const String& pluginPath, WebProcessProxy*, CoreIPC::ArgumentEncoder* reply); + void getPluginProcessConnection(PluginInfoStore*, const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>); void removePluginProcessProxy(PluginProcessProxy*); void getSitesWithData(const PluginInfoStore::Plugin&, WebPluginSiteDataManager*, uint64_t callbackID); void clearSiteData(const PluginInfoStore::Plugin&, WebPluginSiteDataManager*, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID); + void pluginSyncMessageSendTimedOut(const String& pluginPath); + private: PluginProcessManager(); PluginProcessProxy* getOrCreatePluginProcess(const PluginInfoStore::Plugin&); + PluginProcessProxy* pluginProcessWithPath(const String& pluginPath); Vector<PluginProcessProxy*> m_pluginProcesses; }; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp index f167747..561c02b 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -28,7 +28,6 @@ #if ENABLE(PLUGIN_PROCESS) -#include "MachPort.h" #include "PluginProcessCreationParameters.h" #include "PluginProcessManager.h" #include "PluginProcessMessages.h" @@ -37,6 +36,10 @@ #include "WebPluginSiteDataManager.h" #include "WebProcessProxy.h" +#if PLATFORM(MAC) +#include "MachPort.h" +#endif + namespace WebKit { PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginInfoStore::Plugin& pluginInfo) @@ -51,6 +54,7 @@ PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManage #if PLATFORM(MAC) , m_modalWindowIsShowing(false) , m_fullscreenWindowIsShowing(false) + , m_preFullscreenAppPresentationOptions(0) #endif { ProcessLauncher::LaunchOptions launchOptions; @@ -69,15 +73,15 @@ PluginProcessProxy::~PluginProcessProxy() // Asks the plug-in process to create a new connection to a web process. The connection identifier will be // encoded in the given argument encoder and sent back to the connection of the given web process. -void PluginProcessProxy::createWebProcessConnection(WebProcessProxy* webProcessProxy, CoreIPC::ArgumentEncoder* reply) +void PluginProcessProxy::getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply) { - m_pendingConnectionReplies.append(make_pair(webProcessProxy, reply)); + m_pendingConnectionReplies.append(reply); if (m_processLauncher->isLaunching()) { m_numPendingConnectionRequests++; return; } - + // Ask the plug-in process to create a connection. Since the plug-in can be waiting for a synchronous reply // we need to make sure that this message is always processed, even when the plug-in is waiting for a synchronus reply. m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply); @@ -116,17 +120,23 @@ void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDa m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0); } +void PluginProcessProxy::terminate() +{ + m_processLauncher->terminateProcess(); +} + void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch() { // The plug-in process must have crashed or exited, send any pending sync replies we might have. while (!m_pendingConnectionReplies.isEmpty()) { - RefPtr<WebProcessProxy> replyWebProcessProxy = m_pendingConnectionReplies.first().first.release(); - CoreIPC::ArgumentEncoder* reply = m_pendingConnectionReplies.first().second; - m_pendingConnectionReplies.removeFirst(); + RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst(); - // FIXME: This is Mac specific. - reply->encode(CoreIPC::MachPort(0, MACH_MSG_TYPE_MOVE_SEND)); - replyWebProcessProxy->connection()->sendSyncReply(reply); +#if PLATFORM(MAC) + reply->send(CoreIPC::MachPort(0, MACH_MSG_TYPE_MOVE_SEND)); +#else + // FIXME: Implement. + ASSERT_NOT_REACHED(); +#endif } while (!m_pendingGetSitesReplies.isEmpty()) @@ -162,6 +172,10 @@ void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC: { } +void PluginProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*) +{ +} + void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier) { ASSERT(!m_connection); @@ -200,19 +214,17 @@ void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connectio m_numPendingConnectionRequests = 0; } +#if PLATFORM(MAC) void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::MachPort& machPort) { ASSERT(!m_pendingConnectionReplies.isEmpty()); // Grab the first pending connection reply. - RefPtr<WebProcessProxy> replyWebProcessProxy = m_pendingConnectionReplies.first().first.release(); - CoreIPC::ArgumentEncoder* reply = m_pendingConnectionReplies.first().second; - m_pendingConnectionReplies.removeFirst(); + RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst(); - // FIXME: This is Mac specific. - reply->encode(CoreIPC::MachPort(machPort.port(), MACH_MSG_TYPE_MOVE_SEND)); - replyWebProcessProxy->connection()->sendSyncReply(reply); + reply->send(CoreIPC::MachPort(machPort.port(), MACH_MSG_TYPE_MOVE_SEND)); } +#endif void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID) { diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h index e285d64..59bfd90 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h @@ -31,6 +31,7 @@ #include "Connection.h" #include "PluginInfoStore.h" #include "ProcessLauncher.h" +#include "WebProcessProxyMessages.h" #include <wtf/Deque.h> #if PLATFORM(MAC) @@ -63,14 +64,17 @@ public: // Asks the plug-in process to create a new connection to a web process. The connection identifier will be // encoded in the given argument encoder and sent back to the connection of the given web process. - void createWebProcessConnection(WebProcessProxy*, CoreIPC::ArgumentEncoder* reply); - + void getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>); + // Asks the plug-in process to get a list of domains for which the plug-in has data stored. void getSitesWithData(WebPluginSiteDataManager*, uint64_t callbackID); // Asks the plug-in process to clear the data for the given sites. void clearSiteData(WebPluginSiteDataManager*, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID); + // Terminates the plug-in process. + void terminate(); + private: PluginProcessProxy(PluginProcessManager*, const PluginInfoStore::Plugin&); @@ -80,13 +84,16 @@ private: virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); virtual void didClose(CoreIPC::Connection*); virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID); + virtual void syncMessageSendTimedOut(CoreIPC::Connection*); // ProcessLauncher::Client virtual void didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier); // Message handlers void didReceivePluginProcessProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); +#if PLATFORM(MAC) void didCreateWebProcessConnection(const CoreIPC::MachPort&); +#endif void didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID); void didClearSiteData(uint64_t callbackID); @@ -120,7 +127,7 @@ private: // The process launcher for the plug-in host process. RefPtr<ProcessLauncher> m_processLauncher; - Deque<std::pair<RefPtr<WebProcessProxy>, CoreIPC::ArgumentEncoder*> > m_pendingConnectionReplies; + Deque<RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> > m_pendingConnectionReplies; Vector<uint64_t> m_pendingGetSitesRequests; HashMap<uint64_t, RefPtr<WebPluginSiteDataManager> > m_pendingGetSitesReplies; @@ -143,6 +150,7 @@ private: RetainPtr<WKPlaceholderModalWindow *> m_placeholderWindow; bool m_modalWindowIsShowing; bool m_fullscreenWindowIsShowing; + unsigned m_preFullscreenAppPresentationOptions; #endif }; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in index 5fcbe71..7caac11 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in @@ -23,8 +23,9 @@ #if ENABLE(PLUGIN_PROCESS) messages -> PluginProcessProxy { - # FIXME: This is platform specific +#if PLATFORM(MAC) DidCreateWebProcessConnection(CoreIPC::MachPort connectionIdentifier) +#endif DidGetSitesWithData(Vector<WTF::String> sites, uint64_t callbackID) DidClearSiteData(uint64_t callbackID) diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp index 5f56d0b..89620a1 100644 --- a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp @@ -167,8 +167,10 @@ void WebPluginSiteDataManager::getSitesWithData(PassRefPtr<ArrayCallback> prpCal Vector<String> pluginPaths; m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths); - m_webContext->ensureWebProcess(); - m_webContext->process()->send(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID), 0); + + // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this, + // so this code should just be removed. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID)); #endif } @@ -226,8 +228,10 @@ void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t fla m_webContext->relaunchProcessIfNecessary(); Vector<String> pluginPaths; m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths); - m_webContext->ensureWebProcess(); - m_webContext->process()->send(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID), 0); + + // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this, + // so this code should just be removed. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID)); #endif } diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm index 8375fd2..c845a49 100644 --- a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm @@ -105,30 +105,37 @@ void PluginProcessProxy::setFullscreenWindowIsShowing(bool fullscreenWindowIsSho void PluginProcessProxy::enterFullscreen() { - [NSMenu setMenuBarVisible:NO]; + // Get the current presentation options. + m_preFullscreenAppPresentationOptions = [NSApp presentationOptions]; + // Figure out which presentation options to use. + unsigned presentationOptions = m_preFullscreenAppPresentationOptions & ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar); + presentationOptions |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; + + [NSApp setPresentationOptions:presentationOptions]; makePluginProcessTheFrontProcess(); } void PluginProcessProxy::exitFullscreen() { - [NSMenu setMenuBarVisible:YES]; - // If the plug-in host is the current application then we should bring ourselves to the front when it exits full-screen mode. - ProcessSerialNumber frontProcessSerialNumber; GetFrontProcess(&frontProcessSerialNumber); - Boolean isSameProcess = 0; + + // The UI process must be the front process in order to change the presentation mode. + makeUIProcessTheFrontProcess(); + [NSApp setPresentationOptions:m_preFullscreenAppPresentationOptions]; ProcessSerialNumber pluginProcessSerialNumber; if (!getPluginProcessSerialNumber(pluginProcessSerialNumber)) return; - SameProcess(&frontProcessSerialNumber, &pluginProcessSerialNumber, &isSameProcess); - if (!isSameProcess) - return; - - makeUIProcessTheFrontProcess(); + // If the plug-in process was not the front process, switch back to the previous front process. + // (Otherwise we'll keep the UI process as the front process). + Boolean isPluginProcessFrontProcess; + SameProcess(&frontProcessSerialNumber, &pluginProcessSerialNumber, &isPluginProcessFrontProcess); + if (!isPluginProcessFrontProcess) + SetFrontProcess(&frontProcessSerialNumber); } void PluginProcessProxy::setModalWindowIsShowing(bool modalWindowIsShowing) diff --git a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp index f695969..f29fa4f 100644 --- a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp +++ b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp @@ -27,6 +27,7 @@ #include "PluginInfoStore.h" #include "NetscapePluginModule.h" +#include <WebCore/FileSystem.h> #include <WebCore/PathWalker.h> #include <shlwapi.h> @@ -339,9 +340,6 @@ static bool isNewWindowsMediaPlayerPlugin(const PluginInfoStore::Plugin& plugin) bool PluginInfoStore::shouldUsePlugin(const Plugin& plugin) { - // FIXME: We should prefer a newer version of a plugin to an older version, rather than loading - // both. <http://webkit.org/b/49075> - if (plugin.info.name == "Citrix ICA Client") { // The Citrix ICA Client plug-in requires a Mozilla-based browser; see <rdar://6418681>. return false; @@ -393,6 +391,17 @@ bool PluginInfoStore::shouldUsePlugin(const Plugin& plugin) return true; } + // FIXME: We should prefer a newer version of a plugin to an older version, rather than loading + // only the first. <http://webkit.org/b/58469> + String pluginFileName = pathGetFileName(plugin.path); + for (size_t i = 0; i < m_plugins.size(); ++i) { + Plugin& loadedPlugin = m_plugins[i]; + + // If a plug-in with the same filename already exists, we don't want to load it. + if (equalIgnoringCase(pluginFileName, pathGetFileName(loadedPlugin.path))) + return false; + } + return true; } diff --git a/Source/WebKit2/UIProcess/TextChecker.h b/Source/WebKit2/UIProcess/TextChecker.h index 7a5d535..69e2837 100644 --- a/Source/WebKit2/UIProcess/TextChecker.h +++ b/Source/WebKit2/UIProcess/TextChecker.h @@ -31,6 +31,7 @@ namespace WebKit { +class WebPageProxy; struct TextCheckerState; class TextChecker { @@ -50,16 +51,27 @@ public: static bool isSmartInsertDeleteEnabled(); static void setSmartInsertDeleteEnabled(bool); + + static bool substitutionsPanelIsShowing(); + static void toggleSubstitutionsPanelIsShowing(); +#elif PLATFORM(WIN) + static void continuousSpellCheckingEnabledStateChanged(bool); + static void grammarCheckingEnabledStateChanged(bool); #endif - static int64_t uniqueSpellDocumentTag(); + static int64_t uniqueSpellDocumentTag(WebPageProxy*); static void closeSpellDocumentWithTag(int64_t); - +#if USE(UNIFIED_TEXT_CHECKING) static Vector<WebCore::TextCheckingResult> checkTextOfParagraph(int64_t spellDocumentTag, const UChar* text, int length, uint64_t checkingTypes); - static void updateSpellingUIWithMisspelledWord(const String& misspelledWord); - static void updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const WebCore::GrammarDetail&); +#endif + static void checkSpellingOfString(int64_t spellDocumentTag, const UChar* text, uint32_t length, int32_t& misspellingLocation, int32_t& misspellingLength); + static void checkGrammarOfString(int64_t spellDocumentTag, const UChar* text, uint32_t length, Vector<WebCore::GrammarDetail>&, int32_t& badGrammarLocation, int32_t& badGrammarLength); + static bool spellingUIIsShowing(); + static void toggleSpellingUIIsShowing(); + static void updateSpellingUIWithMisspelledWord(int64_t spellDocumentTag, const String& misspelledWord); + static void updateSpellingUIWithGrammarString(int64_t spellDocumentTag, const String& badGrammarPhrase, const WebCore::GrammarDetail&); static void getGuessesForWord(int64_t spellDocumentTag, const String& word, const String& context, Vector<String>& guesses); - static void learnWord(const String& word); + static void learnWord(int64_t spellDocumentTag, const String& word); static void ignoreWord(int64_t spellDocumentTag, const String& word); }; diff --git a/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp b/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp index 94b595a..912d05f 100644 --- a/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp +++ b/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp @@ -163,17 +163,19 @@ void VisitedLinkProvider::pendingVisitedLinksTimerFired() if (!m_table.sharedMemory()->createHandle(handle, SharedMemory::ReadOnly)) return; - m_context->process()->send(Messages::WebProcess::SetVisitedLinkTable(handle), 0); + // FIXME (Multi-WebProcess): Encoding a handle will null it out so we need to create a new + // handle for every process. Maybe the ArgumentEncoder should handle this. + m_context->sendToAllProcesses(Messages::WebProcess::SetVisitedLinkTable(handle)); } // We now need to let the web process know that we've added links. if (m_webProcessHasVisitedLinkState && addedVisitedLinks.size() <= 20) { - m_context->process()->send(Messages::WebProcess::VisitedLinkStateChanged(addedVisitedLinks), 0); + m_context->sendToAllProcesses(Messages::WebProcess::VisitedLinkStateChanged(addedVisitedLinks)); return; } // Just recalculate all the visited links. - m_context->process()->send(Messages::WebProcess::AllVisitedLinkStateChanged(), 0); + m_context->sendToAllProcesses(Messages::WebProcess::AllVisitedLinkStateChanged()); m_webProcessHasVisitedLinkState = true; } diff --git a/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp b/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp index 6b24940..5ea62cd 100644 --- a/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp @@ -65,11 +65,12 @@ void WebApplicationCacheManagerProxy::didReceiveMessage(CoreIPC::Connection* con void WebApplicationCacheManagerProxy::getApplicationCacheOrigins(PassRefPtr<ArrayCallback> prpCallback) { RefPtr<ArrayCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebApplicationCacheManager::GetApplicationCacheOrigins(callbackID), 0); + + // FIXME (Multi-WebProcess): The application cache shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebApplicationCacheManager::GetApplicationCacheOrigins(callbackID)); } void WebApplicationCacheManagerProxy::didGetApplicationCacheOrigins(const Vector<SecurityOriginData>& originDatas, uint64_t callbackID) @@ -80,20 +81,19 @@ void WebApplicationCacheManagerProxy::didGetApplicationCacheOrigins(const Vector void WebApplicationCacheManagerProxy::deleteEntriesForOrigin(WebSecurityOrigin* origin) { - m_webContext->relaunchProcessIfNecessary(); - SecurityOriginData securityOriginData; securityOriginData.protocol = origin->protocol(); securityOriginData.host = origin->host(); securityOriginData.port = origin->port(); - m_webContext->process()->send(Messages::WebApplicationCacheManager::DeleteEntriesForOrigin(securityOriginData), 0); + // FIXME (Multi-WebProcess): The application cache shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebApplicationCacheManager::DeleteEntriesForOrigin(securityOriginData)); } void WebApplicationCacheManagerProxy::deleteAllEntries() { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebApplicationCacheManager::DeleteAllEntries(), 0); + // FIXME (Multi-WebProcess): The application cache shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebApplicationCacheManager::DeleteAllEntries()); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebContext.cpp b/Source/WebKit2/UIProcess/WebContext.cpp index 0609d68..c5d4abc 100644 --- a/Source/WebKit2/UIProcess/WebContext.cpp +++ b/Source/WebKit2/UIProcess/WebContext.cpp @@ -54,6 +54,7 @@ #include <WebCore/Language.h> #include <WebCore/LinkHash.h> #include <WebCore/Logging.h> +#include <WebCore/ResourceRequest.h> #include <wtf/CurrentTime.h> #ifndef NDEBUG @@ -111,8 +112,6 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa , m_visitedLinkProvider(this) , m_alwaysUsesComplexTextCodePath(false) , m_cacheModel(CacheModelDocumentViewer) - , m_clearResourceCachesForNewWebProcess(false) - , m_clearApplicationCacheForNewWebProcess(false) , m_memorySamplerEnabled(false) , m_memorySamplerInterval(1400.0) , m_applicationCacheManagerProxy(WebApplicationCacheManagerProxy::create(this)) @@ -128,6 +127,7 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa , m_shouldPaintNativeControls(true) , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyAlways) #endif + , m_processTerminationEnabled(true) { #ifndef NDEBUG WebKit::initializeLogChannelsIfNecessary(); @@ -193,11 +193,8 @@ void WebContext::initializeInjectedBundleClient(const WKContextInjectedBundleCli void WebContext::initializeHistoryClient(const WKContextHistoryClient* client) { m_historyClient.initialize(client); - - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::SetShouldTrackVisitedLinks(m_historyClient.shouldTrackVisitedLinks()), 0); + + sendToAllProcesses(Messages::WebProcess::SetShouldTrackVisitedLinks(m_historyClient.shouldTrackVisitedLinks())); } void WebContext::initializeDownloadClient(const WKContextDownloadClient* client) @@ -212,10 +209,7 @@ void WebContext::languageChanged(void* context) void WebContext::languageChanged() { - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::LanguageChanged(defaultLanguage()), 0); + sendToAllProcesses(Messages::WebProcess::LanguageChanged(defaultLanguage())); } void WebContext::ensureWebProcess() @@ -241,14 +235,9 @@ void WebContext::ensureWebProcess() parameters.applicationCacheDirectory = applicationCacheDirectory(); parameters.databaseDirectory = databaseDirectory(); parameters.localStorageDirectory = localStorageDirectory(); - parameters.clearResourceCaches = m_clearResourceCachesForNewWebProcess; - parameters.clearApplicationCache = m_clearApplicationCacheForNewWebProcess; #if PLATFORM(MAC) parameters.presenterApplicationPid = getpid(); #endif - - m_clearResourceCachesForNewWebProcess = false; - m_clearApplicationCacheForNewWebProcess = false; copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument); copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure); @@ -274,11 +263,21 @@ void WebContext::ensureWebProcess() m_pendingMessagesToPostToInjectedBundle.clear(); } +void WebContext::enableProcessTermination() +{ + m_processTerminationEnabled = true; + if (shouldTerminate(m_process.get())) + m_process->terminate(); +} + bool WebContext::shouldTerminate(WebProcessProxy* process) { // FIXME: Once we support multiple processes per context, this assertion won't hold. ASSERT(process == m_process); + if (!m_processTerminationEnabled) + return false; + if (!m_downloads.isEmpty()) return false; @@ -348,10 +347,11 @@ void WebContext::disconnectProcess(WebProcessProxy* process) m_pluginSiteDataManager->invalidate(); #endif + // This can cause the web context to be destroyed. m_process = 0; } -WebPageProxy* WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pageGroup) +PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pageGroup) { ensureWebProcess(); @@ -361,17 +361,21 @@ WebPageProxy* WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pa return m_process->createWebPage(pageClient, this, pageGroup); } -void WebContext::relaunchProcessIfNecessary() +WebProcessProxy* WebContext::relaunchProcessIfNecessary() { ensureWebProcess(); + + ASSERT(m_process); + return m_process.get(); } -void WebContext::download(WebPageProxy* initiatingPage, const ResourceRequest& request) +DownloadProxy* WebContext::download(WebPageProxy* initiatingPage, const ResourceRequest& request) { - uint64_t downloadID = createDownloadProxy(); + DownloadProxy* download = createDownloadProxy(); uint64_t initiatingPageID = initiatingPage ? initiatingPage->pageID() : 0; - process()->send(Messages::WebProcess::DownloadRequest(downloadID, initiatingPageID, request), 0); + process()->send(Messages::WebProcess::DownloadRequest(download->downloadID(), initiatingPageID, request), 0); + return download; } void WebContext::postMessageToInjectedBundle(const String& messageName, APIObject* messageBody) @@ -463,58 +467,36 @@ void WebContext::setAdditionalPluginsDirectory(const String& directory) void WebContext::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText) { m_alwaysUsesComplexTextCodePath = alwaysUseComplexText; - - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText), 0); + sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText)); } void WebContext::registerURLSchemeAsEmptyDocument(const String& urlScheme) { m_schemesToRegisterAsEmptyDocument.add(urlScheme); - - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme), 0); + sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme)); } void WebContext::registerURLSchemeAsSecure(const String& urlScheme) { m_schemesToRegisterAsSecure.add(urlScheme); - - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme), 0); + sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme)); } void WebContext::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) { m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme); - - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme), 0); + sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme)); } void WebContext::setCacheModel(CacheModel cacheModel) { m_cacheModel = cacheModel; - - if (!hasValidProcess()) - return; - m_process->send(Messages::WebProcess::SetCacheModel(static_cast<uint32_t>(m_cacheModel)), 0); + sendToAllProcesses(Messages::WebProcess::SetCacheModel(static_cast<uint32_t>(m_cacheModel))); } void WebContext::setDefaultRequestTimeoutInterval(double timeoutInterval) { - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval), 0); + sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval)); } void WebContext::addVisitedLink(const String& visitedURL) @@ -561,14 +543,11 @@ void WebContext::didClearPluginSiteData(uint64_t callbackID) } #endif -uint64_t WebContext::createDownloadProxy() +DownloadProxy* WebContext::createDownloadProxy() { RefPtr<DownloadProxy> downloadProxy = DownloadProxy::create(this); - uint64_t downloadID = downloadProxy->downloadID(); - - m_downloads.set(downloadID, downloadProxy.release()); - - return downloadID; + m_downloads.set(downloadProxy->downloadID(), downloadProxy); + return downloadProxy.get(); } void WebContext::downloadFinished(DownloadProxy* downloadProxy) @@ -700,41 +679,9 @@ CoreIPC::SyncReplyMode WebContext::didReceiveSyncMessage(CoreIPC::Connection* co return CoreIPC::AutomaticReply; } -void WebContext::clearResourceCaches(ResourceCachesToClear cachesToClear) -{ - if (hasValidProcess()) { - m_process->send(Messages::WebProcess::ClearResourceCaches(cachesToClear), 0); - return; - } - - if (cachesToClear == InMemoryResourceCachesOnly) - return; - - // FIXME <rdar://problem/8727879>: Setting this flag ensures that the next time a WebProcess is created, this request to - // clear the resource cache will be respected. But if the user quits the application before another WebProcess is created, - // their request will be ignored. - m_clearResourceCachesForNewWebProcess = true; -} - -void WebContext::clearApplicationCache() -{ - if (!hasValidProcess()) { - // FIXME <rdar://problem/8727879>: Setting this flag ensures that the next time a WebProcess is created, this request to - // clear the application cache will be respected. But if the user quits the application before another WebProcess is created, - // their request will be ignored. - m_clearApplicationCacheForNewWebProcess = true; - return; - } - - m_process->send(Messages::WebProcess::ClearApplicationCache(), 0); -} - void WebContext::setEnhancedAccessibility(bool flag) { - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::SetEnhancedAccessibility(flag), 0); + sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag)); } void WebContext::startMemorySampler(const double interval) @@ -748,16 +695,13 @@ void WebContext::startMemorySampler(const double interval) WebMemorySampler::shared()->start(interval); #endif - if (!hasValidProcess()) - return; - // For WebProcess SandboxExtension::Handle sampleLogSandboxHandle; double now = WTF::currentTime(); String sampleLogFilePath = String::format("WebProcess%llu", static_cast<uint64_t>(now)); sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle); - m_process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval), 0); + sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval)); } void WebContext::stopMemorySampler() @@ -769,11 +713,8 @@ void WebContext::stopMemorySampler() #if ENABLE(MEMORY_SAMPLER) WebMemorySampler::shared()->stop(); #endif - - if (!hasValidProcess()) - return; - - m_process->send(Messages::WebProcess::StopMemorySampler(), 0); + + sendToAllProcesses(Messages::WebProcess::StopMemorySampler()); } String WebContext::databaseDirectory() const @@ -806,4 +747,20 @@ String WebContext::localStorageDirectory() const return platformDefaultLocalStorageDirectory(); } +void WebContext::setHTTPPipeliningEnabled(bool enabled) +{ +#if PLATFORM(MAC) + ResourceRequest::setHTTPPipeliningEnabled(enabled); +#endif +} + +bool WebContext::httpPipeliningEnabled() +{ +#if PLATFORM(MAC) + return ResourceRequest::httpPipeliningEnabled(); +#else + return false; +#endif +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebContext.h b/Source/WebKit2/UIProcess/WebContext.h index a9ba22f..676f1aa 100644 --- a/Source/WebKit2/UIProcess/WebContext.h +++ b/Source/WebKit2/UIProcess/WebContext.h @@ -75,20 +75,22 @@ public: ProcessModel processModel() const { return m_processModel; } WebProcessProxy* process() const { return m_process.get(); } - bool hasValidProcess() const { return m_process && m_process->isValid(); } + template<typename U> bool sendToAllProcesses(const U& message); + template<typename U> bool sendToAllProcessesRelaunchingThemIfNecessary(const U& message); + void processDidFinishLaunching(WebProcessProxy*); // Disconnect the process from the context. void disconnectProcess(WebProcessProxy*); - WebPageProxy* createWebPage(PageClient*, WebPageGroup*); + PassRefPtr<WebPageProxy> createWebPage(PageClient*, WebPageGroup*); - void relaunchProcessIfNecessary(); + WebProcessProxy* relaunchProcessIfNecessary(); const String& injectedBundlePath() const { return m_injectedBundlePath; } - void download(WebPageProxy* initiatingPage, const WebCore::ResourceRequest&); + DownloadProxy* download(WebPageProxy* initiatingPage, const WebCore::ResourceRequest&); void setInjectedBundleInitializationUserData(PassRefPtr<APIObject> userData) { m_injectedBundleInitializationUserData = userData; } APIObject* injectedBundleInitializationUserData() const { return m_injectedBundleInitializationUserData.get(); } @@ -120,8 +122,6 @@ public: void setCacheModel(CacheModel); CacheModel cacheModel() const { return m_cacheModel; } - void clearResourceCaches(ResourceCachesToClear); - void clearApplicationCache(); void setDefaultRequestTimeoutInterval(double); @@ -137,7 +137,7 @@ public: void setEnhancedAccessibility(bool); // Downloads. - uint64_t createDownloadProxy(); + DownloadProxy* createDownloadProxy(); WebDownloadClient& downloadClient() { return m_downloadClient; } void downloadFinished(DownloadProxy*); @@ -168,6 +168,13 @@ public: bool shouldTerminate(WebProcessProxy*); + void disableProcessTermination() { m_processTerminationEnabled = false; } + void enableProcessTermination(); + + // Defaults to false. + void setHTTPPipeliningEnabled(bool); + bool httpPipeliningEnabled(); + private: WebContext(ProcessModel, const String& injectedBundlePath); @@ -205,7 +212,7 @@ private: String localStorageDirectory() const; String platformDefaultLocalStorageDirectory() const; - + ProcessModel m_processModel; // FIXME: In the future, this should be one or more WebProcessProxies. @@ -234,9 +241,6 @@ private: WebDownloadClient m_downloadClient; HashMap<uint64_t, RefPtr<DownloadProxy> > m_downloads; - - bool m_clearResourceCachesForNewWebProcess; - bool m_clearApplicationCacheForNewWebProcess; bool m_memorySamplerEnabled; double m_memorySamplerInterval; @@ -263,8 +267,25 @@ private: String m_overrideDatabaseDirectory; String m_overrideIconDatabasePath; String m_overrideLocalStorageDirectory; + + bool m_processTerminationEnabled; }; +template<typename U> inline bool WebContext::sendToAllProcesses(const U& message) +{ + if (!m_process || !m_process->canSendMessage()) + return false; + + return m_process->send(message, 0); +} + +template<typename U> bool WebContext::sendToAllProcessesRelaunchingThemIfNecessary(const U& message) +{ + relaunchProcessIfNecessary(); + + return m_process->send(message, 0); +} + } // namespace WebKit #endif // WebContext_h diff --git a/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp b/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp index a30ab41..e7b4a6a 100644 --- a/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp @@ -73,11 +73,11 @@ void WebCookieManagerProxy::getHostnamesWithCookies(PassRefPtr<ArrayCallback> pr ASSERT(m_webContext); RefPtr<ArrayCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); - uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebCookieManager::GetHostnamesWithCookies(callbackID), 0); + + // FIXME (Multi-WebProcess): Cookies shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::GetHostnamesWithCookies(callbackID)); } void WebCookieManagerProxy::didGetHostnamesWithCookies(const Vector<String>& hostnameList, uint64_t callbackID) @@ -100,30 +100,25 @@ void WebCookieManagerProxy::didGetHostnamesWithCookies(const Vector<String>& hos void WebCookieManagerProxy::deleteCookiesForHostname(const String& hostname) { ASSERT(m_webContext); - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebCookieManager::DeleteCookiesForHostname(hostname), 0); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::DeleteCookiesForHostname(hostname)); } void WebCookieManagerProxy::deleteAllCookies() { ASSERT(m_webContext); - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebCookieManager::DeleteAllCookies(), 0); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::DeleteAllCookies()); } void WebCookieManagerProxy::startObservingCookieChanges() { ASSERT(m_webContext); - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebCookieManager::StartObservingCookieChanges(), 0); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::StartObservingCookieChanges()); } void WebCookieManagerProxy::stopObservingCookieChanges() { ASSERT(m_webContext); - if (!m_webContext->hasValidProcess()) - return; - m_webContext->process()->send(Messages::WebCookieManager::StopObservingCookieChanges(), 0); + m_webContext->sendToAllProcesses(Messages::WebCookieManager::StopObservingCookieChanges()); } void WebCookieManagerProxy::cookiesDidChange() @@ -134,11 +129,11 @@ void WebCookieManagerProxy::cookiesDidChange() void WebCookieManagerProxy::setHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicy policy) { ASSERT(m_webContext); - m_webContext->relaunchProcessIfNecessary(); #if PLATFORM(MAC) persistHTTPCookieAcceptPolicy(policy); #endif - m_webContext->process()->send(Messages::WebCookieManager::SetHTTPCookieAcceptPolicy(policy), 0); + + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::SetHTTPCookieAcceptPolicy(policy)); } void WebCookieManagerProxy::getHTTPCookieAcceptPolicy(PassRefPtr<HTTPCookieAcceptPolicyCallback> prpCallback) @@ -146,11 +141,12 @@ void WebCookieManagerProxy::getHTTPCookieAcceptPolicy(PassRefPtr<HTTPCookieAccep ASSERT(m_webContext); RefPtr<HTTPCookieAcceptPolicyCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); uint64_t callbackID = callback->callbackID(); m_httpCookieAcceptPolicyCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebCookieManager::GetHTTPCookieAcceptPolicy(callbackID), 0); + + // FIXME (Multi-WebProcess): Cookies shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::GetHTTPCookieAcceptPolicy(callbackID)); } void WebCookieManagerProxy::didGetHTTPCookieAcceptPolicy(uint32_t policy, uint64_t callbackID) diff --git a/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp b/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp index 67323cd..26c518f 100644 --- a/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp @@ -116,12 +116,12 @@ void WebDatabaseManagerProxy::initializeClient(const WKDatabaseManagerClient* cl void WebDatabaseManagerProxy::getDatabasesByOrigin(PassRefPtr<ArrayCallback> prpCallback) { RefPtr<ArrayCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebDatabaseManager::GetDatabasesByOrigin(callbackID), 0); -} + // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::GetDatabasesByOrigin(callbackID)); +} void WebDatabaseManagerProxy::didGetDatabasesByOrigin(const Vector<OriginAndDatabases>& originAndDatabasesVector, uint64_t callbackID) { @@ -169,10 +169,11 @@ void WebDatabaseManagerProxy::didGetDatabasesByOrigin(const Vector<OriginAndData void WebDatabaseManagerProxy::getDatabaseOrigins(PassRefPtr<ArrayCallback> prpCallback) { RefPtr<ArrayCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebDatabaseManager::GetDatabaseOrigins(callbackID), 0); + + // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::GetDatabaseOrigins(callbackID)); } void WebDatabaseManagerProxy::didGetDatabaseOrigins(const Vector<String>& originIdentifiers, uint64_t callbackID) @@ -194,26 +195,26 @@ void WebDatabaseManagerProxy::didGetDatabaseOrigins(const Vector<String>& origin void WebDatabaseManagerProxy::deleteDatabaseWithNameForOrigin(const String& databaseIdentifier, WebSecurityOrigin* origin) { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebDatabaseManager::DeleteDatabaseWithNameForOrigin(databaseIdentifier, origin->databaseIdentifier()), 0); + // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::DeleteDatabaseWithNameForOrigin(databaseIdentifier, origin->databaseIdentifier())); } void WebDatabaseManagerProxy::deleteDatabasesForOrigin(WebSecurityOrigin* origin) { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebDatabaseManager::DeleteDatabasesForOrigin(origin->databaseIdentifier()), 0); + // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::DeleteDatabasesForOrigin(origin->databaseIdentifier())); } void WebDatabaseManagerProxy::deleteAllDatabases() { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebDatabaseManager::DeleteAllDatabases(), 0); + // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::DeleteAllDatabases()); } void WebDatabaseManagerProxy::setQuotaForOrigin(WebSecurityOrigin* origin, uint64_t quota) { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebDatabaseManager::SetQuotaForOrigin(origin->databaseIdentifier(), quota), 0); + // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::SetQuotaForOrigin(origin->databaseIdentifier(), quota)); } void WebDatabaseManagerProxy::didModifyOrigin(const String& originIdentifier) diff --git a/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp b/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp index b9599f3..25ffe23 100644 --- a/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp +++ b/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp @@ -29,6 +29,8 @@ #include "WebPageMessages.h" #include "WebPageProxy.h" #include "WebProcessProxy.h" +#include <WebCore/LocalizedStrings.h> +#include <wtf/text/WTFString.h> using namespace WebCore; @@ -53,7 +55,7 @@ void WebEditCommandProxy::unapply() if (!m_page || !m_page->isValid()) return; - m_page->process()->send(Messages::WebPage::UnapplyEditCommand(m_commandID), m_page->pageID()); + m_page->process()->send(Messages::WebPage::UnapplyEditCommand(m_commandID), m_page->pageID(), CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply); m_page->registerEditCommand(this, WebPageProxy::Redo); } @@ -62,8 +64,89 @@ void WebEditCommandProxy::reapply() if (!m_page || !m_page->isValid()) return; - m_page->process()->send(Messages::WebPage::ReapplyEditCommand(m_commandID), m_page->pageID()); + m_page->process()->send(Messages::WebPage::ReapplyEditCommand(m_commandID), m_page->pageID(), CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply); m_page->registerEditCommand(this, WebPageProxy::Undo); } +String WebEditCommandProxy::nameForEditAction(EditAction editAction) +{ + switch (editAction) { + case EditActionUnspecified: + return String(); + case EditActionSetColor: + return WEB_UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name"); + case EditActionSetBackgroundColor: + return WEB_UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name"); + case EditActionTurnOffKerning: + return WEB_UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name"); + case EditActionTightenKerning: + return WEB_UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name"); + case EditActionLoosenKerning: + return WEB_UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name"); + case EditActionUseStandardKerning: + return WEB_UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name"); + case EditActionTurnOffLigatures: + return WEB_UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name"); + case EditActionUseStandardLigatures: + return WEB_UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name"); + case EditActionUseAllLigatures: + return WEB_UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name"); + case EditActionRaiseBaseline: + return WEB_UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name"); + case EditActionLowerBaseline: + return WEB_UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name"); + case EditActionSetTraditionalCharacterShape: + return WEB_UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name"); + case EditActionSetFont: + return WEB_UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name"); + case EditActionChangeAttributes: + return WEB_UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name"); + case EditActionAlignLeft: + return WEB_UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name"); + case EditActionAlignRight: + return WEB_UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name"); + case EditActionCenter: + return WEB_UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name"); + case EditActionJustify: + return WEB_UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name"); + case EditActionSetWritingDirection: + return WEB_UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name"); + case EditActionSubscript: + return WEB_UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name"); + case EditActionSuperscript: + return WEB_UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name"); + case EditActionUnderline: + return WEB_UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name"); + case EditActionOutline: + return WEB_UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name"); + case EditActionUnscript: + return WEB_UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name"); + case EditActionDrag: + return WEB_UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name"); + case EditActionCut: + return WEB_UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name"); + case EditActionPaste: + return WEB_UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name"); + case EditActionPasteFont: + return WEB_UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name"); + case EditActionPasteRuler: + return WEB_UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name"); + case EditActionTyping: + return WEB_UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name"); + case EditActionCreateLink: + return WEB_UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name"); + case EditActionUnlink: + return WEB_UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name"); + case EditActionInsertList: + return WEB_UI_STRING_KEY("Insert List", "Insert List (Undo action name)", "Undo action name"); + case EditActionFormatBlock: + return WEB_UI_STRING_KEY("Formatting", "Format Block (Undo action name)", "Undo action name"); + case EditActionIndent: + return WEB_UI_STRING_KEY("Indent", "Indent (Undo action name)", "Undo action name"); + case EditActionOutdent: + return WEB_UI_STRING_KEY("Outdent", "Outdent (Undo action name)", "Undo action name"); + } + return String(); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebEditCommandProxy.h b/Source/WebKit2/UIProcess/WebEditCommandProxy.h index 4c08877..67d1430 100644 --- a/Source/WebKit2/UIProcess/WebEditCommandProxy.h +++ b/Source/WebKit2/UIProcess/WebEditCommandProxy.h @@ -28,6 +28,7 @@ #include "APIObject.h" #include <WebCore/EditAction.h> +#include <wtf/Forward.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -51,6 +52,8 @@ public: void unapply(); void reapply(); + static String nameForEditAction(WebCore::EditAction); + private: WebEditCommandProxy(uint64_t commandID, WebCore::EditAction, WebPageProxy*); diff --git a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp index 91daf10..f25bb41 100644 --- a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp @@ -31,7 +31,6 @@ #include "WebContext.h" #include "WebFullScreenManagerMessages.h" #include "WebFullScreenManagerProxyMessages.h" -#include "WebProcess.h" namespace WebKit { diff --git a/Source/WebKit2/UIProcess/WebGeolocationManagerProxy.cpp b/Source/WebKit2/UIProcess/WebGeolocationManagerProxy.cpp index eae4935..14ab88a 100644 --- a/Source/WebKit2/UIProcess/WebGeolocationManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebGeolocationManagerProxy.cpp @@ -61,8 +61,7 @@ void WebGeolocationManagerProxy::providerDidChangePosition(WebGeolocationPositio if (!m_context) return; - // FIXME: Should this check for a valid process? - m_context->process()->send(Messages::WebGeolocationManager::DidChangePosition(position->data()), 0); + m_context->sendToAllProcesses(Messages::WebGeolocationManager::DidChangePosition(position->data())); } void WebGeolocationManagerProxy::providerDidFailToDeterminePosition() @@ -70,8 +69,7 @@ void WebGeolocationManagerProxy::providerDidFailToDeterminePosition() if (!m_context) return; - // FIXME: Should this check for a valid process? - m_context->process()->send(Messages::WebGeolocationManager::DidFailToDeterminePosition(), 0); + m_context->sendToAllProcesses(Messages::WebGeolocationManager::DidFailToDeterminePosition()); } void WebGeolocationManagerProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) diff --git a/Source/WebKit2/UIProcess/WebIconDatabase.cpp b/Source/WebKit2/UIProcess/WebIconDatabase.cpp index c397a1d..aecc34d 100644 --- a/Source/WebKit2/UIProcess/WebIconDatabase.cpp +++ b/Source/WebKit2/UIProcess/WebIconDatabase.cpp @@ -100,14 +100,12 @@ void WebIconDatabase::enableDatabaseCleanup() void WebIconDatabase::retainIconForPageURL(const String& pageURL) { - LOG(IconDatabase, "WK2 UIProcess retaining icon for page URL %s", pageURL.ascii().data()); if (m_iconDatabaseImpl) m_iconDatabaseImpl->retainIconForPageURL(pageURL); } void WebIconDatabase::releaseIconForPageURL(const String& pageURL) { - LOG(IconDatabase, "WK2 UIProcess releasing icon for page URL %s", pageURL.ascii().data()); if (m_iconDatabaseImpl) m_iconDatabaseImpl->releaseIconForPageURL(pageURL); } @@ -157,7 +155,8 @@ void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t return; if (!m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || iconURL.isEmpty()) { - m_webContext->process()->send(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(IconLoadNo), callbackID), 0); + // FIXME (Multi-WebProcess): We need to know which connection to send this message to. + m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(IconLoadNo), callbackID)); return; } @@ -170,23 +169,40 @@ void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t m_pendingLoadDecisionURLMap.set(callbackID, iconURL); return; } - - m_webContext->process()->send(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision((int)decision, callbackID), 0); + + // FIXME (Multi-WebProcess): We need to know which connection to send this message to. + m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision((int)decision, callbackID)); } Image* WebIconDatabase::imageForPageURL(const String& pageURL) { - if (!m_webContext) - return 0; - - if (!m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || pageURL.isEmpty()) - return 0; + if (!m_webContext || !m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || pageURL.isEmpty()) + return 0; // The WebCore IconDatabase ignores the passed in size parameter. // If that changes we'll need to rethink how this API is exposed. return m_iconDatabaseImpl->synchronousIconForPageURL(pageURL, WebCore::IntSize(32, 32)); } +void WebIconDatabase::removeAllIcons() +{ + m_iconDatabaseImpl->removeAllIcons(); +} + +void WebIconDatabase::checkIntegrityBeforeOpening() +{ + IconDatabase::checkIntegrityBeforeOpening(); +} + +void WebIconDatabase::close() +{ + m_iconDatabaseImpl->close(); +} + +void WebIconDatabase::initializeIconDatabaseClient(const WKIconDatabaseClient* client) +{ + m_iconDatabaseClient.initialize(client); +} // WebCore::IconDatabaseClient bool WebIconDatabase::performImport() @@ -195,24 +211,24 @@ bool WebIconDatabase::performImport() return true; } -void WebIconDatabase::didImportIconURLForPageURL(const String&) +void WebIconDatabase::didImportIconURLForPageURL(const String& pageURL) { - // Send a WK2 client notification out here. + didChangeIconForPageURL(pageURL); } -void WebIconDatabase::didImportIconDataForPageURL(const String&) +void WebIconDatabase::didImportIconDataForPageURL(const String& pageURL) { - // Send a WK2 client notification out here. + didChangeIconForPageURL(pageURL); } -void WebIconDatabase::didChangeIconForPageURL(const String&) +void WebIconDatabase::didChangeIconForPageURL(const String& pageURL) { - // Send a WK2 client notification out here. + m_iconDatabaseClient.didChangeIconForPageURL(this, WebURL::create(pageURL).get()); } void WebIconDatabase::didRemoveAllIcons() { - // Send a WK2 client notification out here. + m_iconDatabaseClient.didRemoveAllIcons(this); } void WebIconDatabase::didFinishURLImport() @@ -234,7 +250,8 @@ void WebIconDatabase::didFinishURLImport() // Decisions should never be unknown after the inital import is complete ASSERT(decision != IconLoadUnknown); - m_webContext->process()->send(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(decision), i->first), 0); + // FIXME (Multi-WebProcess): We need to know which connection to send this message to. + m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(decision), i->first)); } m_pendingLoadDecisionURLMap.clear(); diff --git a/Source/WebKit2/UIProcess/WebIconDatabase.h b/Source/WebKit2/UIProcess/WebIconDatabase.h index 802f2aa..91372d6 100644 --- a/Source/WebKit2/UIProcess/WebIconDatabase.h +++ b/Source/WebKit2/UIProcess/WebIconDatabase.h @@ -29,6 +29,7 @@ #include "APIObject.h" #include "Connection.h" +#include "WebIconDatabaseClient.h" #include <WebCore/IconDatabaseClient.h> #include <wtf/Forward.h> #include <wtf/PassRefPtr.h> @@ -77,6 +78,12 @@ public: WebCore::Image* imageForPageURL(const String&); + void removeAllIcons(); + void checkIntegrityBeforeOpening(); + void close(); + + void initializeIconDatabaseClient(const WKIconDatabaseClient*); + // WebCore::IconDatabaseClient virtual bool performImport(); virtual void didImportIconURLForPageURL(const String&); @@ -103,6 +110,7 @@ private: bool m_databaseCleanupDisabled; HashMap<uint64_t, String> m_pendingLoadDecisionURLMap; + WebIconDatabaseClient m_iconDatabaseClient; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebIconDatabaseClient.cpp b/Source/WebKit2/UIProcess/WebIconDatabaseClient.cpp new file mode 100644 index 0000000..e0de366 --- /dev/null +++ b/Source/WebKit2/UIProcess/WebIconDatabaseClient.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebIconDatabaseClient.h" + +#include "WKAPICast.h" +#include "WKSharedAPICast.h" + +namespace WebKit { + +void WebIconDatabaseClient::didChangeIconForPageURL(WebIconDatabase* iconDatabase, WebURL* url) +{ + if (!m_client.didChangeIconForPageURL) + return; + + m_client.didChangeIconForPageURL(toAPI(iconDatabase), toAPI(url), m_client.clientInfo); +} + +void WebIconDatabaseClient::didRemoveAllIcons(WebIconDatabase* iconDatabase) +{ + if (!m_client.didRemoveAllIcons) + return; + + m_client.didRemoveAllIcons(toAPI(iconDatabase), m_client.clientInfo); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebIconDatabaseClient.h b/Source/WebKit2/UIProcess/WebIconDatabaseClient.h new file mode 100644 index 0000000..2311493 --- /dev/null +++ b/Source/WebKit2/UIProcess/WebIconDatabaseClient.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebIconDatabaseClient_h +#define WebIconDatabaseClient_h + +#include "APIClient.h" +#include "WKIconDatabase.h" + +namespace WebKit { + +class APIObject; +class WebIconDatabase; +class WebURL; + +class WebIconDatabaseClient : public APIClient<WKIconDatabaseClient> { +public: + void didChangeIconForPageURL(WebIconDatabase*, WebURL*); + void didRemoveAllIcons(WebIconDatabase*); +}; + +} // namespace WebKit + +#endif // WebIconDatabaseClient_h diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp index b971315..694e76a 100644 --- a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp +++ b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp @@ -46,7 +46,7 @@ namespace WebKit { WebPageGroup* WebInspectorProxy::inspectorPageGroup() { - static WebPageGroup* pageGroup = WebPageGroup::create("__WebInspectorPageGroup__", false).leakRef(); + static WebPageGroup* pageGroup = WebPageGroup::create("__WebInspectorPageGroup__", false, false).leakRef(); return pageGroup; } diff --git a/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp b/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp index 1de1532..93b6fb9 100644 --- a/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp @@ -65,11 +65,11 @@ void WebKeyValueStorageManagerProxy::didReceiveMessage(CoreIPC::Connection* conn void WebKeyValueStorageManagerProxy::getKeyValueStorageOrigins(PassRefPtr<ArrayCallback> prpCallback) { RefPtr<ArrayCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); - uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebKeyValueStorageManager::GetKeyValueStorageOrigins(callbackID), 0); + + // FIXME (Multi-WebProcess): Should key-value storage be handled in the web process? + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebKeyValueStorageManager::GetKeyValueStorageOrigins(callbackID)); } void WebKeyValueStorageManagerProxy::didGetKeyValueStorageOrigins(const Vector<SecurityOriginData>& originDatas, uint64_t callbackID) @@ -80,20 +80,19 @@ void WebKeyValueStorageManagerProxy::didGetKeyValueStorageOrigins(const Vector<S void WebKeyValueStorageManagerProxy::deleteEntriesForOrigin(WebSecurityOrigin* origin) { - m_webContext->relaunchProcessIfNecessary(); - SecurityOriginData securityOriginData; securityOriginData.protocol = origin->protocol(); securityOriginData.host = origin->host(); securityOriginData.port = origin->port(); - m_webContext->process()->send(Messages::WebKeyValueStorageManager::DeleteEntriesForOrigin(securityOriginData), 0); + // FIXME (Multi-WebProcess): Should key-value storage be handled in the web process? + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebKeyValueStorageManager::DeleteEntriesForOrigin(securityOriginData)); } void WebKeyValueStorageManagerProxy::deleteAllEntries() { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebKeyValueStorageManager::DeleteAllEntries(), 0); + // FIXME (Multi-WebProcess): Should key-value storage be handled in the web process? + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebKeyValueStorageManager::DeleteAllEntries()); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp b/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp index c8a7f51..3b034d8 100644 --- a/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp @@ -64,11 +64,12 @@ void WebMediaCacheManagerProxy::didReceiveMessage(CoreIPC::Connection* connectio void WebMediaCacheManagerProxy::getHostnamesWithMediaCache(PassRefPtr<ArrayCallback> prpCallback) { RefPtr<ArrayCallback> callback = prpCallback; - m_webContext->relaunchProcessIfNecessary(); - uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebMediaCacheManager::GetHostnamesWithMediaCache(callbackID), 0); + + // FIXME (Multi-WebProcess): When we're sending this to multiple processes, we need to aggregate the + // callback data when it comes back. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebMediaCacheManager::GetHostnamesWithMediaCache(callbackID)); } void WebMediaCacheManagerProxy::didGetHostnamesWithMediaCache(const Vector<String>& hostnameList, uint64_t callbackID) @@ -90,14 +91,12 @@ void WebMediaCacheManagerProxy::didGetHostnamesWithMediaCache(const Vector<Strin void WebMediaCacheManagerProxy::clearCacheForHostname(const String& hostname) { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebMediaCacheManager::ClearCacheForHostname(hostname), 0); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebMediaCacheManager::ClearCacheForHostname(hostname)); } void WebMediaCacheManagerProxy::clearCacheForAllHostnames() { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebMediaCacheManager::ClearCacheForAllHostnames(), 0); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebMediaCacheManager::ClearCacheForAllHostnames()); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebPageGroup.cpp b/Source/WebKit2/UIProcess/WebPageGroup.cpp index f64dd2c..72588d4 100644 --- a/Source/WebKit2/UIProcess/WebPageGroup.cpp +++ b/Source/WebKit2/UIProcess/WebPageGroup.cpp @@ -47,9 +47,9 @@ static WebPageGroupMap& webPageGroupMap() return map; } -PassRefPtr<WebPageGroup> WebPageGroup::create(const String& identifier, bool visibleToInjectedBundle) +PassRefPtr<WebPageGroup> WebPageGroup::create(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient) { - RefPtr<WebPageGroup> pageGroup = adoptRef(new WebPageGroup(identifier, visibleToInjectedBundle)); + RefPtr<WebPageGroup> pageGroup = adoptRef(new WebPageGroup(identifier, visibleToInjectedBundle, visibleToHistoryClient)); webPageGroupMap().set(pageGroup->pageGroupID(), pageGroup.get()); @@ -61,25 +61,23 @@ WebPageGroup* WebPageGroup::get(uint64_t pageGroupID) return webPageGroupMap().get(pageGroupID); } -WebPageGroup::WebPageGroup(const String& identifier, bool visibleToInjectedBundle) +WebPageGroup::WebPageGroup(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient) { m_data.pageGroupID = generatePageGroupID(); - if (!identifier.isNull()) { + if (!identifier.isNull()) m_data.identifer = identifier; - m_preferences = WebPreferences::create(identifier); - } else { + else m_data.identifer = m_data.identifer = makeString("__uniquePageGroupID-", String::number(m_data.pageGroupID)); - m_preferences = WebPreferences::create(); - } - m_preferences->addPageGroup(this); - m_data.visibleToInjectedBundle = visibleToInjectedBundle; + m_data.visibleToInjectedBundle = visibleToInjectedBundle; + m_data.visibleToHistoryClient = visibleToHistoryClient; } WebPageGroup::~WebPageGroup() { - m_preferences->removePageGroup(this); + if (m_preferences) + m_preferences->removePageGroup(this); webPageGroupMap().remove(pageGroupID()); } @@ -98,15 +96,27 @@ void WebPageGroup::setPreferences(WebPreferences* preferences) if (preferences == m_preferences) return; - m_preferences->removePageGroup(this); - m_preferences = preferences; - m_preferences->addPageGroup(this); + if (!m_preferences) { + m_preferences = preferences; + m_preferences->addPageGroup(this); + } else { + m_preferences->removePageGroup(this); + m_preferences = preferences; + m_preferences->addPageGroup(this); - preferencesDidChange(); + preferencesDidChange(); + } } WebPreferences* WebPageGroup::preferences() const { + if (!m_preferences) { + if (!m_data.identifer.isNull()) + m_preferences = WebPreferences::create(m_data.identifer); + else + m_preferences = WebPreferences::create(); + m_preferences->addPageGroup(const_cast<WebPageGroup*>(this)); + } return m_preferences.get(); } diff --git a/Source/WebKit2/UIProcess/WebPageGroup.h b/Source/WebKit2/UIProcess/WebPageGroup.h index 7859dfc..ccc14bd 100644 --- a/Source/WebKit2/UIProcess/WebPageGroup.h +++ b/Source/WebKit2/UIProcess/WebPageGroup.h @@ -40,7 +40,7 @@ class WebPageGroup : public APIObject { public: static const Type APIType = TypePageGroup; - static PassRefPtr<WebPageGroup> create(const String& identifier = String(), bool visibleToInjectedBundle = true); + static PassRefPtr<WebPageGroup> create(const String& identifier = String(), bool visibleToInjectedBundle = true, bool visibleToHistoryClient = true); static WebPageGroup* get(uint64_t pageGroupID); virtual ~WebPageGroup(); @@ -58,12 +58,12 @@ public: void preferencesDidChange(); private: - WebPageGroup(const String& identifier, bool visibleToInjectedBundle); + WebPageGroup(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient); virtual Type type() const { return APIType; } WebPageGroupData m_data; - RefPtr<WebPreferences> m_preferences; + mutable RefPtr<WebPreferences> m_preferences; HashSet<WebPageProxy*> m_pages; }; diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index ce3af46..aabb304 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -29,10 +29,12 @@ #include "AuthenticationChallengeProxy.h" #include "AuthenticationDecisionListener.h" #include "DataReference.h" +#include "DownloadProxy.h" #include "DrawingAreaProxy.h" #include "FindIndicator.h" #include "MessageID.h" #include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" #include "PageClient.h" #include "PrintInfo.h" #include "SessionState.h" @@ -69,6 +71,7 @@ #include "WebURLRequest.h" #include <WebCore/DragData.h> #include <WebCore/FloatRect.h> +#include <WebCore/FocusDirection.h> #include <WebCore/MIMETypeRegistry.h> #include <WebCore/WindowFeatures.h> #include <stdio.h> @@ -100,14 +103,14 @@ WKPageDebugPaintFlags WebPageProxy::s_debugPaintFlags = 0; static WTF::RefCountedLeakCounter webPageProxyCounter("WebPageProxy"); #endif -PassRefPtr<WebPageProxy> WebPageProxy::create(PageClient* pageClient, WebContext* context, WebPageGroup* pageGroup, uint64_t pageID) +PassRefPtr<WebPageProxy> WebPageProxy::create(PageClient* pageClient, PassRefPtr<WebProcessProxy> process, WebPageGroup* pageGroup, uint64_t pageID) { - return adoptRef(new WebPageProxy(pageClient, context, pageGroup, pageID)); + return adoptRef(new WebPageProxy(pageClient, process, pageGroup, pageID)); } -WebPageProxy::WebPageProxy(PageClient* pageClient, WebContext* context, WebPageGroup* pageGroup, uint64_t pageID) +WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> process, WebPageGroup* pageGroup, uint64_t pageID) : m_pageClient(pageClient) - , m_context(context) + , m_process(process) , m_pageGroup(pageGroup) , m_mainFrame(0) , m_userAgent(standardUserAgent()) @@ -162,6 +165,9 @@ WebPageProxy::WebPageProxy(PageClient* pageClient, WebContext* context, WebPageG WebPageProxy::~WebPageProxy() { + if (!m_isClosed) + close(); + WebContext::statistics().wkPageCount--; if (m_hasSpellDocumentTag) @@ -176,7 +182,7 @@ WebPageProxy::~WebPageProxy() WebProcessProxy* WebPageProxy::process() const { - return m_context->process(); + return m_process.get(); } bool WebPageProxy::isValid() @@ -239,9 +245,11 @@ void WebPageProxy::initializeContextMenuClient(const WKPageContextMenuClient* cl void WebPageProxy::reattachToWebProcess() { + ASSERT(!isValid()); + m_isValid = true; - context()->relaunchProcessIfNecessary(); + m_process = m_process->context()->relaunchProcessIfNecessary(); process()->addExistingWebPage(this, m_pageID); initializeWebPage(); @@ -524,7 +532,7 @@ bool WebPageProxy::canShowMIMEType(const String& mimeType) const return !MIMETypeRegistry::isUnsupportedTextMIMEType(mimeType); String newMimeType = mimeType; - PluginInfoStore::Plugin plugin = context()->pluginInfoStore()->findPlugin(newMimeType, KURL()); + PluginInfoStore::Plugin plugin = m_process->context()->pluginInfoStore()->findPlugin(newMimeType, KURL()); if (!plugin.path.isNull()) return true; @@ -609,6 +617,9 @@ void WebPageProxy::viewStateDidChange(ViewStateFlags flags) process()->send(Messages::WebPage::SetIsInWindow(isInWindow), m_pageID); } } + + if (flags & (ViewWindowIsActive | ViewIsVisible)) + m_drawingArea->setBackingStoreIsDiscardable(!m_pageClient->isViewWindowActive() || !isViewVisible()); } IntSize WebPageProxy::viewSize() const @@ -664,6 +675,28 @@ String WebPageProxy::getSelectedText() process()->sendSync(Messages::WebPage::GetSelectedText(), Messages::WebPage::GetSelectedText::Reply(text), m_pageID); return text; } + +bool WebPageProxy::gestureWillBegin(const IntPoint& point) +{ + bool canBeginPanning = false; + process()->sendSync(Messages::WebPage::GestureWillBegin(point), Messages::WebPage::GestureWillBegin::Reply(canBeginPanning), m_pageID); + return canBeginPanning; +} + +void WebPageProxy::gestureDidScroll(const IntSize& size) +{ + process()->send(Messages::WebPage::GestureDidScroll(size), m_pageID); +} + +void WebPageProxy::gestureDidEnd() +{ + process()->send(Messages::WebPage::GestureDidEnd(), m_pageID); +} + +void WebPageProxy::setGestureReachedScrollingLimit(bool limitReached) +{ + m_pageClient->setGestureReachedScrollingLimit(limitReached); +} #endif #if ENABLE(TILED_BACKING_STORE) @@ -676,7 +709,30 @@ void WebPageProxy::setActualVisibleContentRect(const IntRect& rect) } #endif -void WebPageProxy::performDragControllerAction(DragControllerAction action, WebCore::DragData* dragData, const String& dragStorageName) +void WebPageProxy::dragEntered(WebCore::DragData* dragData, const String& dragStorageName) +{ + SandboxExtension::Handle sandboxExtensionHandle; + performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle); +} + +void WebPageProxy::dragUpdated(WebCore::DragData* dragData, const String& dragStorageName) +{ + SandboxExtension::Handle sandboxExtensionHandle; + performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle); +} + +void WebPageProxy::dragExited(WebCore::DragData* dragData, const String& dragStorageName) +{ + SandboxExtension::Handle sandboxExtensionHandle; + performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle); +} + +void WebPageProxy::performDrag(WebCore::DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle); +} + +void WebPageProxy::performDragControllerAction(DragControllerAction action, WebCore::DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle) { if (!isValid()) return; @@ -685,7 +741,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, WebC process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragData->dragDataMap(), dragData->flags()), m_pageID); #else - process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags()), m_pageID); + process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags(), sandboxExtensionHandle), m_pageID); #endif } @@ -758,7 +814,7 @@ void WebPageProxy::dragEnded(const WebCore::IntPoint& clientPosition, const WebC process()->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID); } -void WebPageProxy::handleMouseEvent(const WebMouseEvent& event) +void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event) { if (!isValid()) return; @@ -768,13 +824,20 @@ void WebPageProxy::handleMouseEvent(const WebMouseEvent& event) process()->responsivenessTimer()->start(); else { if (m_processingMouseMoveEvent) { - m_nextMouseMoveEvent = adoptPtr(new WebMouseEvent(event)); + m_nextMouseMoveEvent = adoptPtr(new NativeWebMouseEvent(event)); return; } m_processingMouseMoveEvent = true; } + // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we + // display a popup menu for select elements. When the user changes the selected item, + // we fake a mouse up event by using this stored down event. This event gets cleared + // when the mouse up message is received from WebProcess. + if (event.type() == WebEvent::MouseDown) + m_currentlyProcessedMouseDownEvent = adoptPtr(new NativeWebMouseEvent(event)); + process()->send(Messages::WebPage::MouseEvent(event), m_pageID); } @@ -860,7 +923,7 @@ void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy* fr uint64_t downloadID = 0; if (action == PolicyDownload) { // Create a download proxy. - downloadID = context()->createDownloadProxy(); + downloadID = m_process->context()->createDownloadProxy()->downloadID(); } // If we received a policy decision while in decidePolicyForMIMEType the decision will @@ -1077,6 +1140,9 @@ void WebPageProxy::viewScaleFactorDidChange(double scaleFactor) void WebPageProxy::setMemoryCacheClientCallsEnabled(bool memoryCacheClientCallsEnabled) { + if (!isValid()) + return; + if (m_areMemoryCacheClientCallsEnabled == memoryCacheClientCallsEnabled) return; @@ -1086,7 +1152,10 @@ void WebPageProxy::setMemoryCacheClientCallsEnabled(bool memoryCacheClientCallsE void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount) { - process()->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID); + if (m_mainFrameHasCustomRepresentation) + m_pageClient->findStringInCustomRepresentation(string, options, maxMatchCount); + else + process()->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID); } void WebPageProxy::hideFindUI() @@ -1096,12 +1165,25 @@ void WebPageProxy::hideFindUI() void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount) { + if (m_mainFrameHasCustomRepresentation) { + m_pageClient->countStringMatchesInCustomRepresentation(string, options, maxMatchCount); + return; + } + + if (!isValid()) + return; + process()->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID); } void WebPageProxy::runJavaScriptInMainFrame(const String& script, PassRefPtr<ScriptValueCallback> prpCallback) { RefPtr<ScriptValueCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_scriptValueCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::RunJavaScriptInMainFrame(script, callbackID), m_pageID); @@ -1110,6 +1192,11 @@ void WebPageProxy::runJavaScriptInMainFrame(const String& script, PassRefPtr<Scr void WebPageProxy::getRenderTreeExternalRepresentation(PassRefPtr<StringCallback> prpCallback) { RefPtr<StringCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_stringCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID); @@ -1118,6 +1205,11 @@ void WebPageProxy::getRenderTreeExternalRepresentation(PassRefPtr<StringCallback void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, PassRefPtr<StringCallback> prpCallback) { RefPtr<StringCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_loadDependentStringCallbackIDs.add(callbackID); m_stringCallbacks.set(callbackID, callback.get()); @@ -1127,6 +1219,11 @@ void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, PassRefPtr<StringCall void WebPageProxy::getContentsAsString(PassRefPtr<StringCallback> prpCallback) { RefPtr<StringCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_loadDependentStringCallbackIDs.add(callbackID); m_stringCallbacks.set(callbackID, callback.get()); @@ -1136,6 +1233,11 @@ void WebPageProxy::getContentsAsString(PassRefPtr<StringCallback> prpCallback) void WebPageProxy::getSelectionOrContentsAsString(PassRefPtr<StringCallback> prpCallback) { RefPtr<StringCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_stringCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID); @@ -1144,6 +1246,11 @@ void WebPageProxy::getSelectionOrContentsAsString(PassRefPtr<StringCallback> prp void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback) { RefPtr<DataCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_dataCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID); @@ -1152,6 +1259,11 @@ void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, PassRefPtr<D void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, WebURL* resourceURL, PassRefPtr<DataCallback> prpCallback) { RefPtr<DataCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_dataCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID); @@ -1160,6 +1272,11 @@ void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, WebURL* resour void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback) { RefPtr<DataCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_dataCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID); @@ -1168,7 +1285,6 @@ void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, PassRefPtr<DataCal void WebPageProxy::forceRepaint(PassRefPtr<VoidCallback> prpCallback) { RefPtr<VoidCallback> callback = prpCallback; - if (!isValid()) { callback->invalidate(); return; @@ -1358,7 +1474,7 @@ void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, const Strin clearPendingAPIRequestURL(); RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1374,7 +1490,7 @@ void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, const Strin void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, const String& url, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1389,7 +1505,7 @@ void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t f void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const ResourceError& error, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1417,12 +1533,13 @@ void WebPageProxy::clearLoadDependentCallbacks() void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeType, bool frameHasCustomRepresentation, const PlatformCertificateInfo& certificateInfo, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored); + m_pageClient->dismissDictionaryLookupPanel(); #endif WebFrameProxy* frame = process()->webFrame(frameID); @@ -1443,7 +1560,7 @@ void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeTyp void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1456,7 +1573,7 @@ void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, CoreIPC::Argu void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1471,7 +1588,7 @@ void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, CoreIPC::ArgumentDeco void WebPageProxy::didFailLoadForFrame(uint64_t frameID, const ResourceError& error, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1488,7 +1605,7 @@ void WebPageProxy::didFailLoadForFrame(uint64_t frameID, const ResourceError& er void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint32_t opaqueSameDocumentNavigationType, const String& url, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1503,7 +1620,7 @@ void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint32_t void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1518,7 +1635,7 @@ void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1531,7 +1648,7 @@ void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDec void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1544,7 +1661,7 @@ void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, Core void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1559,7 +1676,7 @@ void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, CoreIPC::Argume void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1572,7 +1689,7 @@ void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, CoreIPC:: void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1596,7 +1713,7 @@ void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value) void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, uint32_t opaqueNavigationType, uint32_t opaqueModifiers, int32_t opaqueMouseButton, const ResourceRequest& request, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1633,7 +1750,7 @@ void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, uint32_t op void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, uint32_t opaqueNavigationType, uint32_t opaqueModifiers, int32_t opaqueMouseButton, const ResourceRequest& request, const String& frameName, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1652,7 +1769,7 @@ void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, uint32_t opa void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1682,7 +1799,7 @@ void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceRespo void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const WebCore::ResourceError& error, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1697,7 +1814,7 @@ void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const WebCore::Reso void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const StringPairVector& textFieldValues, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -1825,7 +1942,7 @@ void WebPageProxy::setStatusText(const String& text) void WebPageProxy::mouseDidMoveOverElement(uint32_t opaqueModifiers, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -2025,9 +2142,22 @@ void WebPageProxy::backForwardForwardListCount(int32_t& count) count = m_backForwardList->forwardListCount(); } -void WebPageProxy::selectionStateChanged(const SelectionState& selectionState) +void WebPageProxy::editorStateChanged(const EditorState& editorState) { - m_selectionState = selectionState; +#if PLATFORM(MAC) + bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone; +#endif + + m_editorState = editorState; + +#if PLATFORM(MAC) + // This is a temporary state. Flipping secure input state too quickly can expose race conditions. + if (editorState.selectionIsNone) + return; + + if (couldChangeSecureInputState) + m_pageClient->updateSecureInputState(); +#endif } #if PLATFORM(WIN) @@ -2054,6 +2184,17 @@ void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editA registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo); } +void WebPageProxy::canUndoRedo(uint32_t action, bool& result) +{ + result = m_pageClient->canUndoRedo(static_cast<UndoOrRedo>(action)); +} + +void WebPageProxy::executeUndoRedo(uint32_t action, bool& result) +{ + m_pageClient->executeUndoRedo(static_cast<UndoOrRedo>(action)); + result = true; +} + void WebPageProxy::clearAllEditCommands() { m_pageClient->clearAllEditCommands(); @@ -2090,6 +2231,11 @@ void WebPageProxy::setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index process()->send(Messages::WebPage::SetTextForActivePopupMenu(index), m_pageID); } +NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent() +{ + return m_currentlyProcessedMouseDownEvent.get(); +} + void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data) { if (m_activePopupMenu) { @@ -2122,8 +2268,16 @@ void WebPageProxy::hidePopupMenu() void WebPageProxy::showContextMenu(const IntPoint& menuLocation, const ContextMenuState& contextMenuState, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::ArgumentDecoder* arguments) { + internalShowContextMenu(menuLocation, contextMenuState, proposedItems, arguments); + + // No matter the result of internalShowContextMenu, always notify the WebProcess that the menu is hidden so it starts handling mouse events again. + process()->send(Messages::WebPage::ContextMenuHidden(), m_pageID); +} + +void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const ContextMenuState& contextMenuState, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::ArgumentDecoder* arguments) +{ RefPtr<APIObject> userData; - WebContextUserMessageDecoder messageDecoder(userData, context()); + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); if (!arguments->decode(messageDecoder)) return; @@ -2185,13 +2339,17 @@ void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item) process()->updateTextCheckerState(); return; } + if (item.action() == ContextMenuItemTagShowSubstitutions) { + TextChecker::toggleSubstitutionsPanelIsShowing(); + return; + } #endif if (item.action() == ContextMenuItemTagDownloadImageToDisk) { - m_context->download(this, KURL(KURL(), m_activeContextMenuState.absoluteImageURLString)); + m_process->context()->download(this, KURL(KURL(), m_activeContextMenuState.absoluteImageURLString)); return; } if (item.action() == ContextMenuItemTagDownloadLinkToDisk) { - m_context->download(this, KURL(KURL(), m_activeContextMenuState.absoluteLinkURLString)); + m_process->context()->download(this, KURL(KURL(), m_activeContextMenuState.absoluteLinkURLString)); return; } if (item.action() == ContextMenuItemTagCheckSpellingWhileTyping) { @@ -2204,6 +2362,12 @@ void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item) process()->updateTextCheckerState(); return; } + if (item.action() == ContextMenuItemTagShowSpellingPanel) { + if (!TextChecker::spellingUIIsShowing()) + advanceToNextMisspelling(true); + TextChecker::toggleSpellingUIIsShowing(); + return; + } if (item.action() == ContextMenuItemTagLearnSpelling || item.action() == ContextMenuItemTagIgnoreSpelling) ++m_pendingLearnOrIgnoreWordMessageCount; @@ -2242,12 +2406,12 @@ void WebPageProxy::didCancelForOpenPanel() m_openPanelResultListener = 0; } -void WebPageProxy::advanceToNextMisspelling(bool startBeforeSelection) +void WebPageProxy::advanceToNextMisspelling(bool startBeforeSelection) const { process()->send(Messages::WebPage::AdvanceToNextMisspelling(startBeforeSelection), m_pageID); } -void WebPageProxy::changeSpellingToWord(const String& word) +void WebPageProxy::changeSpellingToWord(const String& word) const { if (word.isEmpty()) return; @@ -2255,16 +2419,6 @@ void WebPageProxy::changeSpellingToWord(const String& word) process()->send(Messages::WebPage::ChangeSpellingToWord(word), m_pageID); } -void WebPageProxy::unmarkAllMisspellings() -{ - process()->send(Messages::WebPage::UnmarkAllMisspellings(), m_pageID); -} - -void WebPageProxy::unmarkAllBadGrammar() -{ - process()->send(Messages::WebPage::UnmarkAllBadGrammar(), m_pageID); -} - void WebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> commandProxy, UndoOrRedo undoOrRedo) { m_pageClient->registerEditCommand(commandProxy, undoOrRedo); @@ -2292,26 +2446,45 @@ bool WebPageProxy::isValidEditCommand(WebEditCommandProxy* command) int64_t WebPageProxy::spellDocumentTag() { if (!m_hasSpellDocumentTag) { - m_spellDocumentTag = TextChecker::uniqueSpellDocumentTag(); + m_spellDocumentTag = TextChecker::uniqueSpellDocumentTag(this); m_hasSpellDocumentTag = true; } return m_spellDocumentTag; } +#if USE(UNIFIED_TEXT_CHECKING) + void WebPageProxy::checkTextOfParagraph(const String& text, uint64_t checkingTypes, Vector<TextCheckingResult>& results) { results = TextChecker::checkTextOfParagraph(spellDocumentTag(), text.characters(), text.length(), checkingTypes); } +#endif + +void WebPageProxy::checkSpellingOfString(const String& text, int32_t& misspellingLocation, int32_t& misspellingLength) +{ + TextChecker::checkSpellingOfString(spellDocumentTag(), text.characters(), text.length(), misspellingLocation, misspellingLength); +} + +void WebPageProxy::checkGrammarOfString(const String& text, Vector<WebCore::GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength) +{ + TextChecker::checkGrammarOfString(spellDocumentTag(), text.characters(), text.length(), grammarDetails, badGrammarLocation, badGrammarLength); +} + +void WebPageProxy::spellingUIIsShowing(bool& isShowing) +{ + isShowing = TextChecker::spellingUIIsShowing(); +} + void WebPageProxy::updateSpellingUIWithMisspelledWord(const String& misspelledWord) { - TextChecker::updateSpellingUIWithMisspelledWord(misspelledWord); + TextChecker::updateSpellingUIWithMisspelledWord(spellDocumentTag(), misspelledWord); } void WebPageProxy::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) { - TextChecker::updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail); + TextChecker::updateSpellingUIWithGrammarString(spellDocumentTag(), badGrammarPhrase, grammarDetail); } void WebPageProxy::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses) @@ -2324,7 +2497,7 @@ void WebPageProxy::learnWord(const String& word) MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount); --m_pendingLearnOrIgnoreWordMessageCount; - TextChecker::learnWord(word); + TextChecker::learnWord(spellDocumentTag(), word); } void WebPageProxy::ignoreWord(const String& word) @@ -2339,12 +2512,15 @@ void WebPageProxy::ignoreWord(const String& word) void WebPageProxy::setFocus(bool focused) { - m_pageClient->setFocus(focused); + if (focused) + m_uiClient.focus(this); + else + m_uiClient.unfocus(this); } -void WebPageProxy::takeFocus(bool direction) +void WebPageProxy::takeFocus(uint32_t direction) { - m_pageClient->takeFocus(direction); + m_uiClient.takeFocus(this, (static_cast<FocusDirection>(direction) == FocusDirectionForward) ? kWKFocusDirectionForward : kWKFocusDirectionBackward); } void WebPageProxy::setToolTip(const String& toolTip) @@ -2364,6 +2540,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) WebEvent::Type type = static_cast<WebEvent::Type>(opaqueType); switch (type) { + case WebEvent::NoType: case WebEvent::MouseMove: break; @@ -2383,6 +2560,8 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) } switch (type) { + case WebEvent::NoType: + break; case WebEvent::MouseMove: m_processingMouseMoveEvent = false; if (m_nextMouseMoveEvent) { @@ -2391,12 +2570,14 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) } break; case WebEvent::MouseDown: - case WebEvent::MouseUp: #if ENABLE(GESTURE_EVENTS) case WebEvent::GestureScrollBegin: case WebEvent::GestureScrollEnd: #endif break; + case WebEvent::MouseUp: + m_currentlyProcessedMouseDownEvent = nullptr; + break; case WebEvent::Wheel: { m_processingWheelEvent = false; @@ -2421,7 +2602,12 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) if (handled) break; - m_uiClient.didNotHandleKeyEvent(this, event); + if (m_uiClient.implementsDidNotHandleKeyEvent()) + m_uiClient.didNotHandleKeyEvent(this, event); +#if PLATFORM(WIN) + else + ::TranslateMessage(event.nativeEvent()); +#endif break; } } @@ -2542,30 +2728,26 @@ void WebPageProxy::processDidCrash() m_isValid = false; - if (m_mainFrame) - m_urlAtProcessExit = m_mainFrame->url(); - - m_mainFrame = 0; - + m_mainFrame = nullptr; m_drawingArea = nullptr; #if ENABLE(INSPECTOR) if (m_inspector) { m_inspector->invalidate(); - m_inspector = 0; + m_inspector = nullptr; } #endif #if ENABLE(FULLSCREEN_API) if (m_fullScreenManager) { m_fullScreenManager->invalidate(); - m_fullScreenManager = 0; + m_fullScreenManager = nullptr; } #endif if (m_openPanelResultListener) { m_openPanelResultListener->invalidate(); - m_openPanelResultListener = 0; + m_openPanelResultListener = nullptr; } m_geolocationPermissionRequestManager.invalidateRequests(); @@ -2601,6 +2783,17 @@ void WebPageProxy::processDidCrash() m_pageClient->processDidCrash(); m_loaderClient.processDidCrash(this); + + // Can't expect DidReceiveEvent notifications from a crashed web process. + m_keyEventQueue.clear(); + m_nextWheelEvent = nullptr; + m_nextMouseMoveEvent = nullptr; + m_currentlyProcessedMouseDownEvent = nullptr; + +#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) + dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored); + m_pageClient->dismissDictionaryLookupPanel(); +#endif } WebPageCreationParameters WebPageProxy::creationParameters() const @@ -2764,8 +2957,14 @@ void WebPageProxy::endPrinting() process()->send(Messages::WebPage::EndPrinting(), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0); } -void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<ComputedPagesCallback> callback) +void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<ComputedPagesCallback> prpCallback) { + RefPtr<ComputedPagesCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_computedPagesCallbacks.set(callbackID, callback.get()); m_isInPrintingMode = true; @@ -2773,15 +2972,27 @@ void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo } #if PLATFORM(MAC) || PLATFORM(WIN) -void WebPageProxy::drawRectToPDF(WebFrameProxy* frame, const IntRect& rect, PassRefPtr<DataCallback> callback) +void WebPageProxy::drawRectToPDF(WebFrameProxy* frame, const IntRect& rect, PassRefPtr<DataCallback> prpCallback) { + RefPtr<DataCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_dataCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::DrawRectToPDF(frame->frameID(), rect, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0); } -void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, uint32_t first, uint32_t count, PassRefPtr<DataCallback> callback) +void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, uint32_t first, uint32_t count, PassRefPtr<DataCallback> prpCallback) { + RefPtr<DataCallback> callback = prpCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + uint64_t callbackID = callback->callbackID(); m_dataCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::DrawPagesToPDF(frame->frameID(), first, count, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0); @@ -2808,7 +3019,19 @@ void WebPageProxy::saveDataToFileInDownloadsFolder(const String& suggestedFilena m_uiClient.saveDataToFileInDownloadsFolder(this, suggestedFilename, mimeType, originatingURLString, data); } -#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) +void WebPageProxy::linkClicked(const String& url, const WebMouseEvent& event) +{ + process()->send(Messages::WebPage::LinkClicked(url, event), m_pageID, 0); +} + +#if PLATFORM(MAC) + +void WebPageProxy::substitutionsPanelIsShowing(bool& isShowing) +{ + isShowing = TextChecker::substitutionsPanelIsShowing(); +} + +#if !defined(BUILDING_ON_SNOW_LEOPARD) void WebPageProxy::showCorrectionPanel(int32_t panelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) { m_pageClient->showCorrectionPanel((WebCore::CorrectionPanelInfo::PanelType)panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings); @@ -2828,9 +3051,8 @@ void WebPageProxy::recordAutocorrectionResponse(int32_t responseType, const Stri { m_pageClient->recordAutocorrectionResponse((WebCore::EditorClient::AutocorrectionResponseType)responseType, replacedString, replacementString); } -#endif +#endif // !defined(BUILDING_ON_SNOW_LEOPARD) -#if PLATFORM(MAC) void WebPageProxy::handleCorrectionPanelResult(const String& result) { #if !defined(BUILDING_ON_SNOW_LEOPARD) @@ -2838,6 +3060,6 @@ void WebPageProxy::handleCorrectionPanelResult(const String& result) process()->send(Messages::WebPage::HandleCorrectionPanelResult(result), m_pageID, 0); #endif } -#endif +#endif // PLATFORM(MAC) } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index e3e62d4..bea43b5 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -31,9 +31,9 @@ #include "ContextMenuState.h" #include "DragControllerAction.h" #include "DrawingAreaProxy.h" +#include "EditorState.h" #include "GeolocationPermissionRequestManagerProxy.h" #include "SandboxExtension.h" -#include "SelectionState.h" #include "SharedMemory.h" #include "WKBase.h" #include "WKPagePrivate.h" @@ -78,6 +78,7 @@ namespace WebCore { namespace WebKit { class NativeWebKeyboardEvent; +class NativeWebMouseEvent; class PageClient; class PlatformCertificateInfo; class StringPairVector; @@ -94,7 +95,9 @@ class WebPageGroup; class WebProcessProxy; class WebURLRequest; class WebWheelEvent; +struct AttributedString; struct DictionaryPopupInfo; +struct EditorState; struct PlatformPopupMenuData; struct PrintInfo; struct WebPageCreationParameters; @@ -156,7 +159,7 @@ class WebPageProxy : public APIObject, public WebPopupMenuProxy::Client { public: static const Type APIType = TypePage; - static PassRefPtr<WebPageProxy> create(PageClient*, WebContext*, WebPageGroup*, uint64_t pageID); + static PassRefPtr<WebPageProxy> create(PageClient*, PassRefPtr<WebProcessProxy>, WebPageGroup*, uint64_t pageID); virtual ~WebPageProxy(); uint64_t pageID() const { return m_pageID; } @@ -239,23 +242,34 @@ public: WebCore::IntSize viewSize() const; bool isViewVisible() const { return m_isVisible; } + bool isViewWindowActive() const; void executeEditCommand(const String& commandName); void validateCommand(const String& commandName, PassRefPtr<ValidateCommandCallback>); - const SelectionState& selectionState() const { return m_selectionState; } + const EditorState& editorState() const { return m_editorState; } bool canDelete() const { return hasSelectedRange() && isContentEditable(); } - bool hasSelectedRange() const { return m_selectionState.selectedRangeLength; } - bool isContentEditable() const { return m_selectionState.isContentEditable; } + bool hasSelectedRange() const { return m_editorState.selectionIsRange; } + bool isContentEditable() const { return m_editorState.isContentEditable; } #if PLATFORM(MAC) void updateWindowIsVisible(bool windowIsVisible); void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates); + + void setComposition(const String& text, Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd); + void confirmComposition(); + bool insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd); void getMarkedRange(uint64_t& location, uint64_t& length); + void getSelectedRange(uint64_t& location, uint64_t& length); + void getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString&); uint64_t characterIndexForPoint(const WebCore::IntPoint); WebCore::IntRect firstRectForCharacterRange(uint64_t, uint64_t); + bool executeKeypressCommands(const Vector<WebCore::KeypressCommand>&); + void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput); CGContextRef containingWindowGraphicsContext(); + bool shouldDelayWindowOrderingForEvent(const WebMouseEvent&); + bool acceptsFirstMouse(int eventNumber, const WebMouseEvent&); #endif #if PLATFORM(WIN) void didChangeCompositionSelection(bool); @@ -263,12 +277,18 @@ public: void setComposition(const String&, Vector<WebCore::CompositionUnderline>&, int); WebCore::IntRect firstRectForCharacterInSelectedRange(int); String getSelectedText(); + + bool gestureWillBegin(const WebCore::IntPoint&); + void gestureDidScroll(const WebCore::IntSize&); + void gestureDidEnd(); + + void setGestureReachedScrollingLimit(bool); #endif #if ENABLE(TILED_BACKING_STORE) void setActualVisibleContentRect(const WebCore::IntRect& rect); #endif - void handleMouseEvent(const WebMouseEvent&); + void handleMouseEvent(const NativeWebMouseEvent&); void handleWheelEvent(const WebWheelEvent&); void handleKeyboardEvent(const NativeWebKeyboardEvent&); #if ENABLE(GESTURE_EVENTS) @@ -340,6 +360,10 @@ public: void findString(const String&, FindOptions, unsigned maxMatchCount); void hideFindUI(); void countStringMatches(const String&, FindOptions, unsigned maxMatchCount); + void didCountStringMatches(const String&, uint32_t matchCount); + void setFindIndicator(const WebCore::FloatRect& selectionRectInWindowCoordinates, const Vector<WebCore::FloatRect>& textRectsInSelectionRectCoordinates, const ShareableBitmap::Handle& contentImageHandle, bool fadeOut); + void didFindString(const String&, uint32_t matchCount); + void didFailToFindString(const String&); void getContentsAsString(PassRefPtr<StringCallback>); void getMainResourceDataOfFrame(WebFrameProxy*, PassRefPtr<DataCallback>); @@ -366,7 +390,11 @@ public: void backForwardRemovedItem(uint64_t itemID); // Drag and drop support. - void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String& = String()); + void dragEntered(WebCore::DragData*, const String& dragStorageName = String()); + void dragUpdated(WebCore::DragData*, const String& dragStorageName = String()); + void dragExited(WebCore::DragData*, const String& dragStorageName = String()); + void performDrag(WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&); + void didPerformDragControllerAction(uint64_t resultOperation); void dragEnded(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t operation); #if PLATFORM(MAC) @@ -396,7 +424,6 @@ public: void registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo); WebProcessProxy* process() const; - WebContext* context() const { return m_context.get(); } WebPageGroup* pageGroup() const { return m_pageGroup.get(); } @@ -405,9 +432,6 @@ public: WebCore::DragOperation dragOperation() { return m_currentDragOperation; } void resetDragOperation() { m_currentDragOperation = WebCore::DragOperationNone; } - // REMOVE: For demo purposes only. - const String& urlAtProcessExit() const { return m_urlAtProcessExit; } - void preferencesDidChange(); #if ENABLE(TILED_BACKING_STORE) @@ -427,10 +451,8 @@ public: void findZoomableAreaForPoint(const WebCore::IntPoint&); #endif - void advanceToNextMisspelling(bool startBeforeSelection); - void changeSpellingToWord(const String& word); - void unmarkAllMisspellings(); - void unmarkAllBadGrammar(); + void advanceToNextMisspelling(bool startBeforeSelection) const; + void changeSpellingToWord(const String& word) const; #if PLATFORM(MAC) void uppercaseWord(); void lowercaseWord(); @@ -467,14 +489,17 @@ public: void saveDataToFileInDownloadsFolder(const String& suggestedFilename, const String& mimeType, const String& originatingURLString, WebData*); + void linkClicked(const String&, const WebMouseEvent&); + private: - WebPageProxy(PageClient*, WebContext*, WebPageGroup*, uint64_t pageID); + WebPageProxy(PageClient*, PassRefPtr<WebProcessProxy>, WebPageGroup*, uint64_t pageID); virtual Type type() const { return APIType; } // WebPopupMenuProxy::Client virtual void valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex); virtual void setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index); + virtual NativeWebMouseEvent* currentlyProcessedMouseDownEvent(); // Implemented in generated WebPageProxyMessageReceiver.cpp void didReceiveWebPageProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); @@ -564,8 +589,7 @@ private: void didFindZoomableArea(const WebCore::IntRect&); #endif - // Selection - void selectionStateChanged(const SelectionState&); + void editorStateChanged(const EditorState&); // Back/Forward list management void backForwardAddItem(uint64_t itemID); @@ -578,24 +602,33 @@ private: // Undo management void registerEditCommandForUndo(uint64_t commandID, uint32_t editAction); void clearAllEditCommands(); + void canUndoRedo(uint32_t action, bool& result); + void executeUndoRedo(uint32_t action, bool& result); // Keyboard handling #if PLATFORM(MAC) - void interpretKeyEvent(uint32_t eventType, Vector<WebCore::KeypressCommand>&, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines); + void interpretQueuedKeyEvent(const EditorState&, bool& handled, Vector<WebCore::KeypressCommand>&); + void executeSavedCommandBySelector(const String& selector, bool& handled); +#endif + +#if PLATFORM(GTK) + void getEditorCommandsForKeyEvent(Vector<String>&); #endif - - // Find. - void didCountStringMatches(const String&, uint32_t matchCount); - void setFindIndicator(const WebCore::FloatRect& selectionRectInWindowCoordinates, const Vector<WebCore::FloatRect>& textRectsInSelectionRectCoordinates, const ShareableBitmap::Handle& contentImageHandle, bool fadeOut); - void didFindString(const String&, uint32_t matchCount); - void didFailToFindString(const String&); // Popup Menu. void showPopupMenu(const WebCore::IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData&); void hidePopupMenu(); +#if PLATFORM(WIN) + void setPopupMenuSelectedIndex(int32_t); +#endif // Context Menu. void showContextMenu(const WebCore::IntPoint& menuLocation, const ContextMenuState&, const Vector<WebContextMenuItemData>&, CoreIPC::ArgumentDecoder*); + void internalShowContextMenu(const WebCore::IntPoint& menuLocation, const ContextMenuState&, const Vector<WebContextMenuItemData>&, CoreIPC::ArgumentDecoder*); + + // Search popup results + void saveRecentSearches(const String&, const Vector<String>&); + void loadRecentSearches(const String&, Vector<String>&); #if PLATFORM(MAC) // Speech. @@ -603,13 +636,21 @@ private: void speak(const String&); void stopSpeaking(); + // Spotlight. + void searchWithSpotlight(const String&); + // Dictionary. void didPerformDictionaryLookup(const String&, const DictionaryPopupInfo&); #endif // Spelling and grammar. int64_t spellDocumentTag(); +#if USE(UNIFIED_TEXT_CHECKING) void checkTextOfParagraph(const String& text, uint64_t checkingTypes, Vector<WebCore::TextCheckingResult>& results); +#endif + void checkSpellingOfString(const String& text, int32_t& misspellingLocation, int32_t& misspellingLength); + void checkGrammarOfString(const String& text, Vector<WebCore::GrammarDetail>&, int32_t& badGrammarLocation, int32_t& badGrammarLength); + void spellingUIIsShowing(bool&); void updateSpellingUIWithMisspelledWord(const String& misspelledWord); void updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const WebCore::GrammarDetail&); void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses); @@ -617,7 +658,7 @@ private: void ignoreWord(const String& word); void setFocus(bool focused); - void takeFocus(bool direction); + void takeFocus(uint32_t direction); void setToolTip(const String&); void setCursor(const WebCore::Cursor&); @@ -649,15 +690,20 @@ private: void initializeSandboxExtensionHandle(const WebCore::KURL&, SandboxExtension::Handle&); -#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) +#if PLATFORM(MAC) + void substitutionsPanelIsShowing(bool&); +#if !defined(BUILDING_ON_SNOW_LEOPARD) void showCorrectionPanel(int32_t panelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); void dismissCorrectionPanel(int32_t reason); void dismissCorrectionPanelSoon(int32_t reason, String& result); void recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString); -#endif +#endif // !defined(BUILDING_ON_SNOW_LEOPARD) +#endif // PLATFORM(MAC) void clearLoadDependentCallbacks(); + void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&); + PageClient* m_pageClient; WebLoaderClient m_loaderClient; WebPolicyClient m_policyClient; @@ -668,7 +714,7 @@ private: WebPageContextMenuClient m_contextMenuClient; OwnPtr<DrawingAreaProxy> m_drawingArea; - RefPtr<WebContext> m_context; + RefPtr<WebProcessProxy> m_process; RefPtr<WebPageGroup> m_pageGroup; RefPtr<WebFrameProxy> m_mainFrame; RefPtr<WebFrameProxy> m_focusedFrame; @@ -717,10 +763,7 @@ private: String m_toolTip; - SelectionState m_selectionState; - - // REMOVE: For demo purposes only. - String m_urlAtProcessExit; + EditorState m_editorState; double m_textZoomFactor; double m_pageZoomFactor; @@ -758,7 +801,8 @@ private: OwnPtr<WebWheelEvent> m_nextWheelEvent; bool m_processingMouseMoveEvent; - OwnPtr<WebMouseEvent> m_nextMouseMoveEvent; + OwnPtr<NativeWebMouseEvent> m_nextMouseMoveEvent; + OwnPtr<NativeWebMouseEvent> m_currentlyProcessedMouseDownEvent; uint64_t m_pageID; diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in index e145d82..f5f4238 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in @@ -36,7 +36,7 @@ messages -> WebPageProxy { SetStatusText(WTF::String statusText) SetToolTip(WTF::String toolTip) SetFocus(bool focused) - TakeFocus(bool direction) + TakeFocus(uint32_t direction) FocusedFrameChanged(uint64_t frameID) FrameSetLargestFrameChanged(uint64_t frameID) SetToolbarsAreVisible(bool toolbarsAreVisible) @@ -126,17 +126,11 @@ messages -> WebPageProxy { ViewScaleFactorDidChange(double scaleFactor) -#if PLATFORM(MAC) - # Dictionary support. - DidPerformDictionaryLookup(WTF::String text, WebKit::DictionaryPopupInfo dictionaryPopupInfo) - - # Keyboard support messages - InterpretKeyEvent(uint32_t type) -> (Vector<WebCore::KeypressCommand> commandName, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline> underlines) - - # Remote accessibility messages - RegisterWebProcessAccessibilityToken(CoreIPC::DataReference data) +#if PLATFORM(GTK) + # Support for GTK+ platform keybindings + GetEditorCommandsForKeyEvent() -> (Vector<WTF::String> commandsList) #endif - + # BackForward messages BackForwardAddItem(uint64_t itemID) BackForwardGoToItem(uint64_t itemID) @@ -149,10 +143,11 @@ messages -> WebPageProxy { # Undo/Redo messages RegisterEditCommandForUndo(uint64_t commandID, uint32_t editAction) ClearAllEditCommands() - - # Selection messages - SelectionStateChanged(WebKit::SelectionState selectionState) + CanUndoRedo(uint32_t action) -> (bool result) + ExecuteUndoRedo(uint32_t action) -> (bool result) + # Editor notifications + EditorStateChanged(WebKit::EditorState editorState) #if PLATFORM(WIN) DidChangeCompositionSelection(bool hasChanged) #endif @@ -166,7 +161,10 @@ messages -> WebPageProxy { # PopupMenu messages ShowPopupMenu(WebCore::IntRect rect, uint64_t textDirection, Vector<WebKit::WebPopupItem> items, int32_t selectedIndex, WebKit::PlatformPopupMenuData data) HidePopupMenu() - +#if PLATFORM(WIN) + SetPopupMenuSelectedIndex(int32_t selectedIndex) +#endif + # ContextMenu messages ShowContextMenu(WebCore::IntPoint menuLocation, WebKit::ContextMenuState state, Vector<WebKit::WebContextMenuItemData> items, WebKit::InjectedBundleUserMessageEncoder userData) @@ -180,20 +178,13 @@ messages -> WebPageProxy { # Geolocation messages RequestGeolocationPermissionForFrame(uint64_t geolocationID, uint64_t frameID, WTF::String originIdentifier) -#if PLATFORM(MAC) - # Plug-in complex text input support messages - SetComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled) -#endif - -#if PLATFORM(MAC) - # Speech messages - GetIsSpeaking() -> (bool isSpeaking) - Speak(WTF::String string) - StopSpeaking() -#endif - # Spelling and grammar messages +#if USE(UNIFIED_TEXT_CHECKING) CheckTextOfParagraph(WTF::String text, uint64_t checkingTypes) -> (Vector<WebCore::TextCheckingResult> results) +#endif + CheckSpellingOfString(WTF::String text) -> (int32_t misspellingLocation, int32_t misspellingLength) + CheckGrammarOfString(WTF::String text) -> (Vector<WebCore::GrammarDetail> results, int32_t badGrammarLocation, int32_t badGrammarLength) + SpellingUIIsShowing() -> (bool isShowing) UpdateSpellingUIWithMisspelledWord(WTF::String misspelledWord) UpdateSpellingUIWithGrammarString(WTF::String badGrammarPhrase, WebCore::GrammarDetail grammarDetail) GetGuessesForWord(WTF::String word, WTF::String context) -> (Vector<WTF::String> guesses) @@ -209,6 +200,32 @@ messages -> WebPageProxy { StartDragDrop(WebCore::IntPoint imagePoint, WebCore::IntPoint dragPoint, uint64_t okEffect, HashMap<UINT,Vector<String> > dataMap, WebCore::IntSize dragImageSize, WebKit::SharedMemory::Handle dragImage, bool linkDrag) #endif +#if PLATFORM(MAC) + # Dictionary support. + DidPerformDictionaryLookup(WTF::String text, WebKit::DictionaryPopupInfo dictionaryPopupInfo) + + # Keyboard input support messages + InterpretQueuedKeyEvent(WebKit::EditorState state) -> (bool handled, Vector<WebCore::KeypressCommand> savedCommands) + ExecuteSavedCommandBySelector(WTF::String selector) -> (bool handled) + + # Remote accessibility messages + RegisterWebProcessAccessibilityToken(CoreIPC::DataReference data) + + # Plug-in complex text input support messages + SetComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled) + + # Speech messages + GetIsSpeaking() -> (bool isSpeaking) + Speak(WTF::String string) + StopSpeaking() + + # Spotlight + SearchWithSpotlight(WTF::String string) +#endif + +#if PLATFORM(MAC) + SubstitutionsPanelIsShowing() -> (bool isShowing) +#endif #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) # Autocorrection messages ShowCorrectionPanel(int32_t panelType, WebCore::FloatRect boundingBoxOfReplacedString, String replacedString, String replacementString, Vector<String> alternativeReplacementStrings) @@ -216,4 +233,13 @@ messages -> WebPageProxy { DismissCorrectionPanelSoon(int32_t reason) -> (String result) RecordAutocorrectionResponse(int32_t responseType, String replacedString, String replacementString); #endif + +#if PLATFORM(WIN) + # Windows 7 Gesture Messages + SetGestureReachedScrollingLimit(bool limitReached) +#endif + + # Search popup menus + SaveRecentSearches(WTF::String name, Vector<String> searchItems) + LoadRecentSearches(WTF::String name) -> (Vector<String> result) } diff --git a/Source/WebKit2/UIProcess/WebPopupMenuProxy.h b/Source/WebKit2/UIProcess/WebPopupMenuProxy.h index 96901fb..0af8880 100644 --- a/Source/WebKit2/UIProcess/WebPopupMenuProxy.h +++ b/Source/WebKit2/UIProcess/WebPopupMenuProxy.h @@ -39,6 +39,7 @@ namespace WebKit { struct PlatformPopupMenuData; struct WebPopupItem; +class NativeWebMouseEvent; class WebPopupMenuProxy : public RefCounted<WebPopupMenuProxy> { public: @@ -51,6 +52,7 @@ public: public: virtual void valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex) = 0; virtual void setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index) = 0; + virtual NativeWebMouseEvent* currentlyProcessedMouseDownEvent() = 0; }; virtual ~WebPopupMenuProxy() diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.cpp b/Source/WebKit2/UIProcess/WebProcessProxy.cpp index 8a48724..a8ae574 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/WebProcessProxy.cpp @@ -37,7 +37,6 @@ #include "WebPageProxy.h" #include "WebProcessMessages.h" #include "WebProcessProxyMessages.h" -#include "WebProcessProxyMessageKinds.h" #include <WebCore/KURL.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -59,12 +58,12 @@ static uint64_t generatePageID() return uniquePageID++; } -PassRefPtr<WebProcessProxy> WebProcessProxy::create(WebContext* context) +PassRefPtr<WebProcessProxy> WebProcessProxy::create(PassRefPtr<WebContext> context) { return adoptRef(new WebProcessProxy(context)); } -WebProcessProxy::WebProcessProxy(WebContext* context) +WebProcessProxy::WebProcessProxy(PassRefPtr<WebContext> context) : m_responsivenessTimer(this) , m_context(context) { @@ -163,17 +162,17 @@ void WebProcessProxy::terminate() WebPageProxy* WebProcessProxy::webPage(uint64_t pageID) const { - return m_pageMap.get(pageID).get(); + return m_pageMap.get(pageID); } -WebPageProxy* WebProcessProxy::createWebPage(PageClient* pageClient, WebContext* context, WebPageGroup* pageGroup) +PassRefPtr<WebPageProxy> WebProcessProxy::createWebPage(PageClient* pageClient, WebContext* context, WebPageGroup* pageGroup) { ASSERT(context->process() == this); unsigned pageID = generatePageID(); - RefPtr<WebPageProxy> webPage = WebPageProxy::create(pageClient, context, pageGroup, pageID); - m_pageMap.set(pageID, webPage); - return webPage.get(); + RefPtr<WebPageProxy> webPage = WebPageProxy::create(pageClient, this, pageGroup, pageID); + m_pageMap.set(pageID, webPage.get()); + return webPage.release(); } void WebProcessProxy::addExistingWebPage(WebPageProxy* webPage, uint64_t pageID) @@ -186,21 +185,6 @@ void WebProcessProxy::removeWebPage(uint64_t pageID) m_pageMap.remove(pageID); } -WebProcessProxy::pages_const_iterator WebProcessProxy::pages_begin() -{ - return m_pageMap.begin().values(); -} - -WebProcessProxy::pages_const_iterator WebProcessProxy::pages_end() -{ - return m_pageMap.end().values(); -} - -size_t WebProcessProxy::numberOfPages() -{ - return m_pageMap.size(); -} - WebBackForwardListItem* WebProcessProxy::webBackForwardItem(uint64_t itemID) const { return m_backForwardListItemMap.get(itemID).get(); @@ -232,9 +216,14 @@ void WebProcessProxy::addBackForwardItem(uint64_t itemID, const String& original } #if ENABLE(PLUGIN_PROCESS) -void WebProcessProxy::getPluginProcessConnection(const String& pluginPath, CoreIPC::ArgumentEncoder* reply) +void WebProcessProxy::getPluginProcessConnection(const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply) { - PluginProcessManager::shared().getPluginProcessConnection(pluginPath, this, reply); + PluginProcessManager::shared().getPluginProcessConnection(context()->pluginInfoStore(), pluginPath, reply); +} + +void WebProcessProxy::pluginSyncMessageSendTimedOut(const String& pluginPath) +{ + PluginProcessManager::shared().pluginSyncMessageSendTimedOut(pluginPath); } #endif @@ -276,22 +265,6 @@ CoreIPC::SyncReplyMode WebProcessProxy::didReceiveSyncMessage(CoreIPC::Connectio if (messageID.is<CoreIPC::MessageClassWebProcessProxy>()) return didReceiveSyncWebProcessProxyMessage(connection, messageID, arguments, reply); -#if ENABLE(PLUGIN_PROCESS) - if (messageID.is<CoreIPC::MessageClassWebProcessProxyLegacy>()) { - switch (messageID.get<WebProcessProxyLegacyMessage::Kind>()) { - case WebProcessProxyLegacyMessage::GetPluginProcessConnection: { - String pluginPath; - - if (!arguments->decode(CoreIPC::Out(pluginPath))) - return CoreIPC::AutomaticReply; - - getPluginProcessConnection(pluginPath, reply); - return CoreIPC::ManualReply; - } - } - } -#endif - if (messageID.is<CoreIPC::MessageClassWebContext>() || messageID.is<CoreIPC::MessageClassWebContextLegacy>() || messageID.is<CoreIPC::MessageClassDownloadProxy>() || messageID.is<CoreIPC::MessageClassWebIconDatabase>()) return m_context->didReceiveSyncMessage(connection, messageID, arguments, reply); @@ -331,6 +304,10 @@ void WebProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::Me terminate(); } +void WebProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*) +{ +} + void WebProcessProxy::didBecomeUnresponsive(ResponsivenessTimer*) { Vector<RefPtr<WebPageProxy> > pages; @@ -364,7 +341,7 @@ void WebProcessProxy::didFinishLaunching(CoreIPC::Connection::Identifier connect m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main()); #if PLATFORM(MAC) m_connection->setShouldCloseConnectionOnMachExceptions(); -#elif PLATFORM(QT) +#elif PLATFORM(QT) || PLATFORM(GTK) m_connection->setShouldCloseConnectionOnProcessTermination(processIdentifier()); #endif diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.h b/Source/WebKit2/UIProcess/WebProcessProxy.h index 04dbd98..761aad4 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.h +++ b/Source/WebKit2/UIProcess/WebProcessProxy.h @@ -34,6 +34,7 @@ #include "ResponsivenessTimer.h" #include "ThreadLauncher.h" #include "WebPageProxy.h" +#include "WebProcessProxyMessages.h" #include <WebCore/LinkHash.h> #include <wtf/Forward.h> #include <wtf/HashMap.h> @@ -53,12 +54,10 @@ struct WebNavigationDataStore; class WebProcessProxy : public RefCounted<WebProcessProxy>, CoreIPC::Connection::Client, ResponsivenessTimer::Client, ProcessLauncher::Client, ThreadLauncher::Client { public: - typedef HashMap<uint64_t, RefPtr<WebPageProxy> > WebPageProxyMap; - typedef WebPageProxyMap::const_iterator::Values pages_const_iterator; typedef HashMap<uint64_t, RefPtr<WebFrameProxy> > WebFrameProxyMap; typedef HashMap<uint64_t, RefPtr<WebBackForwardListItem> > WebBackForwardListItemMap; - static PassRefPtr<WebProcessProxy> create(WebContext*); + static PassRefPtr<WebProcessProxy> create(PassRefPtr<WebContext>); ~WebProcessProxy(); void terminate(); @@ -73,19 +72,15 @@ public: return m_connection.get(); } - WebContext* context() const { return m_context; } + WebContext* context() const { return m_context.get(); } PlatformProcessIdentifier processIdentifier() const { return m_processLauncher->processIdentifier(); } WebPageProxy* webPage(uint64_t pageID) const; - WebPageProxy* createWebPage(PageClient*, WebContext*, WebPageGroup*); + PassRefPtr<WebPageProxy> createWebPage(PageClient*, WebContext*, WebPageGroup*); void addExistingWebPage(WebPageProxy*, uint64_t pageID); void removeWebPage(uint64_t pageID); - pages_const_iterator pages_begin(); - pages_const_iterator pages_end(); - size_t numberOfPages(); - WebBackForwardListItem* webBackForwardItem(uint64_t itemID) const; ResponsivenessTimer* responsivenessTimer() { return &m_responsivenessTimer; } @@ -108,7 +103,7 @@ public: template<typename E, typename T> bool deprecatedSend(E messageID, uint64_t destinationID, const T& arguments); private: - explicit WebProcessProxy(WebContext*); + explicit WebProcessProxy(PassRefPtr<WebContext>); // Initializes the process or thread launcher which will begin launching the process. void connect(); @@ -126,14 +121,20 @@ private: void shouldTerminate(bool& shouldTerminate); #if ENABLE(PLUGIN_PROCESS) - void getPluginProcessConnection(const String& pluginPath, CoreIPC::ArgumentEncoder* reply); + void getPluginProcessConnection(const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>); + void pluginSyncMessageSendTimedOut(const String& pluginPath); #endif // CoreIPC::Connection::Client - void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); - CoreIPC::SyncReplyMode didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*); - void didClose(CoreIPC::Connection*); - void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID); + virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + virtual CoreIPC::SyncReplyMode didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*); + virtual void didClose(CoreIPC::Connection*); + virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID); + virtual void syncMessageSendTimedOut(CoreIPC::Connection*); + +#if PLATFORM(WIN) + Vector<HWND> windowsToReceiveSentMessagesWhileWaitingForSyncReply(); +#endif // ResponsivenessTimer::Client void didBecomeUnresponsive(ResponsivenessTimer*); @@ -158,9 +159,9 @@ private: RefPtr<ProcessLauncher> m_processLauncher; RefPtr<ThreadLauncher> m_threadLauncher; - WebContext* m_context; + RefPtr<WebContext> m_context; - WebPageProxyMap m_pageMap; + HashMap<uint64_t, WebPageProxy*> m_pageMap; WebFrameProxyMap m_frameMap; WebBackForwardListItemMap m_backForwardListItemMap; }; diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.messages.in b/Source/WebKit2/UIProcess/WebProcessProxy.messages.in index 99014d4..e80bdd0 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebProcessProxy.messages.in @@ -26,4 +26,9 @@ messages -> WebProcessProxy { DidDestroyFrame(uint64_t frameID) ShouldTerminate() -> (bool shouldTerminate) + +#if ENABLE(PLUGIN_PROCESS) + GetPluginProcessConnection(WTF::String pluginPath) -> (CoreIPC::MachPort connectionHandle) Delayed + PluginSyncMessageSendTimedOut(WTF::String pluginPath) +#endif } diff --git a/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp b/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp index 403a8dc..8c06bdc 100644 --- a/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp @@ -67,7 +67,9 @@ void WebResourceCacheManagerProxy::getCacheOrigins(PassRefPtr<ArrayCallback> prp m_webContext->relaunchProcessIfNecessary(); uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - m_webContext->process()->send(Messages::WebResourceCacheManager::GetCacheOrigins(callbackID), 0); + + // FIXME (Multi-WebProcess): When multi-process is enabled, we need to aggregate the callback data from all processes. + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebResourceCacheManager::GetCacheOrigins(callbackID)); } void WebResourceCacheManagerProxy::didGetCacheOrigins(const Vector<SecurityOriginData>& origins, uint64_t callbackID) @@ -76,21 +78,19 @@ void WebResourceCacheManagerProxy::didGetCacheOrigins(const Vector<SecurityOrigi performAPICallbackWithSecurityOriginDataVector(origins, callback.get()); } -void WebResourceCacheManagerProxy::clearCacheForOrigin(WebSecurityOrigin* origin) +void WebResourceCacheManagerProxy::clearCacheForOrigin(WebSecurityOrigin* origin, ResourceCachesToClear cachesToClear) { - m_webContext->relaunchProcessIfNecessary(); - SecurityOriginData securityOrigin; securityOrigin.protocol = origin->protocol(); securityOrigin.host = origin->host(); securityOrigin.port = origin->port(); - m_webContext->process()->send(Messages::WebResourceCacheManager::ClearCacheForOrigin(securityOrigin), 0); + + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebResourceCacheManager::ClearCacheForOrigin(securityOrigin, cachesToClear)); } -void WebResourceCacheManagerProxy::clearCacheForAllOrigins() +void WebResourceCacheManagerProxy::clearCacheForAllOrigins(ResourceCachesToClear cachesToClear) { - m_webContext->relaunchProcessIfNecessary(); - m_webContext->process()->send(Messages::WebResourceCacheManager::ClearCacheForAllOrigins(), 0); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebResourceCacheManager::ClearCacheForAllOrigins(cachesToClear)); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.h b/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.h index 1a360b4..f0c7bb5 100644 --- a/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.h +++ b/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.h @@ -29,6 +29,7 @@ #include "APIObject.h" #include "Arguments.h" #include "GenericCallback.h" +#include "ResourceCachesToClear.h" #include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> @@ -58,8 +59,8 @@ public: void clearContext() { m_webContext = 0; } void getCacheOrigins(PassRefPtr<ArrayCallback>); - void clearCacheForOrigin(WebSecurityOrigin*); - void clearCacheForAllOrigins(); + void clearCacheForOrigin(WebSecurityOrigin*, ResourceCachesToClear); + void clearCacheForAllOrigins(ResourceCachesToClear); void didReceiveWebResourceCacheManagerProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); diff --git a/Source/WebKit2/UIProcess/WebUIClient.cpp b/Source/WebKit2/UIProcess/WebUIClient.cpp index 9bb8efc..ec13a41 100644 --- a/Source/WebKit2/UIProcess/WebUIClient.cpp +++ b/Source/WebKit2/UIProcess/WebUIClient.cpp @@ -84,6 +84,30 @@ void WebUIClient::close(WebPageProxy* page) m_client.close(toAPI(page), m_client.clientInfo); } +void WebUIClient::takeFocus(WebPageProxy* page, WKFocusDirection direction) +{ + if (!m_client.takeFocus) + return; + + m_client.takeFocus(toAPI(page), direction, m_client.clientInfo); +} + +void WebUIClient::focus(WebPageProxy* page) +{ + if (!m_client.focus) + return; + + m_client.focus(toAPI(page), m_client.clientInfo); +} + +void WebUIClient::unfocus(WebPageProxy* page) +{ + if (!m_client.unfocus) + return; + + m_client.unfocus(toAPI(page), m_client.clientInfo); +} + void WebUIClient::runJavaScriptAlert(WebPageProxy* page, const String& message, WebFrameProxy* frame) { if (!m_client.runJavaScriptAlert) @@ -139,6 +163,11 @@ void WebUIClient::missingPluginButtonClicked(WebPageProxy* page, const String& m m_client.missingPluginButtonClicked(toAPI(page), toAPI(mimeType.impl()), toAPI(url.impl()), toAPI(pluginsPageURL.impl()), m_client.clientInfo); } +bool WebUIClient::implementsDidNotHandleKeyEvent() const +{ + return m_client.didNotHandleKeyEvent; +} + void WebUIClient::didNotHandleKeyEvent(WebPageProxy* page, const NativeWebKeyboardEvent& event) { if (!m_client.didNotHandleKeyEvent) diff --git a/Source/WebKit2/UIProcess/WebUIClient.h b/Source/WebKit2/UIProcess/WebUIClient.h index 8fcf7b6..196574a 100644 --- a/Source/WebKit2/UIProcess/WebUIClient.h +++ b/Source/WebKit2/UIProcess/WebUIClient.h @@ -56,6 +56,10 @@ public: void showPage(WebPageProxy*); void close(WebPageProxy*); + void takeFocus(WebPageProxy*, WKFocusDirection); + void focus(WebPageProxy*); + void unfocus(WebPageProxy*); + void runJavaScriptAlert(WebPageProxy*, const String&, WebFrameProxy*); bool runJavaScriptConfirm(WebPageProxy*, const String&, WebFrameProxy*); String runJavaScriptPrompt(WebPageProxy*, const String&, const String&, WebFrameProxy*); @@ -63,6 +67,8 @@ public: void setStatusText(WebPageProxy*, const String&); void mouseDidMoveOverElement(WebPageProxy*, WebEvent::Modifiers, APIObject*); void missingPluginButtonClicked(WebPageProxy*, const String& mimeType, const String& url, const String& pluginsPageURL); + + bool implementsDidNotHandleKeyEvent() const; void didNotHandleKeyEvent(WebPageProxy*, const NativeWebKeyboardEvent&); bool toolbarsAreVisible(WebPageProxy*); diff --git a/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp b/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp index 718e3b8..73245dd 100644 --- a/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp +++ b/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp @@ -54,18 +54,18 @@ CFDictionaryRef WebBackForwardList::createCFDictionaryRepresentation(WebPageProx { ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size()); - RetainPtr<CFNumberRef> currentIndex(AdoptCF, CFNumberCreate(0, kCFNumberIntType, &m_current)); RetainPtr<CFMutableArrayRef> entries(AdoptCF, CFArrayCreateMutable(0, m_entries.size(), &kCFTypeArrayCallBacks)); - - const void* keys[2] = { SessionHistoryCurrentIndexKey(), SessionHistoryEntriesKey() }; - const void* values[2] = { currentIndex.get(), entries.get() }; - RetainPtr<CFDictionaryRef> dictionary(AdoptCF, CFDictionaryCreate(0, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + // We may need to update the current index to account for entries that are filtered by the callback. + int currentIndex = m_current; for (size_t i = 0; i < m_entries.size(); ++i) { RefPtr<WebURL> webURL = WebURL::create(m_entries[i]->url()); - if (filter && !filter(toAPI(m_page), WKPageGetSessionHistoryURLValueType(), toURLRef(m_entries[i]->originalURL().impl()), context)) + if (filter && !filter(toAPI(m_page), WKPageGetSessionHistoryURLValueType(), toURLRef(m_entries[i]->originalURL().impl()), context)) { + if (i <= static_cast<size_t>(currentIndex)) + currentIndex--; continue; + } RetainPtr<CFStringRef> url(AdoptCF, m_entries[i]->url().createCFString()); RetainPtr<CFStringRef> title(AdoptCF, m_entries[i]->title().createCFString()); @@ -78,8 +78,12 @@ CFDictionaryRef WebBackForwardList::createCFDictionaryRepresentation(WebPageProx RetainPtr<CFDictionaryRef> entryDictionary(AdoptCF, CFDictionaryCreate(0, keys, values, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFArrayAppendValue(entries.get(), entryDictionary.get()); } - - return dictionary.leakRef(); + RetainPtr<CFNumberRef> currentIndexNumber(AdoptCF, CFNumberCreate(0, kCFNumberIntType, ¤tIndex)); + + const void* keys[2] = { SessionHistoryCurrentIndexKey(), SessionHistoryEntriesKey() }; + const void* values[2] = { currentIndexNumber.get(), entries.get() }; + + return CFDictionaryCreate(0, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } bool WebBackForwardList::restoreFromCFDictionaryRepresentation(CFDictionaryRef dictionary) diff --git a/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp b/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp index 45e77df..02b864b 100644 --- a/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp +++ b/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp @@ -180,4 +180,48 @@ void WebPageProxy::restoreFromSessionStateData(WebData* webData) loadURL(provisionalURL); } +static RetainPtr<CFStringRef> autosaveKey(const String& name) +{ + String key = "com.apple.WebKit.searchField:" + name; + return RetainPtr<CFStringRef>(AdoptCF, key.createCFString()); +} + +void WebPageProxy::saveRecentSearches(const String& name, const Vector<String>& searchItems) +{ + // The WebProcess shouldn't have bothered to send this message if the name was empty. + ASSERT(!name.isEmpty()); + + RetainPtr<CFMutableArrayRef> items; + + if (size_t size = searchItems.size()) { + items.adoptCF(CFArrayCreateMutable(0, size, &kCFTypeArrayCallBacks)); + for (size_t i = 0; i < size; ++i) { + RetainPtr<CFStringRef> item(AdoptCF, searchItems[i].createCFString()); + CFArrayAppendValue(items.get(), item.get()); + } + } + + CFPreferencesSetAppValue(autosaveKey(name).get(), items.get(), kCFPreferencesCurrentApplication); + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +void WebPageProxy::loadRecentSearches(const String& name, Vector<String>& searchItems) +{ + // The WebProcess shouldn't have bothered to send this message if the name was empty. + ASSERT(!name.isEmpty()); + + searchItems.clear(); + RetainPtr<CFArrayRef> items(AdoptCF, reinterpret_cast<CFArrayRef>(CFPreferencesCopyAppValue(autosaveKey(name).get(), kCFPreferencesCurrentApplication))); + + if (!items || CFGetTypeID(items.get()) != CFArrayGetTypeID()) + return; + + size_t size = CFArrayGetCount(items.get()); + for (size_t i = 0; i < size; ++i) { + CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(items.get(), i); + if (CFGetTypeID(item) == CFStringGetTypeID()) + searchItems.append(item); + } +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/cf/WebPreferencesCF.cpp b/Source/WebKit2/UIProcess/cf/WebPreferencesCF.cpp index 1b7c2dc..5f6ca9d 100644 --- a/Source/WebKit2/UIProcess/cf/WebPreferencesCF.cpp +++ b/Source/WebKit2/UIProcess/cf/WebPreferencesCF.cpp @@ -26,28 +26,119 @@ #include "config.h" #include "WebPreferences.h" +#include <wtf/RetainPtr.h> +#include <wtf/text/StringConcatenate.h> + #if !PLATFORM(MAC) namespace WebKit { +static RetainPtr<CFStringRef> cfStringFromWebCoreString(const String& string) +{ + return RetainPtr<CFStringRef>(AdoptCF, CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(string.characters()), string.length())); +} + +static inline RetainPtr<CFStringRef> makeKey(const String& identifier, const String& baseKey) +{ + return cfStringFromWebCoreString(makeString(identifier, ".WebKit2", baseKey)); +} + +static void setStringValueIfInUserDefaults(const String& identifier, const String& baseKey, WebPreferencesStore& store) +{ + RetainPtr<CFPropertyListRef> value(AdoptCF, CFPreferencesCopyAppValue(makeKey(identifier, baseKey).get(), kCFPreferencesCurrentApplication)); + if (!value) + return; + if (CFGetTypeID(value.get()) != CFStringGetTypeID()) + return; + + store.setStringValueForKey(baseKey, (CFStringRef)value.get()); +} + +static void setBoolValueIfInUserDefaults(const String& identifier, const String& baseKey, WebPreferencesStore& store) +{ + RetainPtr<CFPropertyListRef> value(AdoptCF, CFPreferencesCopyAppValue(makeKey(identifier, baseKey).get(), kCFPreferencesCurrentApplication)); + if (!value) + return; + if (CFGetTypeID(value.get()) != CFBooleanGetTypeID()) + return; + + store.setBoolValueForKey(baseKey, CFBooleanGetValue((CFBooleanRef)value.get()) ? true : false); +} + +static void setUInt32ValueIfInUserDefaults(const String& identifier, const String& baseKey, WebPreferencesStore& store) +{ + RetainPtr<CFPropertyListRef> value(AdoptCF, CFPreferencesCopyAppValue(makeKey(identifier, baseKey).get(), kCFPreferencesCurrentApplication)); + if (!value) + return; + if (CFGetTypeID(value.get()) != CFNumberGetTypeID()) + return; + int32_t intValue = 0; + if (!CFNumberGetValue((CFNumberRef)value.get(), kCFNumberSInt32Type, &intValue)) + return; + + store.setUInt32ValueForKey(baseKey, intValue); +} + +static void setDoubleValueIfInUserDefaults(const String& identifier, const String& baseKey, WebPreferencesStore& store) +{ + RetainPtr<CFPropertyListRef> value(AdoptCF, CFPreferencesCopyAppValue(makeKey(identifier, baseKey).get(), kCFPreferencesCurrentApplication)); + if (!value) + return; + if (CFGetTypeID(value.get()) != CFNumberGetTypeID()) + return; + double doubleValue = 0; + if (!CFNumberGetValue((CFNumberRef)value.get(), kCFNumberDoubleType, &doubleValue)) + return; + + store.setDoubleValueForKey(baseKey, doubleValue); +} + void WebPreferences::platformInitializeStore() { + if (!m_identifier) + return; + +#define INITIALIZE_PREFERENCE_FROM_NSUSERDEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) \ + set##TypeName##ValueIfInUserDefaults(m_identifier, WebPreferencesKey::KeyLower##Key(), m_store); + + FOR_EACH_WEBKIT_PREFERENCE(INITIALIZE_PREFERENCE_FROM_NSUSERDEFAULTS) + +#undef INITIALIZE_PREFERENCE_FROM_NSUSERDEFAULTS + } -void WebPreferences::platformUpdateStringValueForKey(const String&, const String&) +void WebPreferences::platformUpdateStringValueForKey(const String& key, const String& value) { + if (!m_identifier) + return; + + CFPreferencesSetAppValue(makeKey(m_identifier, key).get(), cfStringFromWebCoreString(value).get(), kCFPreferencesCurrentApplication); } -void WebPreferences::platformUpdateBoolValueForKey(const String&, bool) +void WebPreferences::platformUpdateBoolValueForKey(const String& key, bool value) { + if (!m_identifier) + return; + + CFPreferencesSetAppValue(makeKey(m_identifier, key).get(), value ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); } -void WebPreferences::platformUpdateUInt32ValueForKey(const String&, uint32_t) +void WebPreferences::platformUpdateUInt32ValueForKey(const String& key, uint32_t value) { + if (!m_identifier) + return; + + RetainPtr<CFNumberRef> number(AdoptCF, CFNumberCreate(0, kCFNumberSInt32Type, &value)); + CFPreferencesSetAppValue(makeKey(m_identifier, key).get(), number.get(), kCFPreferencesCurrentApplication); } -void WebPreferences::platformUpdateDoubleValueForKey(const String&, double) +void WebPreferences::platformUpdateDoubleValueForKey(const String& key, double value) { + if (!m_identifier) + return; + + RetainPtr<CFNumberRef> number(AdoptCF, CFNumberCreate(0, kCFNumberDoubleType, &value)); + CFPreferencesSetAppValue(makeKey(m_identifier, key).get(), number.get(), kCFPreferencesCurrentApplication); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp index a5c708f..89a9ef7 100644 --- a/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp @@ -32,7 +32,7 @@ #include "UpdateChunk.h" #include "WebProcessProxy.h" #include "WebView.h" - +#include <WebCore/GtkVersioning.h> #include <gdk/gdk.h> using namespace WebCore; diff --git a/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp b/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp index 6a6715a..118bee1 100644 --- a/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp @@ -58,7 +58,7 @@ void TextChecker::setGrammarCheckingEnabled(bool isGrammarCheckingEnabled) notImplemented(); } -int64_t TextChecker::uniqueSpellDocumentTag() +int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy*) { notImplemented(); return 0; @@ -69,18 +69,33 @@ void TextChecker::closeSpellDocumentWithTag(int64_t) notImplemented(); } -Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, const UChar* text, int length, uint64_t checkingTypes) +void TextChecker::checkSpellingOfString(int64_t, const UChar*, uint32_t, int32_t&, int32_t&) { notImplemented(); - return Vector<WebCore::TextCheckingResult>(); } -void TextChecker::updateSpellingUIWithMisspelledWord(const String& misspelledWord) +void TextChecker::checkGrammarOfString(int64_t, const UChar*, uint32_t, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&) { notImplemented(); } -void TextChecker::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +bool TextChecker::spellingUIIsShowing() +{ + notImplemented(); + return false; +} + +void TextChecker::toggleSpellingUIIsShowing() +{ + notImplemented(); +} + +void TextChecker::updateSpellingUIWithMisspelledWord(int64_t, const String&) +{ + notImplemented(); +} + +void TextChecker::updateSpellingUIWithGrammarString(int64_t, const String&, const GrammarDetail&) { notImplemented(); } @@ -90,7 +105,7 @@ void TextChecker::getGuessesForWord(int64_t spellDocumentTag, const String& word notImplemented(); } -void TextChecker::learnWord(const String& word) +void TextChecker::learnWord(int64_t, const String&) { notImplemented(); } diff --git a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp index 838de97..8945d13 100644 --- a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp @@ -27,6 +27,10 @@ #include "config.h" #include "WebPageProxy.h" +#include "NativeWebKeyboardEvent.h" +#include "NotImplemented.h" +#include "PageClient.h" + namespace WebKit { String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent) @@ -35,4 +39,19 @@ String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent return "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.7 (KHTML, like Gecko) Version/5.0 Safari/534.7"; } +void WebPageProxy::getEditorCommandsForKeyEvent(Vector<WTF::String>& commandsList) +{ + m_pageClient->getEditorCommandsForKeyEvent(m_keyEventQueue.first(), commandsList); +} + +void WebPageProxy::saveRecentSearches(const String&, const Vector<String>&) +{ + notImplemented(); +} + +void WebPageProxy::loadRecentSearches(const String&, Vector<String>&) +{ + notImplemented(); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/gtk/WebView.cpp b/Source/WebKit2/UIProcess/gtk/WebView.cpp index 2ff67cd..aa45c62 100644 --- a/Source/WebKit2/UIProcess/gtk/WebView.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebView.cpp @@ -30,6 +30,7 @@ #include "ChunkedUpdateDrawingAreaProxy.h" #include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" #include "NotImplemented.h" #include "WebContext.h" #include "WebContextMenuProxy.h" @@ -38,11 +39,12 @@ #include "WebPageProxy.h" #include <wtf/text/WTFString.h> +typedef HashMap<int, const char*> IntConstCharHashMap; + using namespace WebCore; namespace WebKit { - void WebView::handleFocusInEvent(GtkWidget* widget) { if (!(m_isPageActive)) { @@ -59,8 +61,185 @@ void WebView::handleFocusOutEvent(GtkWidget* widget) m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive); } + +static void backspaceCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "backspace"); + client->addPendingEditorCommand("DeleteBackward"); +} + +static void selectAllCallback(GtkWidget* widget, gboolean select, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "select-all"); + client->addPendingEditorCommand(select ? "SelectAll" : "Unselect"); +} + +static void cutClipboardCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "cut-clipboard"); + client->addPendingEditorCommand("Cut"); +} + +static void copyClipboardCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "copy-clipboard"); + client->addPendingEditorCommand("Copy"); +} + +static void pasteClipboardCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "paste-clipboard"); + client->addPendingEditorCommand("Paste"); +} + +static void toggleOverwriteCallback(GtkWidget* widget, EditorClient*) +{ + // We don't support toggling the overwrite mode, but the default callback expects + // the GtkTextView to have a layout, so we handle this signal just to stop it. + g_signal_stop_emission_by_name(widget, "toggle-overwrite"); +} + +// GTK+ will still send these signals to the web view. So we can safely stop signal +// emission without breaking accessibility. +static void popupMenuCallback(GtkWidget* widget, EditorClient*) +{ + g_signal_stop_emission_by_name(widget, "popup-menu"); +} + +static void showHelpCallback(GtkWidget* widget, EditorClient*) +{ + g_signal_stop_emission_by_name(widget, "show-help"); +} + +static const char* const gtkDeleteCommands[][2] = { + { "DeleteBackward", "DeleteForward" }, // Characters + { "DeleteWordBackward", "DeleteWordForward" }, // Word ends + { "DeleteWordBackward", "DeleteWordForward" }, // Words + { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Lines + { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Line ends + { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraph ends + { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraphs + { 0, 0 } // Whitespace (M-\ in Emacs) +}; + +static void deleteFromCursorCallback(GtkWidget* widget, GtkDeleteType deleteType, gint count, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "delete-from-cursor"); + int direction = count > 0 ? 1 : 0; + + // Ensuring that deleteType <= G_N_ELEMENTS here results in a compiler warning + // that the condition is always true. + + if (deleteType == GTK_DELETE_WORDS) { + if (!direction) { + client->addPendingEditorCommand("MoveWordForward"); + client->addPendingEditorCommand("MoveWordBackward"); + } else { + client->addPendingEditorCommand("MoveWordBackward"); + client->addPendingEditorCommand("MoveWordForward"); + } + } else if (deleteType == GTK_DELETE_DISPLAY_LINES) { + if (!direction) + client->addPendingEditorCommand("MoveToBeginningOfLine"); + else + client->addPendingEditorCommand("MoveToEndOfLine"); + } else if (deleteType == GTK_DELETE_PARAGRAPHS) { + if (!direction) + client->addPendingEditorCommand("MoveToBeginningOfParagraph"); + else + client->addPendingEditorCommand("MoveToEndOfParagraph"); + } + + const char* rawCommand = gtkDeleteCommands[deleteType][direction]; + if (!rawCommand) + return; + + for (int i = 0; i < abs(count); i++) + client->addPendingEditorCommand(rawCommand); +} + +static const char* const gtkMoveCommands[][4] = { + { "MoveBackward", "MoveForward", + "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Forward/backward grapheme + { "MoveLeft", "MoveRight", + "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Left/right grapheme + { "MoveWordBackward", "MoveWordForward", + "MoveWordBackwardAndModifySelection", "MoveWordForwardAndModifySelection" }, // Forward/backward word + { "MoveUp", "MoveDown", + "MoveUpAndModifySelection", "MoveDownAndModifySelection" }, // Up/down line + { "MoveToBeginningOfLine", "MoveToEndOfLine", + "MoveToBeginningOfLineAndModifySelection", "MoveToEndOfLineAndModifySelection" }, // Up/down line ends + { "MoveParagraphForward", "MoveParagraphBackward", + "MoveParagraphForwardAndModifySelection", "MoveParagraphBackwardAndModifySelection" }, // Up/down paragraphs + { "MoveToBeginningOfParagraph", "MoveToEndOfParagraph", + "MoveToBeginningOfParagraphAndModifySelection", "MoveToEndOfParagraphAndModifySelection" }, // Up/down paragraph ends. + { "MovePageUp", "MovePageDown", + "MovePageUpAndModifySelection", "MovePageDownAndModifySelection" }, // Up/down page + { "MoveToBeginningOfDocument", "MoveToEndOfDocument", + "MoveToBeginningOfDocumentAndModifySelection", "MoveToEndOfDocumentAndModifySelection" }, // Begin/end of buffer + { 0, 0, + 0, 0 } // Horizontal page movement +}; + +static void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint count, gboolean extendSelection, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "move-cursor"); + int direction = count > 0 ? 1 : 0; + if (extendSelection) + direction += 2; + + if (static_cast<unsigned>(step) >= G_N_ELEMENTS(gtkMoveCommands)) + return; + + const char* rawCommand = gtkMoveCommands[step][direction]; + if (!rawCommand) + return; + + for (int i = 0; i < abs(count); i++) + client->addPendingEditorCommand(rawCommand); +} + +static const unsigned CtrlKey = 1 << 0; +static const unsigned AltKey = 1 << 1; +static const unsigned ShiftKey = 1 << 2; + +struct KeyDownEntry { + unsigned virtualKey; + unsigned modifiers; + const char* name; +}; + +struct KeyPressEntry { + unsigned charCode; + unsigned modifiers; + const char* name; +}; + +static const KeyDownEntry keyDownEntries[] = { + { 'B', CtrlKey, "ToggleBold" }, + { 'I', CtrlKey, "ToggleItalic" }, + { VK_ESCAPE, 0, "Cancel" }, + { VK_OEM_PERIOD, CtrlKey, "Cancel" }, + { VK_TAB, 0, "InsertTab" }, + { VK_TAB, ShiftKey, "InsertBacktab" }, + { VK_RETURN, 0, "InsertNewline" }, + { VK_RETURN, CtrlKey, "InsertNewline" }, + { VK_RETURN, AltKey, "InsertNewline" }, + { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, +}; + +static const KeyPressEntry keyPressEntries[] = { + { '\t', 0, "InsertTab" }, + { '\t', ShiftKey, "InsertBacktab" }, + { '\r', 0, "InsertNewline" }, + { '\r', CtrlKey, "InsertNewline" }, + { '\r', AltKey, "InsertNewline" }, + { '\r', AltKey | ShiftKey, "InsertNewline" }, +}; + WebView::WebView(WebContext* context, WebPageGroup* pageGroup) : m_isPageActive(true) + , m_nativeWidget(gtk_text_view_new()) { m_page = context->createWebPage(this, pageGroup); @@ -71,6 +250,17 @@ WebView::WebView(WebContext* context, WebPageGroup* pageGroup) WebViewWidget* webViewWidget = WEB_VIEW_WIDGET(m_viewWidget); webViewWidgetSetWebViewInstance(webViewWidget, this); + + g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this); + g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this); + g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this); + g_signal_connect(m_nativeWidget.get(), "paste-clipboard", G_CALLBACK(pasteClipboardCallback), this); + g_signal_connect(m_nativeWidget.get(), "select-all", G_CALLBACK(selectAllCallback), this); + g_signal_connect(m_nativeWidget.get(), "move-cursor", G_CALLBACK(moveCursorCallback), this); + g_signal_connect(m_nativeWidget.get(), "delete-from-cursor", G_CALLBACK(deleteFromCursorCallback), this); + g_signal_connect(m_nativeWidget.get(), "toggle-overwrite", G_CALLBACK(toggleOverwriteCallback), this); + g_signal_connect(m_nativeWidget.get(), "popup-menu", G_CALLBACK(popupMenuCallback), this); + g_signal_connect(m_nativeWidget.get(), "show-help", G_CALLBACK(showHelpCallback), this); } WebView::~WebView() @@ -99,7 +289,7 @@ void WebView::handleKeyboardEvent(GdkEventKey* event) void WebView::handleMouseEvent(GdkEvent* event, int currentClickCount) { - m_page->handleMouseEvent(WebEventFactory::createWebMouseEvent(event, currentClickCount)); + m_page->handleMouseEvent(NativeWebMouseEvent(event, currentClickCount)); } void WebView::handleWheelEvent(GdkEventScroll* event) @@ -107,6 +297,52 @@ void WebView::handleWheelEvent(GdkEventScroll* event) m_page->handleWheelEvent(WebEventFactory::createWebWheelEvent(event)); } +void WebView::getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent& event, Vector<WTF::String>& commandList) +{ + m_pendingEditorCommands.clear(); + +#ifdef GTK_API_VERSION_2 + gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key)); +#else + gtk_bindings_activate_event(G_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key)); +#endif + + if (m_pendingEditorCommands.isEmpty()) { + commandList.append(m_pendingEditorCommands); + return; + } + + DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyDownCommandsMap, ()); + DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyPressCommandsMap, ()); + + if (keyDownCommandsMap.isEmpty()) { + for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++) + keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); + + for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++) + keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); + } + + unsigned modifiers = 0; + if (event.shiftKey()) + modifiers |= ShiftKey; + if (event.altKey()) + modifiers |= AltKey; + if (event.controlKey()) + modifiers |= CtrlKey; + + // For keypress events, we want charCode(), but keyCode() does that. + int mapKey = modifiers << 16 | event.nativeVirtualKeyCode(); + if (mapKey) { + HashMap<int, const char*>* commandMap = event.type() == WebEvent::KeyDown ? + &keyDownCommandsMap : &keyPressCommandsMap; + if (const char* commandString = commandMap->get(mapKey)) + m_pendingEditorCommands.append(commandString); + } + + commandList.append(m_pendingEditorCommands); +} + bool WebView::isActive() { return m_isPageActive; @@ -179,11 +415,6 @@ void WebView::didRelaunchProcess() notImplemented(); } -void WebView::setFocus(bool) -{ - notImplemented(); -} - void WebView::takeFocus(bool) { notImplemented(); @@ -222,6 +453,17 @@ void WebView::clearAllEditCommands() notImplemented(); } +bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo) +{ + notImplemented(); + return false; +} + +void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo) +{ + notImplemented(); +} + FloatRect WebView::convertToDeviceSpace(const FloatRect& viewRect) { notImplemented(); @@ -312,5 +554,14 @@ void WebView::flashBackingStoreUpdates(const Vector<IntRect>&) notImplemented(); } +void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned) +{ + notImplemented(); +} + +void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned) +{ + notImplemented(); +} } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/gtk/WebView.h b/Source/WebKit2/UIProcess/gtk/WebView.h index 6c281ed..6cef14c 100644 --- a/Source/WebKit2/UIProcess/gtk/WebView.h +++ b/Source/WebKit2/UIProcess/gtk/WebView.h @@ -30,6 +30,7 @@ #include "PageClient.h" #include "WebPageProxy.h" +#include "WindowsKeyboardCodes.h" #include <WebCore/IntSize.h> #include <gdk/gdk.h> #include <glib.h> @@ -64,6 +65,8 @@ public: void handleWheelEvent(GdkEventScroll*); void handleMouseEvent(GdkEvent*, int); + void addPendingEditorCommand(const char* command) { m_pendingEditorCommands.append(WTF::String(command)); } + private: WebView(WebContext*, WebPageGroup*); @@ -85,13 +88,14 @@ private: virtual void processDidCrash(); virtual void didRelaunchProcess(); virtual void pageClosed(); - virtual void setFocus(bool focused); virtual void takeFocus(bool direction); virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void setCursor(const WebCore::Cursor&); virtual void setViewportArguments(const WebCore::ViewportArguments&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); + virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); + virtual void executeUndoRedo(WebPageProxy::UndoOrRedo); virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&); @@ -103,6 +107,9 @@ private: virtual void didChangeScrollbarsForMainFrame() const; virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects); virtual float userSpaceScaleFactor() const { return 1; } + virtual void getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent&, Vector<WTF::String>&); + virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned); + virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned); #if USE(ACCELERATED_COMPOSITING) virtual void pageDidEnterAcceleratedCompositing(); @@ -118,6 +125,8 @@ private: GtkWidget* m_viewWidget; bool m_isPageActive; RefPtr<WebPageProxy> m_page; + Vector<WTF::String> m_pendingEditorCommands; + GRefPtr<GtkWidget> m_nativeWidget; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/mac/CorrectionPanel.h b/Source/WebKit2/UIProcess/mac/CorrectionPanel.h index d4bc353..85a98ef 100644 --- a/Source/WebKit2/UIProcess/mac/CorrectionPanel.h +++ b/Source/WebKit2/UIProcess/mac/CorrectionPanel.h @@ -27,8 +27,8 @@ #define CorrectionPanel_h #if !defined(BUILDING_ON_SNOW_LEOPARD) -#import <AppKit/NSTextChecker.h> -#import <WebCore/CorrectionPanelInfo.h> +#import <AppKit/NSSpellChecker.h> +#import <WebCore/SpellingCorrectionController.h> #import <wtf/RetainPtr.h> @class WKView; @@ -47,7 +47,7 @@ public: private: bool isShowing() const { return m_view; } void dismissInternal(WebCore::ReasonForDismissingCorrectionPanel, bool dismissingExternally); - void handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionBubbleType); + void handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionIndicatorType); bool m_wasDismissedExternally; WebCore::ReasonForDismissingCorrectionPanel m_reasonForDismissing; diff --git a/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm b/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm index ab6818f..0fc520b 100644 --- a/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm +++ b/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm @@ -33,18 +33,18 @@ using namespace WebCore; -static inline NSCorrectionBubbleType correctionBubbleType(CorrectionPanelInfo::PanelType panelType) +static inline NSCorrectionIndicatorType correctionIndicatorType(CorrectionPanelInfo::PanelType panelType) { switch (panelType) { case CorrectionPanelInfo::PanelTypeCorrection: - return NSCorrectionBubbleTypeCorrection; + return NSCorrectionIndicatorTypeDefault; case CorrectionPanelInfo::PanelTypeReversion: - return NSCorrectionBubbleTypeReversion; + return NSCorrectionIndicatorTypeReversion; case CorrectionPanelInfo::PanelTypeSpellingSuggestions: - return NSCorrectionBubbleTypeGuesses; + return NSCorrectionIndicatorTypeGuesses; } ASSERT_NOT_REACHED(); - return NSCorrectionBubbleTypeCorrection; + return NSCorrectionIndicatorTypeDefault; } namespace WebKit { @@ -71,7 +71,7 @@ void CorrectionPanel::show(WKView* view, CorrectionPanelInfo::PanelType type, co NSString* replacedStringAsNSString = replacedString; NSString* replacementStringAsNSString = replacementString; m_view = view; - NSCorrectionBubbleType bubbleType = correctionBubbleType(type); + NSCorrectionIndicatorType indicatorType = correctionIndicatorType(type); NSMutableArray* alternativeStrings = 0; if (!alternativeReplacementStrings.isEmpty()) { @@ -82,8 +82,8 @@ void CorrectionPanel::show(WKView* view, CorrectionPanelInfo::PanelType type, co } NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker]; - [spellChecker showCorrectionBubbleOfType:bubbleType primaryString:replacementStringAsNSString alternativeStrings:alternativeStrings forStringInRect:boundingBoxOfReplacedString view:m_view.get() completionHandler:^(NSString* acceptedString) { - handleAcceptedReplacement(acceptedString, replacedStringAsNSString, replacementStringAsNSString, bubbleType); + [spellChecker showCorrectionIndicatorOfType:indicatorType primaryString:replacementStringAsNSString alternativeStrings:alternativeStrings forStringInRect:boundingBoxOfReplacedString view:m_view.get() completionHandler:^(NSString* acceptedString) { + handleAcceptedReplacement(acceptedString, replacedStringAsNSString, replacementStringAsNSString, indicatorType); }]; } @@ -113,7 +113,7 @@ void CorrectionPanel::dismissInternal(ReasonForDismissingCorrectionPanel reason, m_reasonForDismissing = reason; m_resultForSynchronousDismissal.clear(); - [[NSSpellChecker sharedSpellChecker] dismissCorrectionBubbleForView:m_view.get()]; + [[NSSpellChecker sharedSpellChecker] dismissCorrectionIndicatorForView:m_view.get()]; m_view.clear(); } @@ -122,13 +122,13 @@ void CorrectionPanel::recordAutocorrectionResponse(WKView* view, NSCorrectionRes [[NSSpellChecker sharedSpellChecker] recordResponse:response toCorrection:replacementString forWord:replacedString language:nil inSpellDocumentWithTag:[view spellCheckerDocumentTag]]; } -void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionBubbleType correctionBubbleType) +void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionIndicatorType correctionIndicatorType) { NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker]; NSInteger documentTag = [m_view.get() spellCheckerDocumentTag]; - switch (correctionBubbleType) { - case NSCorrectionBubbleTypeCorrection: + switch (correctionIndicatorType) { + case NSCorrectionIndicatorTypeDefault: if (acceptedReplacement) [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag]; else { @@ -138,11 +138,11 @@ void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, N [spellChecker recordResponse:NSCorrectionResponseIgnored toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag]; } break; - case NSCorrectionBubbleTypeReversion: + case NSCorrectionIndicatorTypeReversion: if (acceptedReplacement) [spellChecker recordResponse:NSCorrectionResponseReverted toCorrection:replaced forWord:acceptedReplacement language:nil inSpellDocumentWithTag:documentTag]; break; - case NSCorrectionBubbleTypeGuesses: + case NSCorrectionIndicatorTypeGuesses: if (acceptedReplacement) [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag]; break; diff --git a/Source/WebKit2/UIProcess/mac/TextCheckerMac.mm b/Source/WebKit2/UIProcess/mac/TextCheckerMac.mm index cef3a55..29493f9 100644 --- a/Source/WebKit2/UIProcess/mac/TextCheckerMac.mm +++ b/Source/WebKit2/UIProcess/mac/TextCheckerMac.mm @@ -27,10 +27,13 @@ #import "TextChecker.h" #import "TextCheckerState.h" +#import <WebCore/NotImplemented.h> #import <wtf/RetainPtr.h> #ifndef BUILDING_ON_SNOW_LEOPARD -#import <AppKit/NSTextChecker.h> +@interface NSSpellChecker (WebNSSpellCheckerDetails) +- (NSString *)languageForWordRange:(NSRange)range inString:(NSString *)string orthography:(NSOrthography *)orthography; +@end #endif static NSString* const WebAutomaticSpellingCorrectionEnabled = @"WebAutomaticSpellingCorrectionEnabled"; @@ -195,7 +198,22 @@ void TextChecker::setSmartInsertDeleteEnabled(bool flag) [[NSUserDefaults standardUserDefaults] setBool:flag forKey:WebSmartInsertDeleteEnabled]; } -int64_t TextChecker::uniqueSpellDocumentTag() +bool TextChecker::substitutionsPanelIsShowing() +{ + return [[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible]; +} + +void TextChecker::toggleSubstitutionsPanelIsShowing() +{ + NSPanel *substitutionsPanel = [[NSSpellChecker sharedSpellChecker] substitutionsPanel]; + if ([substitutionsPanel isVisible]) { + [substitutionsPanel orderOut:nil]; + return; + } + [substitutionsPanel orderFront:nil]; +} + +int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy*) { return [NSSpellChecker uniqueSpellDocumentTag]; } @@ -205,6 +223,8 @@ void TextChecker::closeSpellDocumentWithTag(int64_t tag) [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:tag]; } +#if USE(UNIFIED_TEXT_CHECKING) + Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, const UChar* text, int length, uint64_t checkingTypes) { Vector<TextCheckingResult> results; @@ -292,12 +312,40 @@ Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocume return results; } -void TextChecker::updateSpellingUIWithMisspelledWord(const String& misspelledWord) +#endif + +void TextChecker::checkSpellingOfString(int64_t, const UChar*, uint32_t, int32_t&, int32_t&) +{ + // Mac uses checkTextOfParagraph instead. + notImplemented(); +} + +void TextChecker::checkGrammarOfString(int64_t, const UChar*, uint32_t, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&) +{ + // Mac uses checkTextOfParagraph instead. + notImplemented(); +} + +bool TextChecker::spellingUIIsShowing() +{ + return [[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible]; +} + +void TextChecker::toggleSpellingUIIsShowing() +{ + NSPanel *spellingPanel = [[NSSpellChecker sharedSpellChecker] spellingPanel]; + if ([spellingPanel isVisible]) + [spellingPanel orderOut:nil]; + else + [spellingPanel orderFront:nil]; +} + +void TextChecker::updateSpellingUIWithMisspelledWord(int64_t, const String& misspelledWord) { [[NSSpellChecker sharedSpellChecker] updateSpellingPanelWithMisspelledWord:misspelledWord]; } -void TextChecker::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +void TextChecker::updateSpellingUIWithGrammarString(int64_t, const String& badGrammarPhrase, const GrammarDetail& grammarDetail) { RetainPtr<NSMutableArray> corrections(AdoptNS, [[NSMutableArray alloc] init]); for (size_t i = 0; i < grammarDetail.guesses.size(); ++i) { @@ -307,7 +355,7 @@ void TextChecker::updateSpellingUIWithGrammarString(const String& badGrammarPhra NSRange grammarRange = NSMakeRange(grammarDetail.location, grammarDetail.length); NSString *grammarUserDescription = grammarDetail.userDescription; - RetainPtr<NSMutableDictionary> grammarDetailDict(AdoptNS, [[NSDictionary alloc] initWithObjectsAndKeys:[NSValue valueWithRange:grammarRange], NSGrammarRange, grammarUserDescription, NSGrammarUserDescription, corrections.get(), NSGrammarCorrections, nil]); + RetainPtr<NSDictionary> grammarDetailDict(AdoptNS, [[NSDictionary alloc] initWithObjectsAndKeys:[NSValue valueWithRange:grammarRange], NSGrammarRange, grammarUserDescription, NSGrammarUserDescription, corrections.get(), NSGrammarCorrections, nil]); [[NSSpellChecker sharedSpellChecker] updateSpellingPanelWithGrammarString:badGrammarPhrase detail:grammarDetailDict.get()]; } @@ -331,7 +379,7 @@ void TextChecker::getGuessesForWord(int64_t spellDocumentTag, const String& word guesses.append(guess); } -void TextChecker::learnWord(const String& word) +void TextChecker::learnWord(int64_t, const String& word) { [[NSSpellChecker sharedSpellChecker] learnWord:word]; } diff --git a/Source/WebKit2/UIProcess/mac/WebContextMac.mm b/Source/WebKit2/UIProcess/mac/WebContextMac.mm index f7c186d..e770d5b 100644 --- a/Source/WebKit2/UIProcess/mac/WebContextMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebContextMac.mm @@ -84,12 +84,11 @@ void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& para NSURLCache *urlCache = [NSURLCache sharedURLCache]; parameters.parentProcessName = [[NSProcessInfo processInfo] processName]; - parameters.nsURLCachePath = fileSystemRepresentation([(NSString *)cachePath.get() stringByStandardizingPath]); + parameters.nsURLCachePath = [(NSString *)cachePath.get() stringByStandardizingPath]; parameters.nsURLCacheMemoryCapacity = [urlCache memoryCapacity]; parameters.nsURLCacheDiskCapacity = [urlCache diskCapacity]; - ASSERT(strlen(parameters.nsURLCachePath.data())); - ASSERT(parameters.nsURLCachePath.data()[strlen(parameters.nsURLCachePath.data()) - 1] != '/'); // Necessary for NSURLCache to find the cache file. + ASSERT(!parameters.nsURLCachePath.isEmpty()); #if USE(ACCELERATED_COMPOSITING) && HAVE(HOSTED_CORE_ANIMATION) mach_port_t renderServerPort = WKInitializeRenderServer(); @@ -98,7 +97,7 @@ void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& para #endif // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle. - parameters.uiProcessBundleResourcePath = fileSystemRepresentation([[NSBundle mainBundle] resourcePath]); + parameters.uiProcessBundleResourcePath = [[NSBundle mainBundle] resourcePath]; #if USE(CFURLSTORAGESESSIONS) parameters.uiProcessBundleIdentifier = String([[NSBundle mainBundle] bundleIdentifier]); diff --git a/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm index d533573..33238b0 100644 --- a/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm @@ -23,11 +23,13 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "WebFullScreenManagerProxy.h" -#include "LayerTreeContext.h" -#include "WKFullScreenWindowController.h" -#include "WKViewInternal.h" +#import "config.h" +#import "WebFullScreenManagerProxy.h" + +#import "LayerTreeContext.h" +#import "WKFullScreenWindowController.h" +#import "WKViewInternal.h" +#import <WebCore/IntRect.h> #if ENABLE(FULLSCREEN_API) diff --git a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm index 9657764..e406166 100644 --- a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm @@ -31,6 +31,7 @@ #import "WKAPICast.h" #import "WKView.h" #import "WebPageProxy.h" +#import "WebProcessProxy.h" #import <WebKitSystemInterface.h> #import <WebCore/LocalizedStrings.h> #import <wtf/text/WTFString.h> @@ -80,7 +81,7 @@ WebPageProxy* WebInspectorProxy::platformCreateInspectorPage() ASSERT(m_page); ASSERT(!m_inspectorView); - m_inspectorView.adoptNS([[WKView alloc] initWithFrame:NSZeroRect contextRef:toAPI(page()->context()) pageGroupRef:toAPI(inspectorPageGroup())]); + m_inspectorView.adoptNS([[WKView alloc] initWithFrame:NSZeroRect contextRef:toAPI(page()->process()->context()) pageGroupRef:toAPI(inspectorPageGroup())]); ASSERT(m_inspectorView); [m_inspectorView.get() setDrawsBackground:NO]; @@ -135,7 +136,7 @@ void WebInspectorProxy::platformClose() void WebInspectorProxy::platformInspectedURLChanged(const String& urlString) { - NSString *title = [NSString stringWithFormat:UI_STRING("Web Inspector — %@", "Web Inspector window title"), (NSString *)urlString]; + NSString *title = [NSString stringWithFormat:WEB_UI_STRING("Web Inspector — %@", "Web Inspector window title"), (NSString *)urlString]; [m_inspectorWindow.get() setTitle:title]; } diff --git a/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm index 90df81e..9dacae5 100644 --- a/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm @@ -26,10 +26,13 @@ #import "config.h" #import "WebPageProxy.h" +#import "AttributedString.h" #import "DataReference.h" #import "DictionaryPopupInfo.h" +#import "EditorState.h" #import "NativeWebKeyboardEvent.h" #import "PageClient.h" +#import "PageClientImpl.h" #import "TextChecker.h" #import "WebPageMessages.h" #import "WebProcessProxy.h" @@ -105,8 +108,7 @@ void WebPageProxy::getIsSpeaking(bool& isSpeaking) void WebPageProxy::speak(const String& string) { - NSString *convertedString = string; - [NSApp speakString:convertedString]; + [NSApp speakString:nsStringFromWebCoreString(string)]; } void WebPageProxy::stopSpeaking() @@ -114,6 +116,11 @@ void WebPageProxy::stopSpeaking() [NSApp stopSpeaking:nil]; } +void WebPageProxy::searchWithSpotlight(const String& string) +{ + [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:nsStringFromWebCoreString(string)]; +} + CGContextRef WebPageProxy::containingWindowGraphicsContext() { return m_pageClient->containingWindowGraphicsContext(); @@ -134,11 +141,38 @@ void WebPageProxy::windowAndViewFramesChanged(const IntRect& windowFrameInScreen process()->send(Messages::WebPage::WindowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates, accessibilityViewCoordinates), m_pageID); } +void WebPageProxy::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) +{ + process()->sendSync(Messages::WebPage::SetComposition(text, underlines, selectionStart, selectionEnd, replacementRangeStart, replacementRangeEnd), Messages::WebPage::SetComposition::Reply(m_editorState), m_pageID); +} + +void WebPageProxy::confirmComposition() +{ + process()->sendSync(Messages::WebPage::ConfirmComposition(), Messages::WebPage::ConfirmComposition::Reply(m_editorState), m_pageID); +} + +bool WebPageProxy::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) +{ + bool handled; + process()->sendSync(Messages::WebPage::InsertText(text, replacementRangeStart, replacementRangeEnd), Messages::WebPage::InsertText::Reply(handled, m_editorState), m_pageID); + return handled; +} + void WebPageProxy::getMarkedRange(uint64_t& location, uint64_t& length) { process()->sendSync(Messages::WebPage::GetMarkedRange(), Messages::WebPage::GetMarkedRange::Reply(location, length), m_pageID); } - + +void WebPageProxy::getSelectedRange(uint64_t& location, uint64_t& length) +{ + process()->sendSync(Messages::WebPage::GetSelectedRange(), Messages::WebPage::GetSelectedRange::Reply(location, length), m_pageID); +} + +void WebPageProxy::getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString& result) +{ + process()->sendSync(Messages::WebPage::GetAttributedSubstringFromRange(location, length), Messages::WebPage::GetAttributedSubstringFromRange::Reply(result), m_pageID); +} + uint64_t WebPageProxy::characterIndexForPoint(const IntPoint point) { uint64_t result; @@ -152,20 +186,27 @@ WebCore::IntRect WebPageProxy::firstRectForCharacterRange(uint64_t location, uin process()->sendSync(Messages::WebPage::FirstRectForCharacterRange(location, length), Messages::WebPage::FirstRectForCharacterRange::Reply(resultRect), m_pageID); return resultRect; } - + +bool WebPageProxy::executeKeypressCommands(const Vector<WebCore::KeypressCommand>& commands) +{ + bool result; + process()->sendSync(Messages::WebPage::ExecuteKeypressCommands(commands), Messages::WebPage::ExecuteKeypressCommands::Reply(result, m_editorState), m_pageID); + return result; +} + bool WebPageProxy::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes) { bool result; - const double MessageTimeout = 20; - process()->sendSync(Messages::WebPage::WriteSelectionToPasteboard(pasteboardName, pasteboardTypes), Messages::WebPage::WriteSelectionToPasteboard::Reply(result), m_pageID, MessageTimeout); + const double messageTimeout = 20; + process()->sendSync(Messages::WebPage::WriteSelectionToPasteboard(pasteboardName, pasteboardTypes), Messages::WebPage::WriteSelectionToPasteboard::Reply(result), m_pageID, messageTimeout); return result; } bool WebPageProxy::readSelectionFromPasteboard(const String& pasteboardName) { bool result; - const double MessageTimeout = 20; - process()->sendSync(Messages::WebPage::ReadSelectionFromPasteboard(pasteboardName), Messages::WebPage::ReadSelectionFromPasteboard::Reply(result), m_pageID, MessageTimeout); + const double messageTimeout = 20; + process()->sendSync(Messages::WebPage::ReadSelectionFromPasteboard(pasteboardName), Messages::WebPage::ReadSelectionFromPasteboard::Reply(result), m_pageID, messageTimeout); return result; } @@ -186,9 +227,10 @@ void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint& process()->send(Messages::WebPage::PerformDictionaryLookupAtLocation(point), m_pageID); } -void WebPageProxy::interpretKeyEvent(uint32_t type, Vector<KeypressCommand>& commandsList, uint32_t selectionStart, uint32_t selectionEnd, Vector<CompositionUnderline>& underlines) +void WebPageProxy::interpretQueuedKeyEvent(const EditorState& state, bool& handled, Vector<WebCore::KeypressCommand>& commands) { - m_pageClient->interceptKeyEvent(m_keyEventQueue.first(), commandsList, selectionStart, selectionEnd, underlines); + m_editorState = state; + handled = m_pageClient->interpretKeyEvent(m_keyEventQueue.first(), commands); } // Complex text input support for plug-ins. @@ -248,4 +290,25 @@ void WebPageProxy::setComplexTextInputEnabled(uint64_t pluginComplexTextInputIde m_pageClient->setComplexTextInputEnabled(pluginComplexTextInputIdentifier, complexTextInputEnabled); } +void WebPageProxy::executeSavedCommandBySelector(const String& selector, bool& handled) +{ + handled = m_pageClient->executeSavedCommandBySelector(selector); +} + +bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent& event) +{ + bool result = false; + const double messageTimeout = 3; + process()->sendSync(Messages::WebPage::ShouldDelayWindowOrderingEvent(event), Messages::WebPage::ShouldDelayWindowOrderingEvent::Reply(result), m_pageID, messageTimeout); + return result; +} + +bool WebPageProxy::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event) +{ + bool result = false; + const double messageTimeout = 3; + process()->sendSync(Messages::WebPage::AcceptsFirstMouse(eventNumber, event), Messages::WebPage::AcceptsFirstMouse::Reply(result), m_pageID, messageTimeout); + return result; +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm index 7ce8764..d13a2a7 100644 --- a/Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm @@ -26,6 +26,7 @@ #import "config.h" #import "WebPopupMenuProxyMac.h" +#import "NativeWebMouseEvent.h" #import "PageClientImpl.h" #import "PlatformPopupMenuData.h" #import "WKView.h" @@ -61,7 +62,7 @@ void WebPopupMenuProxyMac::populate(const Vector<WebPopupItem>& items, NSFont *f int size = items.size(); for (int i = 0; i < size; i++) { - if (items[i].m_type == WebPopupItem::Seperator) + if (items[i].m_type == WebPopupItem::Separator) [[m_popup.get() menu] addItem:[NSMenuItem separatorItem]]; else { [m_popup.get() addItemWithTitle:@""]; @@ -108,11 +109,20 @@ void WebPopupMenuProxyMac::showPopupMenu(const IntRect& rect, TextDirection text // These values were borrowed from AppKit to match their placement of the menu. const int popOverHorizontalAdjust = -10; - NSRect titleFrame = [m_popup.get() titleRectForBounds:rect]; - if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0) - titleFrame = rect; - float vertOffset = roundf((NSMaxY(rect) - NSMaxY(titleFrame)) + NSHeight(titleFrame)); - NSPoint location = NSMakePoint(NSMinX(rect) + popOverHorizontalAdjust, NSMaxY(rect) - vertOffset); + const int popUnderHorizontalAdjust = 6; + const int popUnderVerticalAdjust = 6; + + // Menus that pop-over directly obscure the node that generated the popup menu. + // Menus that pop-under are offset underneath it. + NSPoint location; + if (data.shouldPopOver) { + NSRect titleFrame = [m_popup.get() titleRectForBounds:rect]; + if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0) + titleFrame = rect; + float vertOffset = roundf((NSMaxY(rect) - NSMaxY(titleFrame)) + NSHeight(titleFrame)); + location = NSMakePoint(NSMinX(rect) + popOverHorizontalAdjust, NSMaxY(rect) - vertOffset); + } else + location = NSMakePoint(NSMinX(rect) + popUnderHorizontalAdjust, NSMaxY(rect) + popUnderVerticalAdjust); RetainPtr<NSView> dummyView(AdoptNS, [[NSView alloc] initWithFrame:rect]); [m_webView addSubview:dummyView.get()]; @@ -122,9 +132,41 @@ void WebPopupMenuProxyMac::showPopupMenu(const IntRect& rect, TextDirection text [m_popup.get() dismissPopUp]; [dummyView.get() removeFromSuperview]; - - if (m_client) - m_client->valueChangedForPopupMenu(this, [m_popup.get() indexOfSelectedItem]); + + if (!m_client) + return; + + m_client->valueChangedForPopupMenu(this, [m_popup.get() indexOfSelectedItem]); + + // <https://bugs.webkit.org/show_bug.cgi?id=57904> This code is adopted from EventHandler::sendFakeEventsAfterWidgetTracking(). + if (!m_client->currentlyProcessedMouseDownEvent()) + return; + + NSEvent* initiatingNSEvent = m_client->currentlyProcessedMouseDownEvent()->nativeEvent(); + if ([initiatingNSEvent type] != NSLeftMouseDown) + return; + + NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSLeftMouseUp + location:[initiatingNSEvent locationInWindow] + modifierFlags:[initiatingNSEvent modifierFlags] + timestamp:[initiatingNSEvent timestamp] + windowNumber:[initiatingNSEvent windowNumber] + context:[initiatingNSEvent context] + eventNumber:[initiatingNSEvent eventNumber] + clickCount:[initiatingNSEvent clickCount] + pressure:[initiatingNSEvent pressure]]; + + [NSApp postEvent:fakeEvent atStart:YES]; + fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved + location:[[m_webView window] convertScreenToBase:[NSEvent mouseLocation]] + modifierFlags:[initiatingNSEvent modifierFlags] + timestamp:[initiatingNSEvent timestamp] + windowNumber:[initiatingNSEvent windowNumber] + context:[initiatingNSEvent context] + eventNumber:0 + clickCount:0 + pressure:0]; + [NSApp postEvent:fakeEvent atStart:YES]; } void WebPopupMenuProxyMac::hidePopupMenu() diff --git a/Source/WebKit2/UIProcess/qt/TextCheckerQt.cpp b/Source/WebKit2/UIProcess/qt/TextCheckerQt.cpp index a28b867..2582cc2 100644 --- a/Source/WebKit2/UIProcess/qt/TextCheckerQt.cpp +++ b/Source/WebKit2/UIProcess/qt/TextCheckerQt.cpp @@ -59,7 +59,7 @@ void TextChecker::setGrammarCheckingEnabled(bool isGrammarCheckingEnabled) notImplemented(); } -int64_t TextChecker::uniqueSpellDocumentTag() +int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy*) { notImplemented(); return 0; @@ -70,18 +70,33 @@ void TextChecker::closeSpellDocumentWithTag(int64_t) notImplemented(); } -Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, const UChar* text, int length, uint64_t checkingTypes) +void TextChecker::checkSpellingOfString(int64_t, const UChar*, uint32_t, int32_t&, int32_t&) { notImplemented(); - return Vector<WebCore::TextCheckingResult>(); } -void TextChecker::updateSpellingUIWithMisspelledWord(const String& misspelledWord) +void TextChecker::checkGrammarOfString(int64_t, const UChar*, uint32_t, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&) { notImplemented(); } -void TextChecker::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +bool TextChecker::spellingUIIsShowing() +{ + notImplemented(); + return false; +} + +void TextChecker::toggleSpellingUIIsShowing() +{ + notImplemented(); +} + +void TextChecker::updateSpellingUIWithMisspelledWord(int64_t, const String&) +{ + notImplemented(); +} + +void TextChecker::updateSpellingUIWithGrammarString(int64_t, const String&, const GrammarDetail&) { notImplemented(); } @@ -91,7 +106,7 @@ void TextChecker::getGuessesForWord(int64_t spellDocumentTag, const String& word notImplemented(); } -void TextChecker::learnWord(const String& word) +void TextChecker::learnWord(int64_t, const String&) { notImplemented(); } diff --git a/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp index d6e8639..615cd8d 100644 --- a/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "WebPageProxy.h" +#include <WebCore/NotImplemented.h> + namespace WebKit { String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent) @@ -34,4 +36,14 @@ String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent return "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6) AppleWebKit/531.4 (KHTML, like Gecko) Version/4.0.3 Safari/531.4"; } +void WebPageProxy::saveRecentSearches(const String&, const Vector<String>&) +{ + notImplemented(); +} + +void WebPageProxy::loadRecentSearches(const String&, Vector<String>&) +{ + notImplemented(); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/TextCheckerWin.cpp b/Source/WebKit2/UIProcess/win/TextCheckerWin.cpp index dbc6fdc..9f7c766 100644 --- a/Source/WebKit2/UIProcess/win/TextCheckerWin.cpp +++ b/Source/WebKit2/UIProcess/win/TextCheckerWin.cpp @@ -27,6 +27,7 @@ #include "TextChecker.h" #include "TextCheckerState.h" +#include "WebTextChecker.h" #include <WebCore/NotImplemented.h> using namespace WebCore; @@ -37,68 +38,103 @@ static TextCheckerState textCheckerState; const TextCheckerState& TextChecker::state() { - notImplemented(); + static bool didInitializeState; + if (didInitializeState) + return textCheckerState; + + WebTextCheckerClient& client = WebTextChecker::shared()->client(); + textCheckerState.isContinuousSpellCheckingEnabled = client.continuousSpellCheckingEnabled(); + textCheckerState.isGrammarCheckingEnabled = client.grammarCheckingEnabled(); + + didInitializeState = true; return textCheckerState; } bool TextChecker::isContinuousSpellCheckingAllowed() { - notImplemented(); - - return false; + return WebTextChecker::shared()->client().continuousSpellCheckingAllowed(); } void TextChecker::setContinuousSpellCheckingEnabled(bool isContinuousSpellCheckingEnabled) { - notImplemented(); + if (state().isContinuousSpellCheckingEnabled == isContinuousSpellCheckingEnabled) + return; + textCheckerState.isContinuousSpellCheckingEnabled = isContinuousSpellCheckingEnabled; + WebTextChecker::shared()->client().setContinuousSpellCheckingEnabled(isContinuousSpellCheckingEnabled); } void TextChecker::setGrammarCheckingEnabled(bool isGrammarCheckingEnabled) { - notImplemented(); + if (state().isGrammarCheckingEnabled == isGrammarCheckingEnabled) + return; + textCheckerState.isGrammarCheckingEnabled = isGrammarCheckingEnabled; + WebTextChecker::shared()->client().setGrammarCheckingEnabled(isGrammarCheckingEnabled); +} + +void TextChecker::continuousSpellCheckingEnabledStateChanged(bool enabled) +{ + textCheckerState.isContinuousSpellCheckingEnabled = enabled; +} + +void TextChecker::grammarCheckingEnabledStateChanged(bool enabled) +{ + textCheckerState.isGrammarCheckingEnabled = enabled; +} + +int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy* page) +{ + return WebTextChecker::shared()->client().uniqueSpellDocumentTag(page); +} + +void TextChecker::closeSpellDocumentWithTag(int64_t tag) +{ + WebTextChecker::shared()->client().closeSpellDocumentWithTag(tag); +} + +void TextChecker::checkSpellingOfString(int64_t spellDocumentTag, const UChar* text, uint32_t length, int32_t& misspellingLocation, int32_t& misspellingLength) +{ + WebTextChecker::shared()->client().checkSpellingOfString(spellDocumentTag, String(text, length), misspellingLocation, misspellingLength); } -int64_t TextChecker::uniqueSpellDocumentTag() +void TextChecker::checkGrammarOfString(int64_t spellDocumentTag, const UChar* text, uint32_t length, Vector<WebCore::GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength) { - notImplemented(); - return 0; + WebTextChecker::shared()->client().checkGrammarOfString(spellDocumentTag, String(text, length), grammarDetails, badGrammarLocation, badGrammarLength); } -void TextChecker::closeSpellDocumentWithTag(int64_t) +bool TextChecker::spellingUIIsShowing() { - notImplemented(); + return WebTextChecker::shared()->client().spellingUIIsShowing(); } -Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, const UChar* text, int length, uint64_t checkingTypes) +void TextChecker::toggleSpellingUIIsShowing() { - notImplemented(); - return Vector<WebCore::TextCheckingResult>(); + WebTextChecker::shared()->client().toggleSpellingUIIsShowing(); } -void TextChecker::updateSpellingUIWithMisspelledWord(const String& misspelledWord) +void TextChecker::updateSpellingUIWithMisspelledWord(int64_t spellDocumentTag, const String& misspelledWord) { - notImplemented(); + WebTextChecker::shared()->client().updateSpellingUIWithMisspelledWord(spellDocumentTag, misspelledWord); } -void TextChecker::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +void TextChecker::updateSpellingUIWithGrammarString(int64_t spellDocumentTag, const String& badGrammarPhrase, const GrammarDetail& grammarDetail) { - notImplemented(); + WebTextChecker::shared()->client().updateSpellingUIWithGrammarString(spellDocumentTag, badGrammarPhrase, grammarDetail); } void TextChecker::getGuessesForWord(int64_t spellDocumentTag, const String& word, const String& context, Vector<String>& guesses) { - notImplemented(); + WebTextChecker::shared()->client().guessesForWord(spellDocumentTag, word, guesses); } -void TextChecker::learnWord(const String& word) +void TextChecker::learnWord(int64_t spellDocumentTag, const String& word) { - notImplemented(); + WebTextChecker::shared()->client().learnWord(spellDocumentTag, word); } void TextChecker::ignoreWord(int64_t spellDocumentTag, const String& word) { - notImplemented(); + WebTextChecker::shared()->client().ignoreWord(spellDocumentTag, word); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebContextWin.cpp b/Source/WebKit2/UIProcess/win/WebContextWin.cpp index d5fd859..c1c2a00 100644 --- a/Source/WebKit2/UIProcess/win/WebContextWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebContextWin.cpp @@ -48,9 +48,7 @@ void WebContext::setShouldPaintNativeControls(bool b) { m_shouldPaintNativeControls = b; - if (!hasValidProcess()) - return; - m_process->send(Messages::WebProcess::SetShouldPaintNativeControls(m_shouldPaintNativeControls), 0); + sendToAllProcesses(Messages::WebProcess::SetShouldPaintNativeControls(m_shouldPaintNativeControls)); } void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& parameters) diff --git a/Source/WebKit2/UIProcess/win/WebGrammarDetail.cpp b/Source/WebKit2/UIProcess/win/WebGrammarDetail.cpp new file mode 100644 index 0000000..8df528c --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebGrammarDetail.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebGrammarDetail.h" + +#include "ImmutableArray.h" +#include "WKGrammarDetail.h" +#include "WebString.h" + +namespace WebKit { + +PassRefPtr<WebGrammarDetail> WebGrammarDetail::create(int location, int length, ImmutableArray* guesses, const String& userDescription) +{ + return adoptRef(new WebGrammarDetail(location, length, guesses, userDescription)); +} + +PassRefPtr<WebGrammarDetail> WebGrammarDetail::create(const WebCore::GrammarDetail& grammarDetail) +{ + return adoptRef(new WebGrammarDetail(grammarDetail)); +} + +WebGrammarDetail::WebGrammarDetail(int location, int length, ImmutableArray* guesses, const String& userDescription) +{ + m_grammarDetail.location = location; + m_grammarDetail.length = length; + + size_t numGuesses = guesses->size(); + m_grammarDetail.guesses.reserveCapacity(numGuesses); + for (size_t i = 0; i < numGuesses; ++i) + m_grammarDetail.guesses.uncheckedAppend(guesses->at<WebString>(i)->string()); + + m_grammarDetail.userDescription = userDescription; +} + +PassRefPtr<ImmutableArray> WebGrammarDetail::guesses() const +{ + size_t numGuesses = m_grammarDetail.guesses.size(); + Vector<RefPtr<APIObject> > wkGuesses(numGuesses); + for (unsigned i = 0; i < numGuesses; ++i) + wkGuesses[i] = WebString::create(m_grammarDetail.guesses[i]); + return ImmutableArray::adopt(wkGuesses); +} + +WebGrammarDetail::WebGrammarDetail(const WebCore::GrammarDetail& grammarDetail) + : m_grammarDetail(grammarDetail) +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebGrammarDetail.h b/Source/WebKit2/UIProcess/win/WebGrammarDetail.h new file mode 100644 index 0000000..ff79b5c --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebGrammarDetail.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebGrammarDetail_h +#define WebGrammarDetail_h + +#include "APIObject.h" +#include <WebCore/TextCheckerClient.h> +#include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> + +namespace WebKit { + +class ImmutableArray; + +class WebGrammarDetail : public APIObject { +public: + static const Type APIType = TypeGrammarDetail; + static PassRefPtr<WebGrammarDetail> create(int location, int length, ImmutableArray* guesses, const String& userDescription); + static PassRefPtr<WebGrammarDetail> create(const WebCore::GrammarDetail&); + + int location() const { return m_grammarDetail.location; } + int length() const { return m_grammarDetail.length; } + PassRefPtr<ImmutableArray> guesses() const; + const String& userDescription() const { return m_grammarDetail.userDescription; } + + const WebCore::GrammarDetail& grammarDetail() { return m_grammarDetail; } + +private: + WebGrammarDetail(int location, int length, ImmutableArray* guesses, const String& userDescription); + WebGrammarDetail(const WebCore::GrammarDetail&); + + virtual Type type() const { return APIType; } + + WebCore::GrammarDetail m_grammarDetail; +}; + +} // namespace WebKit + +#endif // WebGrammarDetail_h diff --git a/Source/WebKit2/UIProcess/win/WebInspectorProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebInspectorProxyWin.cpp index 30b012e..ec5e91c 100644 --- a/Source/WebKit2/UIProcess/win/WebInspectorProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebInspectorProxyWin.cpp @@ -30,6 +30,7 @@ #include "WebKitBundle.h" #include "WebPageProxy.h" +#include "WebProcessProxy.h" #include "WebView.h" #include <WebCore/WebCoreInstanceHandle.h> #include <wtf/PassRefPtr.h> @@ -155,7 +156,7 @@ WebPageProxy* WebInspectorProxy::platformCreateInspectorPage() ASSERT(!m_inspectorWindow); RECT emptyRect = { 0 }; - m_inspectorView = WebView::create(emptyRect, m_page->context(), inspectorPageGroup(), 0); + m_inspectorView = WebView::create(emptyRect, m_page->process()->context(), inspectorPageGroup(), 0); return m_inspectorView->page(); } diff --git a/Source/WebKit2/UIProcess/win/WebPageProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebPageProxyWin.cpp index 1745a06..40a4cbb 100644 --- a/Source/WebKit2/UIProcess/win/WebPageProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebPageProxyWin.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "WebPageProxy.h" +#include "WebPopupMenuProxyWin.h" #include "resource.h" #include <tchar.h> @@ -54,4 +55,12 @@ String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationNameForUserAgent.isEmpty() ? "" : " ", applicationNameForUserAgent); } +void WebPageProxy::setPopupMenuSelectedIndex(int32_t selectedIndex) +{ + if (!m_activePopupMenu) + return; + + static_cast<WebPopupMenuProxyWin*>(m_activePopupMenu.get())->setFocusedIndex(selectedIndex); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp index eebde75..a8d8063 100644 --- a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "WebPopupMenuProxyWin.h" +#include "NativeWebMouseEvent.h" #include "WebView.h" #include <WebCore/WebCoreInstanceHandle.h> #include <WebCore/ScrollbarTheme.h> @@ -324,8 +325,26 @@ void WebPopupMenuProxyWin::showPopupMenu(const IntRect& rect, TextDirection, dou m_showPopup = false; ::ShowWindow(m_popup, SW_HIDE); - if (m_client) - m_client->valueChangedForPopupMenu(this, m_newSelectedIndex); + if (!m_client) + return; + + m_client->valueChangedForPopupMenu(this, m_newSelectedIndex); + + // <https://bugs.webkit.org/show_bug.cgi?id=57904> In order to properly call the onClick() + // handler on a <select> element, we need to fake a mouse up event in the main window. + // The main window already received the mouse down, which showed this popup, but upon + // selection of an item the mouse up gets eaten by the popup menu. So we take the mouse down + // event, change the message type to a mouse up event, and post that in the message queue. + // Thus, we are virtually clicking at the + // same location where the mouse down event occurred. This allows the hit test to select + // the correct element, and thereby call the onClick() JS handler. + if (!m_client->currentlyProcessedMouseDownEvent()) + return; + + const MSG* initiatingWinEvent = m_client->currentlyProcessedMouseDownEvent()->nativeEvent(); + MSG fakeEvent = *initiatingWinEvent; + fakeEvent.message = WM_LBUTTONUP; + ::PostMessage(fakeEvent.hwnd, fakeEvent.message, fakeEvent.wParam, fakeEvent.lParam); } void WebPopupMenuProxyWin::hidePopupMenu() diff --git a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h index 5a20edf..9d6d5b2 100644 --- a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h +++ b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h @@ -51,6 +51,8 @@ public: virtual void showPopupMenu(const WebCore::IntRect&, WebCore::TextDirection, double scaleFactor, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex); virtual void hidePopupMenu(); + bool setFocusedIndex(int index, bool hotTracking = false); + void hide() { hidePopupMenu(); } private: @@ -63,8 +65,10 @@ private: virtual int scrollPosition(WebCore::Scrollbar*) const; virtual void setScrollOffset(const WebCore::IntPoint&); virtual void invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect&); + virtual void invalidateScrollCornerRect(const WebCore::IntRect&) { } virtual bool isActive() const { return true; } - virtual bool scrollbarCornerPresent() const { return false; } + virtual bool isScrollCornerVisible() const { return false; } + virtual WebCore::IntRect scrollCornerRect() const { return WebCore::IntRect(); } virtual WebCore::Scrollbar* verticalScrollbar() const { return m_scrollbar.get(); } // NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea. @@ -107,7 +111,6 @@ private: void paint(const WebCore::IntRect& damageRect, HDC = 0); int visibleItems() const; int listIndexAtPoint(const WebCore::IntPoint&) const; - bool setFocusedIndex(int index, bool hotTracking = false); int focusedIndex() const; void focusFirst(); void focusLast(); diff --git a/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp new file mode 100644 index 0000000..1856b3b --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebProcessProxy.h" + +namespace WebKit { + +Vector<HWND> WebProcessProxy::windowsToReceiveSentMessagesWhileWaitingForSyncReply() +{ + return Vector<HWND>(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebTextChecker.cpp b/Source/WebKit2/UIProcess/win/WebTextChecker.cpp new file mode 100644 index 0000000..2761844 --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebTextChecker.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebTextChecker.h" + +#include "TextChecker.h" +#include "WKAPICast.h" +#include "WebContext.h" +#include <wtf/RefPtr.h> + +namespace WebKit { + +WebTextChecker* WebTextChecker::shared() +{ + static WebTextChecker* textChecker = adoptRef(new WebTextChecker).leakRef(); + return textChecker; +} + +WebTextChecker::WebTextChecker() +{ +} + +void WebTextChecker::setClient(const WKTextCheckerClient* client) +{ + m_client.initialize(client); +} + +static void updateStateForAllWebProcesses() +{ + const Vector<WebContext*>& contexts = WebContext::allContexts(); + for (size_t i = 0; i < contexts.size(); ++i) { + WebProcessProxy* webProcess = contexts[i]->process(); + if (!webProcess) + continue; + webProcess->updateTextCheckerState(); + } +} + +void WebTextChecker::continuousSpellCheckingEnabledStateChanged(bool enabled) +{ + TextChecker::continuousSpellCheckingEnabledStateChanged(enabled); + updateStateForAllWebProcesses(); +} + +void WebTextChecker::grammarCheckingEnabledStateChanged(bool enabled) +{ + TextChecker::grammarCheckingEnabledStateChanged(enabled); + updateStateForAllWebProcesses(); +} + +void WebTextChecker::checkSpelling(const WebPageProxy* page, bool startBeforeSelection) +{ + page->advanceToNextMisspelling(startBeforeSelection); +} + +void WebTextChecker::changeSpellingToWord(const WebPageProxy* page, const String& text) +{ + page->changeSpellingToWord(text); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebTextChecker.h b/Source/WebKit2/UIProcess/win/WebTextChecker.h new file mode 100644 index 0000000..a1c574c --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebTextChecker.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebTextChecker_h +#define WebTextChecker_h + +#include "APIObject.h" +#include "WKTextChecker.h" +#include "WebTextCheckerClient.h" +#include <wtf/Forward.h> + +namespace WebKit { + +class WebPageProxy; + +class WebTextChecker : public APIObject { +public: + static const Type APIType = TypeTextChecker; + + static WebTextChecker* shared(); + + void setClient(const WKTextCheckerClient*); + WebTextCheckerClient& client() { return m_client; } + + void continuousSpellCheckingEnabledStateChanged(bool); + void grammarCheckingEnabledStateChanged(bool); + + void checkSpelling(const WebPageProxy*, bool startBeforeSelection); + void changeSpellingToWord(const WebPageProxy*, const String&); + +private: + WebTextChecker(); + + virtual Type type() const { return APIType; } + + WebTextCheckerClient m_client; +}; + +} // namespace WebKit + +#endif // WebTextChecker_h diff --git a/Source/WebKit2/UIProcess/win/WebTextCheckerClient.cpp b/Source/WebKit2/UIProcess/win/WebTextCheckerClient.cpp new file mode 100644 index 0000000..86e52c6 --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebTextCheckerClient.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebTextCheckerClient.h" + +#include "ImmutableArray.h" +#include "WKAPICast.h" +#include "WKSharedAPICast.h" +#include "WebGrammarDetail.h" +#include "WebPageProxy.h" +#include <wtf/text/WTFString.h> + +namespace WebKit { + +bool WebTextCheckerClient::continuousSpellCheckingAllowed() +{ + if (!m_client.continuousSpellCheckingAllowed) + return false; + + return m_client.continuousSpellCheckingAllowed(m_client.clientInfo); +} + +bool WebTextCheckerClient::continuousSpellCheckingEnabled() +{ + if (!m_client.continuousSpellCheckingEnabled) + return false; + + return m_client.continuousSpellCheckingEnabled(m_client.clientInfo); +} + +void WebTextCheckerClient::setContinuousSpellCheckingEnabled(bool enabled) +{ + if (!m_client.setContinuousSpellCheckingEnabled) + return; + + m_client.setContinuousSpellCheckingEnabled(enabled, m_client.clientInfo); +} + +bool WebTextCheckerClient::grammarCheckingEnabled() +{ + if (!m_client.grammarCheckingEnabled) + return false; + + return m_client.grammarCheckingEnabled(m_client.clientInfo); +} + +void WebTextCheckerClient::setGrammarCheckingEnabled(bool enabled) +{ + if (!m_client.setGrammarCheckingEnabled) + return; + + m_client.setGrammarCheckingEnabled(enabled, m_client.clientInfo); +} + +uint64_t WebTextCheckerClient::uniqueSpellDocumentTag(WebPageProxy* page) +{ + if (!m_client.uniqueSpellDocumentTag) + return 0; + + return m_client.uniqueSpellDocumentTag(toAPI(page), m_client.clientInfo); +} + +void WebTextCheckerClient::closeSpellDocumentWithTag(uint64_t tag) +{ + if (!m_client.closeSpellDocumentWithTag) + return; + + m_client.closeSpellDocumentWithTag(tag, m_client.clientInfo); +} + +void WebTextCheckerClient::checkSpellingOfString(uint64_t tag, const String& text, int32_t& misspellingLocation, int32_t& misspellingLength) +{ + if (!m_client.checkSpellingOfString) + return; + + m_client.checkSpellingOfString(tag, toAPI(text.impl()), &misspellingLocation, &misspellingLength, m_client.clientInfo); +} + +void WebTextCheckerClient::checkGrammarOfString(uint64_t tag, const String& text, Vector<WebCore::GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength) +{ + if (!m_client.checkGrammarOfString) + return; + + WKArrayRef wkGrammarDetailsRef = 0; + m_client.checkGrammarOfString(tag, toAPI(text.impl()), &wkGrammarDetailsRef, &badGrammarLocation, &badGrammarLength, m_client.clientInfo); + + RefPtr<ImmutableArray> wkGrammarDetails = adoptRef(toImpl(wkGrammarDetailsRef)); + size_t numGrammarDetails = wkGrammarDetails->size(); + for (size_t i = 0; i < numGrammarDetails; ++i) + grammarDetails.append(wkGrammarDetails->at<WebGrammarDetail>(i)->grammarDetail()); +} + +bool WebTextCheckerClient::spellingUIIsShowing() +{ + if (!m_client.spellingUIIsShowing) + return false; + + return m_client.spellingUIIsShowing(m_client.clientInfo); +} + +void WebTextCheckerClient::toggleSpellingUIIsShowing() +{ + if (!m_client.toggleSpellingUIIsShowing) + return; + + return m_client.toggleSpellingUIIsShowing(m_client.clientInfo); +} + +void WebTextCheckerClient::updateSpellingUIWithMisspelledWord(uint64_t tag, const String& misspelledWord) +{ + if (!m_client.updateSpellingUIWithMisspelledWord) + return; + + m_client.updateSpellingUIWithMisspelledWord(tag, toAPI(misspelledWord.impl()), m_client.clientInfo); +} + +void WebTextCheckerClient::updateSpellingUIWithGrammarString(uint64_t tag, const String& badGrammarPhrase, const WebCore::GrammarDetail& grammarDetail) +{ + if (!m_client.updateSpellingUIWithGrammarString) + return; + + m_client.updateSpellingUIWithGrammarString(tag, toAPI(badGrammarPhrase.impl()), toAPI(grammarDetail), m_client.clientInfo); +} + +void WebTextCheckerClient::guessesForWord(uint64_t tag, const String& word, Vector<String>& guesses) +{ + if (!m_client.guessesForWord) + return; + + RefPtr<ImmutableArray> wkGuesses = adoptRef(toImpl(m_client.guessesForWord(tag, toAPI(word.impl()), m_client.clientInfo))); + size_t numGuesses = wkGuesses->size(); + for (size_t i = 0; i < numGuesses; ++i) + guesses.append(wkGuesses->at<WebString>(i)->string()); +} + +void WebTextCheckerClient::learnWord(uint64_t tag, const String& word) +{ + if (!m_client.learnWord) + return; + + m_client.learnWord(tag, toAPI(word.impl()), m_client.clientInfo); +} + +void WebTextCheckerClient::ignoreWord(uint64_t tag, const String& word) +{ + if (!m_client.ignoreWord) + return; + + m_client.ignoreWord(tag, toAPI(word.impl()), m_client.clientInfo); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebTextCheckerClient.h b/Source/WebKit2/UIProcess/win/WebTextCheckerClient.h new file mode 100644 index 0000000..50fb42d --- /dev/null +++ b/Source/WebKit2/UIProcess/win/WebTextCheckerClient.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebTextCheckerClient_h +#define WebTextCheckerClient_h + +#include "APIClient.h" +#include "WKTextChecker.h" +#include <WebCore/TextCheckerClient.h> +#include <wtf/Forward.h> +#include <wtf/Vector.h> + +namespace WebKit { + +class WebPageProxy; + +class WebTextCheckerClient : public APIClient<WKTextCheckerClient> { +public: + bool continuousSpellCheckingAllowed(); + bool continuousSpellCheckingEnabled(); + void setContinuousSpellCheckingEnabled(bool); + bool grammarCheckingEnabled(); + void setGrammarCheckingEnabled(bool); + uint64_t uniqueSpellDocumentTag(WebPageProxy*); + void closeSpellDocumentWithTag(uint64_t); + void checkSpellingOfString(uint64_t tag, const String& text, int32_t& misspellingLocation, int32_t& misspellingLength); + void checkGrammarOfString(uint64_t tag, const String& text, Vector<WebCore::GrammarDetail>&, int32_t& badGrammarLocation, int32_t& badGrammarLength); + bool spellingUIIsShowing(); + void toggleSpellingUIIsShowing(); + void updateSpellingUIWithMisspelledWord(uint64_t tag, const String& misspelledWord); + void updateSpellingUIWithGrammarString(uint64_t tag, const String& badGrammarPhrase, const WebCore::GrammarDetail&); + void guessesForWord(uint64_t tag, const String& word, Vector<String>& guesses); + void learnWord(uint64_t tag, const String& word); + void ignoreWord(uint64_t tag, const String& word); +}; + +} // namespace WebKit + +#endif // WebTextCheckerClient_h diff --git a/Source/WebKit2/UIProcess/win/WebUndoClient.cpp b/Source/WebKit2/UIProcess/win/WebUndoClient.cpp index 9bc96f5..9b86540 100644 --- a/Source/WebKit2/UIProcess/win/WebUndoClient.cpp +++ b/Source/WebKit2/UIProcess/win/WebUndoClient.cpp @@ -49,5 +49,21 @@ void WebUndoClient::clearAllEditCommands(WebView* view) m_client.clearAllEditCommands(toAPI(view), m_client.clientInfo); } +bool WebUndoClient::canUndoRedo(WebView* view, WebPageProxy::UndoOrRedo undoOrRedo) +{ + if (!m_client.canUndoRedo) + return false; + + return m_client.canUndoRedo(toAPI(view), undoOrRedo, m_client.clientInfo); +} + +void WebUndoClient::executeUndoRedo(WebView* view, WebPageProxy::UndoOrRedo undoOrRedo) +{ + if (!m_client.executeUndoRedo) + return; + + m_client.executeUndoRedo(toAPI(view), undoOrRedo, m_client.clientInfo); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebUndoClient.h b/Source/WebKit2/UIProcess/win/WebUndoClient.h index 12582c0..b7fdc15 100755 --- a/Source/WebKit2/UIProcess/win/WebUndoClient.h +++ b/Source/WebKit2/UIProcess/win/WebUndoClient.h @@ -39,6 +39,8 @@ class WebUndoClient : public APIClient<WKViewUndoClient> { public: void registerEditCommand(WebView*, PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); void clearAllEditCommands(WebView*); + bool canUndoRedo(WebView*, WebPageProxy::UndoOrRedo); + void executeUndoRedo(WebView*, WebPageProxy::UndoOrRedo); }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebView.cpp b/Source/WebKit2/UIProcess/win/WebView.cpp index 1447864..8cecb02 100644 --- a/Source/WebKit2/UIProcess/win/WebView.cpp +++ b/Source/WebKit2/UIProcess/win/WebView.cpp @@ -31,6 +31,7 @@ #include "FindIndicator.h" #include "Logging.h" #include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" #include "Region.h" #include "RunLoop.h" #include "WKAPICast.h" @@ -44,13 +45,14 @@ #include <WebCore/BitmapInfo.h> #include <WebCore/Cursor.h> #include <WebCore/FloatRect.h> -#if PLATFORM(CG) +#if USE(CG) #include <WebCore/GraphicsContextCG.h> #endif #include <WebCore/IntRect.h> #include <WebCore/SoftLinking.h> #include <WebCore/WebCoreInstanceHandle.h> #include <WebCore/WindowMessageBroadcaster.h> +#include <WebCore/WindowsTouch.h> #include <wtf/text/WTFString.h> namespace Ime { @@ -67,6 +69,17 @@ SOFT_LINK(IMM32, ImmNotifyIME, BOOL, WINAPI, (HIMC hIMC, DWORD dwAction, DWORD d SOFT_LINK(IMM32, ImmAssociateContextEx, BOOL, WINAPI, (HWND hWnd, HIMC hIMC, DWORD dwFlags), (hWnd, hIMC, dwFlags)) }; +// Soft link functions for gestures and panning. +SOFT_LINK_LIBRARY(USER32); +SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO)); +SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT)); +SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO)); + +SOFT_LINK_LIBRARY(Uxtheme); +SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND)); +SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL)); +SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL)); + using namespace WebCore; namespace WebKit { @@ -157,6 +170,12 @@ LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_VSCROLL: lResult = onVerticalScroll(hWnd, message, wParam, lParam, handled); break; + case WM_GESTURENOTIFY: + lResult = onGestureNotify(hWnd, message, wParam, lParam, handled); + break; + case WM_GESTURE: + lResult = onGesture(hWnd, message, wParam, lParam, handled); + break; case WM_SYSKEYDOWN: case WM_KEYDOWN: case WM_SYSCHAR: @@ -254,6 +273,10 @@ WebView::WebView(RECT rect, WebContext* context, WebPageGroup* pageGroup, HWND p , m_inIMEComposition(0) , m_findIndicatorCallback(0) , m_findIndicatorCallbackContext(0) + , m_lastPanX(0) + , m_lastPanY(0) + , m_overPanY(0) + , m_gestureReachedScrollingLimit(false) { registerWebViewWindowClass(); @@ -365,7 +388,7 @@ void WebView::windowAncestryDidChange() LRESULT WebView::onMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) { - WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(hWnd, message, wParam, lParam, m_wasActivatedByMouseEvent); + NativeWebMouseEvent mouseEvent = NativeWebMouseEvent(hWnd, message, wParam, lParam, m_wasActivatedByMouseEvent); setWasActivatedByMouseEvent(false); switch (message) { @@ -480,6 +503,109 @@ LRESULT WebView::onVerticalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM return 0; } +LRESULT WebView::onGestureNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) +{ + // We shouldn't be getting any gesture messages without SetGestureConfig soft-linking correctly. + ASSERT(SetGestureConfigPtr()); + + GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam); + + POINT localPoint = { gn->ptsLocation.x, gn->ptsLocation.y }; + ::ScreenToClient(m_window, &localPoint); + + bool canPan = m_page->gestureWillBegin(localPoint); + + DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER; + DWORD dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; + if (canPan) + dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; + else + dwPanBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; + + GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock }; + return SetGestureConfigPtr()(m_window, 0, 1, &gc, sizeof(gc)); +} + +LRESULT WebView::onGesture(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) +{ + ASSERT(GetGestureInfoPtr()); + ASSERT(CloseGestureInfoHandlePtr()); + ASSERT(UpdatePanningFeedbackPtr()); + ASSERT(BeginPanningFeedbackPtr()); + ASSERT(EndPanningFeedbackPtr()); + + if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr() || !UpdatePanningFeedbackPtr() || !BeginPanningFeedbackPtr() || !EndPanningFeedbackPtr()) { + handled = false; + return 0; + } + + HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam); + GESTUREINFO gi = {0}; + gi.cbSize = sizeof(GESTUREINFO); + + if (!GetGestureInfoPtr()(gestureHandle, &gi)) { + handled = false; + return 0; + } + + switch (gi.dwID) { + case GID_BEGIN: + m_lastPanX = gi.ptsLocation.x; + m_lastPanY = gi.ptsLocation.y; + break; + case GID_END: + m_page->gestureDidEnd(); + break; + case GID_PAN: { + int currentX = gi.ptsLocation.x; + int currentY = gi.ptsLocation.y; + + // Reverse the calculations because moving your fingers up should move the screen down, and + // vice-versa. + int deltaX = m_lastPanX - currentX; + int deltaY = m_lastPanY - currentY; + + m_lastPanX = currentX; + m_lastPanY = currentY; + + // Calculate the overpan for window bounce. + m_overPanY -= deltaY; + + if (deltaX || deltaY) + m_page->gestureDidScroll(IntSize(deltaX, deltaY)); + + if (gi.dwFlags & GF_BEGIN) { + BeginPanningFeedbackPtr()(m_window); + m_gestureReachedScrollingLimit = false; + m_overPanY = 0; + } else if (gi.dwFlags & GF_END) { + EndPanningFeedbackPtr()(m_window, true); + m_overPanY = 0; + } + + // FIXME: Support horizontal window bounce - <http://webkit.org/b/58068>. + // FIXME: Window Bounce doesn't undo until user releases their finger - <http://webkit.org/b/58069>. + + if (m_gestureReachedScrollingLimit) + UpdatePanningFeedbackPtr()(m_window, 0, m_overPanY, gi.dwFlags & GF_INERTIA); + + CloseGestureInfoHandlePtr()(gestureHandle); + + handled = true; + return 0; + } + default: + break; + } + + // If we get to this point, the gesture has not been handled. We forward + // the call to DefWindowProc by returning false, and we don't need to + // to call CloseGestureInfoHandle. + // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx + handled = false; + return 0; +} + LRESULT WebView::onKeyEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) { m_page->handleKeyboardEvent(NativeWebKeyboardEvent(hWnd, message, wParam, lParam)); @@ -565,8 +691,22 @@ LRESULT WebView::onPrintClientEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool RECT winRect; ::GetClientRect(hWnd, &winRect); + // Twidding the visibility flags tells the DrawingArea to resume painting. Right now, the + // the visible state of the view only affects whether or not painting happens, but in the + // future it could affect more, which we wouldn't want to touch here. + + // FIXME: We should have a better way of telling the WebProcess to draw even if we're + // invisible than twiddling the visibility flag. + + bool wasVisible = isViewVisible(); + if (!wasVisible) + setIsVisible(true); + paint(hdc, winRect); + if (!wasVisible) + setIsVisible(false); + handled = true; return 0; } @@ -626,11 +766,8 @@ LRESULT WebView::onShowWindowEvent(HWND hWnd, UINT message, WPARAM wParam, LPARA // lParam is 0 when the message is sent because of a ShowWindow call. // FIXME: Since we don't get notified when an ancestor window is hidden or shown, we will keep // painting even when we have a hidden ancestor. <http://webkit.org/b/54104> - if (!lParam) { - m_isVisible = wParam; - if (m_page) - m_page->viewStateDidChange(WebPageProxy::ViewIsVisible); - } + if (!lParam) + setIsVisible(wParam); handled = false; return 0; @@ -760,6 +897,15 @@ void WebView::close() { m_undoClient.initialize(0); ::RevokeDragDrop(m_window); + if (m_window) { + // We can't check IsWindow(m_window) here, because that will return true even while + // we're already handling WM_DESTROY. So we check !m_isBeingDestroyed instead. + if (!m_isBeingDestroyed) + DestroyWindow(m_window); + // Either we just destroyed m_window, or it's in the process of being destroyed. Either + // way, we clear it out to make sure we don't try to use it later. + m_window = 0; + } setParentWindow(0); m_page->close(); } @@ -844,10 +990,6 @@ void WebView::didRelaunchProcess() ::InvalidateRect(m_window, 0, TRUE); } -void WebView::takeFocus(bool) -{ -} - void WebView::toolTipChanged(const String&, const String& newToolTip) { if (!m_toolTipWindow) @@ -929,6 +1071,16 @@ void WebView::clearAllEditCommands() m_undoClient.clearAllEditCommands(this); } +bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) +{ + return m_undoClient.canUndoRedo(this, undoOrRedo); +} + +void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) +{ + m_undoClient.executeUndoRedo(this, undoOrRedo); +} + void WebView::reapplyEditCommand(WebEditCommandProxy* command) { if (!m_page->isValid() || !m_page->isValidEditCommand(command)) @@ -996,7 +1148,7 @@ void WebView::setInputMethodState(bool enabled) void WebView::compositionSelectionChanged(bool hasChanged) { - if (m_page->selectionState().hasComposition && !hasChanged) + if (m_page->editorState().hasComposition && !hasChanged) resetIME(); } @@ -1104,7 +1256,7 @@ bool WebView::onIMEComposition(LPARAM lparam) if (!hInputContext) return true; - if (!m_page->selectionState().isContentEditable) + if (!m_page->editorState().isContentEditable) return true; prepareCandidateWindow(hInputContext); @@ -1147,7 +1299,7 @@ bool WebView::onIMEEndComposition() LOG(TextInput, "onIMEEndComposition"); // If the composition hasn't been confirmed yet, it needs to be cancelled. // This happens after deleting the last character from inline input hole. - if (m_page->selectionState().hasComposition) + if (m_page->editorState().hasComposition) m_page->confirmComposition(String()); if (m_inIMEComposition) @@ -1158,7 +1310,7 @@ bool WebView::onIMEEndComposition() LRESULT WebView::onIMERequestCharPosition(IMECHARPOSITION* charPos) { - if (charPos->dwCharPos && !m_page->selectionState().hasComposition) + if (charPos->dwCharPos && !m_page->editorState().hasComposition) return 0; IntRect caret = m_page->firstRectForCharacterInSelectedRange(charPos->dwCharPos); charPos->pt.x = caret.x(); @@ -1190,7 +1342,7 @@ LRESULT WebView::onIMERequestReconvertString(RECONVERTSTRING* reconvertString) LRESULT WebView::onIMERequest(WPARAM request, LPARAM data) { LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data()); - if (!m_page->selectionState().isContentEditable) + if (!m_page->editorState().isContentEditable) return 0; switch (request) { @@ -1254,7 +1406,7 @@ void WebView::setFindIndicator(PassRefPtr<FindIndicator> prpFindIndicator, bool hbmp = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, static_cast<void**>(&bits), 0, 0); HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc, hbmp)); -#if PLATFORM(CG) +#if USE(CG) RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(bits, width, height, 8, width * sizeof(RGBQUAD), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); @@ -1310,12 +1462,28 @@ void WebView::didChangeScrollbarsForMainFrame() const { } +void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned) +{ +} + +void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned) +{ +} + void WebView::setIsInWindow(bool isInWindow) { m_isInWindow = isInWindow; m_page->viewStateDidChange(WebPageProxy::ViewIsInWindow); } +void WebView::setIsVisible(bool isVisible) +{ + m_isVisible = isVisible; + + if (m_page) + m_page->viewStateDidChange(WebPageProxy::ViewIsVisible); +} + #if USE(ACCELERATED_COMPOSITING) void WebView::enterAcceleratedCompositingMode(const LayerTreeContext&) @@ -1425,7 +1593,7 @@ HRESULT STDMETHODCALLTYPE WebView::DragEnter(IDataObject* pDataObject, DWORD grf POINTL localpt = pt; ::ScreenToClient(m_window, (LPPOINT)&localpt); DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); - m_page->performDragControllerAction(DragControllerActionEntered, &data); + m_page->dragEntered(&data); *pdwEffect = dragOperationToDragCursor(m_page->dragOperation()); m_lastDropEffect = *pdwEffect; @@ -1443,7 +1611,7 @@ HRESULT STDMETHODCALLTYPE WebView::DragOver(DWORD grfKeyState, POINTL pt, DWORD* POINTL localpt = pt; ::ScreenToClient(m_window, (LPPOINT)&localpt); DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); - m_page->performDragControllerAction(DragControllerActionUpdated, &data); + m_page->dragUpdated(&data); *pdwEffect = dragOperationToDragCursor(m_page->dragOperation()); } else *pdwEffect = DROPEFFECT_NONE; @@ -1459,7 +1627,7 @@ HRESULT STDMETHODCALLTYPE WebView::DragLeave() if (m_dragData) { DragData data(m_dragData.get(), IntPoint(), IntPoint(), DragOperationNone); - m_page->performDragControllerAction(DragControllerActionExited, &data); + m_page->dragExited(&data); m_dragData = 0; m_page->resetDragOperation(); } @@ -1476,7 +1644,9 @@ HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeySt POINTL localpt = pt; ::ScreenToClient(m_window, (LPPOINT)&localpt); DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); - m_page->performDragControllerAction(DragControllerActionPerformDrag, &data); + + SandboxExtension::Handle sandboxExtensionHandle; + m_page->performDrag(&data, String(), sandboxExtensionHandle); return S_OK; } diff --git a/Source/WebKit2/UIProcess/win/WebView.h b/Source/WebKit2/UIProcess/win/WebView.h index 1d65179..d62311c 100644 --- a/Source/WebKit2/UIProcess/win/WebView.h +++ b/Source/WebKit2/UIProcess/win/WebView.h @@ -60,6 +60,7 @@ public: void setParentWindow(HWND); void windowAncestryDidChange(); void setIsInWindow(bool); + void setIsVisible(bool); void setOverrideCursor(HCURSOR); void setInitialFocus(bool forward); void setScrollOffsetOnNextResize(const WebCore::IntSize&); @@ -97,6 +98,8 @@ private: LRESULT onWheelEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); LRESULT onHorizontalScroll(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); LRESULT onVerticalScroll(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); + LRESULT onGestureNotify(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); + LRESULT onGesture(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); LRESULT onKeyEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); LRESULT onPaintEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); LRESULT onPrintClientEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled); @@ -154,13 +157,13 @@ private: virtual void processDidCrash(); virtual void didRelaunchProcess(); virtual void pageClosed(); - virtual void takeFocus(bool direction); - virtual void setFocus(bool focused) { } virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void setCursor(const WebCore::Cursor&); virtual void setViewportArguments(const WebCore::ViewportArguments&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); + virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); + virtual void executeUndoRedo(WebPageProxy::UndoOrRedo); virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&); @@ -182,8 +185,13 @@ private: WebCore::DragOperation keyStateToDragOperation(DWORD grfKeyState) const; virtual void didChangeScrollbarsForMainFrame() const; + virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount); + virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned maxMatchCount); + virtual HWND nativeWindow(); + virtual void setGestureReachedScrollingLimit(bool limitReached) { m_gestureReachedScrollingLimit = limitReached; } + // WebCore::WindowMessageListener virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM); @@ -219,6 +227,13 @@ private: // Thus, on return from DoDragDrop we have the correct pdwEffect for the drag-and-drop operation. // (see https://bugs.webkit.org/show_bug.cgi?id=29264) DWORD m_lastDropEffect; + + int m_lastPanX; + int m_lastPanY; + + int m_overPanY; + + bool m_gestureReachedScrollingLimit; }; } // namespace WebKit |